Merge branch 'master' into weeklyDaily

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

@ -32,3 +32,32 @@ steps:
sonar_host: https://codefirst.iut.uca.fr/sonar/ sonar_host: https://codefirst.iut.uca.fr/sonar/
sonar_token: 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 package-lock.json
# db # db
socialgraph.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 #!/bin/sh
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null; then if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null; then
# Tuer le processus associé au port # Tuer le processus associé au port
pid=$(lsof -Pi :3000 -sTCP:LISTEN -t) pid=$(lsof -Pi :3000 -sTCP:LISTEN -t)
@ -23,8 +25,8 @@ fi
npm start & 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": "^4.18.2",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jspdf": "^2.5.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
@ -4593,6 +4594,12 @@
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz",
"integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==" "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": { "node_modules/@types/range-parser": {
"version": "1.2.6", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz",
@ -5732,6 +5739,17 @@
"node": ">= 4.0.0" "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": { "node_modules/autoprefixer": {
"version": "10.4.16", "version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", "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", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" "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": { "node_modules/base64id": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@ -6336,6 +6363,17 @@
"node-int64": "^0.4.0" "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": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "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": { "node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", "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" "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": { "node_modules/css-loader": {
"version": "6.8.1", "version": "6.8.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", "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" "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": { "node_modules/domutils": {
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@ -9184,6 +9262,11 @@
"bser": "2.1.1" "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": { "node_modules/file-entry-cache": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -10095,6 +10178,19 @@
"webpack": "^5.20.0" "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": { "node_modules/htmlparser2": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
@ -13025,6 +13121,23 @@
"node": ">=0.10.0" "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": { "node_modules/jsx-ast-utils": {
"version": "3.3.5", "version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@ -16913,6 +17026,15 @@
"node": ">=0.10.0" "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": { "node_modules/rimraf": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@ -17728,6 +17850,15 @@
"node": ">=8" "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": { "node_modules/stackframe": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "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", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" "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": { "node_modules/svgo": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@ -18480,6 +18620,15 @@
"node": ">=8" "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": { "node_modules/text-table": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -19049,6 +19198,15 @@
"node": ">= 0.4.0" "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": { "node_modules/uuid": {
"version": "9.0.1", "version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",

@ -17,6 +17,7 @@
"express": "^4.18.2", "express": "^4.18.2",
"express-session": "^1.17.3", "express-session": "^1.17.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jspdf": "^2.5.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.2.0", "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(); 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; module.exports = AuthController;

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

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

@ -7,12 +7,14 @@ const app = express();
const server = http.createServer(app); const server = http.createServer(app);
const io = socketIO(server, { const io = socketIO(server, {
cors: { 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"], methods: ["GET", "POST"],
credentials: true credentials: true
} }
}); });
let lastSocketJoined = ""
const map = new Map() const map = new Map()
server.listen(3002, () => { server.listen(3002, () => {
@ -24,18 +26,61 @@ io.on('connection', (socket) => {
socket.on('network created', (network, person, indices, room, start) =>{ socket.on('network created', (network, person, indices, room, start) =>{
io.to(room).emit("game created", network, person, indices, 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) =>{ socket.on("lobby joined", (room, player) =>{
console.log(player)
if (player.type=="User"){ 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) socket.join(room)
return
}
} }
if (map.get(room) == undefined){ io.to(socket.id).emit("game already started")
map.set(room, [{type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture}]) return
}
}
if (game == undefined){
map.set(room, {tab: [{type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture}], started: false, actualPlayer: 0, lastWorks: false})
socket.join(room)
} }
else{ else{
const tab = map.get(room) const tab = game.tab
for(let i = 0; i<tab.length; i++){ for(let i = 0; i<tab.length; i++){
if (tab[i].id === socket.id && player.type==="User"){ if (tab[i].id === socket.id && player.type==="User"){
tab.splice(i, 1) tab.splice(i, 1)
@ -43,25 +88,39 @@ io.on('connection', (socket) => {
} }
if (player.type!=="User"){ 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{ 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)) 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) =>{ 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++){ for(let i = 0; i<tab.length; i++){
if (tab[i].id === bot.id){ if (tab[i].id === bot.id){
tab.splice(i, 1) tab.splice(i, 1)
} }
} }
io.to(room).emit("new player", map.get(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)
}) })
@ -85,19 +144,80 @@ io.on('connection', (socket) => {
io.to(askingPlayer.id).emit("asked wrong") 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", () =>{ socket.on("disconnect", () =>{
for (const k of map.keys()){ for (const k of map.keys()){
const tab = map.get(k) const tab = map.get(k)
for (let i = 0; i<tab.length; i++){ for (let i = 0; i<tab.tab.length; i++){
if (tab[i].id === socket.id){ if (tab.tab[i].id === socket.id){
tab.splice(i, 1) if (!tab.started){
tab.tab.splice(i, 1)
if (i==0){
tab.tab.sort(comparePlayersByType).reverse()
}
io.to(k).emit("player left", tab, i) 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) =>{ 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) 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") 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) => { socket.on("opacity activated", (id) => {
io.to(id).emit("opacity activated") io.to(id).emit("opacity activated")
}) })
@ -127,5 +251,17 @@ io.on('connection', (socket) => {
socket.on("end game", (winnerIndex, room) =>{ socket.on("end game", (winnerIndex, room) =>{
io.to(room).emit("end game", winnerIndex) 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 ADRESSE_DBSERVER = "http://localhost:3003"
const tmp = ADRESSE_DBSERVER
const tmp2 = ADRESSE_WEBSERVER
const ADRESSE_WEBSITE = "" const ADRESSE_WEBSITE = ""
export {ADRESSE_DBSERVER, ADRESSE_WEBSERVER, ADRESSE_WEBSITE} export {ADRESSE_DBSERVER, ADRESSE_WEBSERVER, ADRESSE_WEBSITE}

@ -15,7 +15,8 @@ import Lobby from './Pages/Lobby';
import InGame from './Pages/InGame'; import InGame from './Pages/InGame';
import EndGame from './Pages/EndGame'; import EndGame from './Pages/EndGame';
import InfoPage from './Pages/InfoPage'; import InfoPage from './Pages/InfoPage';
import SoloGame from './Pages/SoloGame';
import DeducGrid from './Pages/DeducGrid';
import Lobbies from './Pages/Lobbies'; import Lobbies from './Pages/Lobbies';
/* Component */ /* Component */
@ -40,6 +41,11 @@ import 'bootstrap/dist/css/bootstrap.min.css';
import messagesFr from './Translations/fr.json'; import messagesFr from './Translations/fr.json';
import messagesEn from './Translations/en.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 = { const messages = {
fr: messagesFr, fr: messagesFr,
en: messagesEn, en: messagesEn,
@ -58,17 +64,11 @@ function App() {
//const location = useLocation(); //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 ( return (
// <div className="App"> <ErrorBoundary fallback={(error, errorInfo) => <ErrorPage />}>
// <header className="App-header">
// <Home />
// <img src={logo} className="App-logo" alt="logo" />
// </header>
// </div>
<AuthProvider> <AuthProvider>
<GameProvider> <GameProvider>
{/*@ts-ignore*/} {/*@ts-ignore*/}
@ -80,20 +80,24 @@ function App() {
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} /> <Route path="/signup" element={<SignUp />} />
<Route path="/play" element={<Play/>} /> <Route path="/play" element={<NewPlay/>} />
<Route path="/lobby" element={<Lobby/>} /> <Route path="/lobby" element={<Lobby/>} />
<Route path="/endgame" element={<EndGame/>} /> <Route path="/endgame" element={<EndGame/>} />
<Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/> <Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/>
<Route path="/info" element={<InfoPage 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="/profile" element={<Profile/>} />
<Route path="/join" element={<Lobbies/>}/> <Route path="/join" element={<Lobbies/>}/>
{/* <Route path="/solo" element={<SoloGame locale={locale} changeLocale={changeLocale} />}/> */} {/* <Route path="/solo" element={<SoloGame locale={locale} changeLocale={changeLocale} />}/> */}
<Route path="*" element={<ErrorPage code="404" msg='not found' />} /> {/* page 404 */}
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
</ThemeProvider> </ThemeProvider>
</IntlProvider> </IntlProvider>
</GameProvider> </GameProvider>
</AuthProvider> </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 { useAuth } from "../Contexts/AuthContext";
import Indice from "../model/Indices/Indice"; import Indice from "../model/Indices/Indice";
import Pair from "../model/Pair"; 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 { interface MyGraphComponentProps {
onNodeClick: (shouldShowChoiceBar: boolean) => void; onNodeClick: (shouldShowChoiceBar: boolean) => void;
handleShowTurnBar: (shouldShowTurnBar: boolean) => void handleShowTurnBar: (shouldShowTurnBar: boolean) => void
@ -29,13 +35,17 @@ interface MyGraphComponentProps {
setNetwork: (network: Network) => void setNetwork: (network: Network) => void
showLast: boolean showLast: boolean
setNetworkEnigme: (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => void setNetworkEnigme: (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => void
askedWrong: boolean
setAskedWrong: (askedWrong: boolean) => void
setPlayerIndex: (playerIndex: number) => void setPlayerIndex: (playerIndex: number) => void
importToPdf: boolean
setImportToPdf: (imp: boolean) => void
} }
let lastAskingPlayer = 0 let lastAskingPlayer = 0
let lastNodeId = -1 let lastNodeId = -1
let first = true let first = true
let askedWrong = false let askedWrongLocal = false
let mapIndexPersons: Map<number, Person[]> = new Map<number, Person[]>() let mapIndexPersons: Map<number, Person[]> = new Map<number, Person[]>()
let touchedPlayer = -1 let touchedPlayer = -1
let botIndex = -1 let botIndex = -1
@ -49,16 +59,23 @@ let firstEnigme = true
let firstIndex = true let firstIndex = true
let endgame= false let endgame= false
let firstHistory = true 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 let cptTour: number = 0
//* Gestion du temps : //* Gestion du temps :
let initMtn = 0 let initMtn = 0
const {isLoggedIn, user, manager} = useAuth(); 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 params = new URLSearchParams(window.location.search);
const navigate = useNavigate(); const navigate = useNavigate();
@ -72,6 +89,13 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
setElapsedTime((prevElapsedTime) => prevElapsedTime + 0.5); setElapsedTime((prevElapsedTime) => prevElapsedTime + 0.5);
settempsData(elapsedTime) 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 // Vérifiez si la durée est écoulée, puis arrêtez le timer
if (endgame) { if (endgame) {
clearInterval(intervalId); clearInterval(intervalId);
@ -83,15 +107,21 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}, [elapsedTime, endgame]); }, [elapsedTime, endgame]);
useEffect(() => {
testPlayers = players
console.log(testPlayers)
}, [players])
useEffect(() =>{ useEffect(() =>{
touchedPlayer=playerTouched touchedPlayer=playerTouched
console.log(playerTouched)
if (touchedPlayer == -1){ if (touchedPlayer == -1){
if (!askedWrong){ if (!askedWrongLocal){
socket.emit("put correct background", socket.id) socket.emit("put correct background", socket.id)
} }
} }
else if (touchedPlayer < players.length && touchedPlayer>=0){ else if (touchedPlayer < players.length && touchedPlayer>=0){
if(!askedWrong){ if(!askedWrongLocal){
socket.emit("put correct background", socket.id) socket.emit("put correct background", socket.id)
socket.emit("put grey background", socket.id, touchedPlayer) socket.emit("put grey background", socket.id, touchedPlayer)
} }
@ -136,8 +166,9 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
useEffect(() =>{ useEffect(() =>{
if (actualPlayerIndex==0){ cptBug=0
const bot = players[lastIndex] if (actualPlayerIndex==firstPlayer){
const bot = testPlayers[lastIndex]
if(bot instanceof Bot && botIndex != lastIndex){ if(bot instanceof Bot && botIndex != lastIndex){
botIndex = lastIndex botIndex = lastIndex
if (personNetwork!=null){ if (personNetwork!=null){
@ -161,7 +192,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
const tester = IndiceTesterFactory.Create(indices[playerIndex]) const tester = IndiceTesterFactory.Create(indices[playerIndex])
const works = tester.Works(person) 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){ if (i==players.length){
socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex) socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex)
} }
@ -170,7 +201,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
if(!works){ if(!works){
socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex) 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()) console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1 playerIndex = lastIndex + 1
if(playerIndex == players.length){ if(playerIndex == players.length){
@ -185,7 +220,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
else{ else{
if (person!=undefined){ if (person!=undefined){
if (players[choosedPlayerIndex] instanceof Bot){ if (testPlayers[choosedPlayerIndex] instanceof Bot){
console.log("BOT") console.log("BOT")
const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex]) const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex])
const works = tester.Works(person) const works = tester.Works(person)
@ -200,7 +235,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
else{ else{
console.log(lastIndex + " interroge " + choosedPlayerIndex + " a propos de " + person.getName() + " et dit non") console.log(lastIndex + " interroge " + choosedPlayerIndex + " a propos de " + person.getName() + " et dit non")
socket.emit("node checked", personIndex, false, choosedPlayerIndex, room, lastIndex) 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()) console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1 playerIndex = lastIndex + 1
if(playerIndex == players.length){ if(playerIndex == players.length){
@ -211,11 +250,15 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
else{ else{
console.log(choosedPlayerIndex + " => Pas bot" ) 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()) console.log(lastIndex + " interroge " + +choosedPlayerIndex + " sur " + personNetwork.getPersons()[personIndex].getName())
const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex]) const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex])
if (!tester.Works(person)){ 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()) console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1 playerIndex = lastIndex + 1
if(playerIndex == players.length){ if(playerIndex == players.length){
@ -256,18 +299,24 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
} }
//* fonction qui reinitialise le graphe useEffect(() => {
const resGraph = () => { //? comment accéder au nework ?? if (importToPdf){
const savedGraphStateString = localStorage.getItem('graphState'); setImportToPdf(false)
if (savedGraphStateString !== null) { const graphContainer = document.getElementById("graph-container");
const savedGraphState = JSON.parse(savedGraphStateString); if (graphContainer == null){
//network.setData(savedGraphState); return
} else {
// La clé 'graphState' n'existe pas dans le localStorage, prenez une action en conséquence.
console.log("ayoooooo");
} }
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(() => { useEffect(() => {
if (personNetwork == null){ if (personNetwork == null){
@ -288,7 +337,10 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
return; return;
} }
// Charger les données dans le graph // 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 // Configuration des options du Graphe
const initialOptions = { 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 direction: 'LR', // LR (Left to Right) ou autre selon votre préférence
sortMethod: 'hubsize' sortMethod: 'hubsize'
}, },
distanceMin: 500, // Set the minimum distance between nodes
//randomSeed: 2 //randomSeed: 2
}, },
physics: { 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", () => { socket.on("reset graph", () => {
console.log("reset graph") console.log("reset graph")
initialOptions.physics.enabled = true initialOptions.physics.enabled = true
@ -356,6 +484,16 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}) })
if (!solo){ if (!solo){
socket.on("who plays", (index) => {
playerIndex=index
setPlayerIndex(index)
setLastIndex(index)
if (actualPlayerIndex==index){
handleShowTurnBar(true)
}
})
socket.on("asked all", (id) =>{ socket.on("asked all", (id) =>{
//@ts-ignore //@ts-ignore
const pers = personNetwork.getPersons().find((p) => p.getId() == id) 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) => { socket.on("node checked",(id, works, askedIndex, newPlayerIndex, socketId) => {
cptBug=0
//@ts-ignore //@ts-ignore
const node = nodes.get().find((n) => id == n.id) const node = nodes.get().find((n) => id == n.id)
if (node!=undefined){ if (node!=undefined){
onNodeClick(false) onNodeClick(false)
playerIndex = newPlayerIndex playerIndex = newPlayerIndex
setPlayerIndex(playerIndex) setPlayerIndex(playerIndex)
setLastIndex(newPlayerIndex)
console.log(newPlayerIndex)
//@ts-ignore //@ts-ignore
if (mapIndexPersons.get(askedIndex)?.find((p) => p.getId() == id) == undefined){ if (mapIndexPersons.get(askedIndex)?.find((p) => p.getId() == id) == undefined){
//@ts-ignore //@ts-ignore
@ -396,7 +537,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
if (p!=undefined && tab != undefined){ if (p!=undefined && tab != undefined){
tab.push(p) tab.push(p)
if (actualPlayerIndex == 0){ if (actualPlayerIndex == 0){
players.forEach((player) => { testPlayers.forEach((player) => {
if (player instanceof Bot){ if (player instanceof Bot){
player.newInformation(p, askedIndex, works) player.newInformation(p, askedIndex, works)
} }
@ -410,7 +551,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
cptHistory++ cptHistory++
if (cptHistory % 2 == 0){ if (cptHistory % 2 == 0){
lastNodes.push(node) 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", () =>{ socket.on("asked wrong", () =>{
askedWrong = true 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 askedWrongBot=true
handleShowTurnBar(true) handleShowTurnBar(true)
handleTurnBarTextChange("Mauvais choix, posez un carré !") handleTurnBarTextChange("Mauvais choix, posez un carré !")
socket.emit("put grey background", socket.id, actualPlayerIndex) 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) => { socket.on("asked", (nodeId, askingPlayer) => {
if (askingPlayer.id !== lastAskingPlayer || nodeId !== lastNodeId ){ if (askingPlayer.id !== lastAskingPlayer || nodeId !== lastNodeId ){
lastAskingPlayer = askingPlayer.id lastAskingPlayer = askingPlayer.id
lastNodeId = nodeId lastNodeId = nodeId
@ -458,7 +651,6 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
const node = nodes.get().find((n) => nodeId == n.id) const node = nodes.get().find((n) => nodeId == n.id)
if (node != undefined && indice != null){ if (node != undefined && indice != null){
var tester = IndiceTesterFactory.Create(indice) var tester = IndiceTesterFactory.Create(indice)
let maybe = actualPlayerIndex
if (tester.Works(pers)){ if (tester.Works(pers)){
playerIndex = playerIndex + 1 playerIndex = playerIndex + 1
if(playerIndex == players.length){ if(playerIndex == players.length){
@ -467,13 +659,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("node checked", nodeId, true, actualPlayerIndex, room, playerIndex) socket.emit("node checked", nodeId, true, actualPlayerIndex, room, playerIndex)
} }
else{ else{
maybe = actualPlayerIndex - 1 let index = testPlayers.findIndex((p) => p.id == askingPlayer.id)
if(maybe == 0){ if (testPlayers[index] instanceof Bot){
maybe = players.length - 1
}
//@ts-ignore
let index = players.findIndex((p) => p.id == askingPlayer.id)
if (players[index] instanceof Bot){
index = playerIndex + 1 index = playerIndex + 1
if(index == players.length){ if(index == players.length){
index = 0 index = 0
@ -519,13 +706,25 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
} }
else if(indice != null){ else if(indice != null){
//Pour poser un carré
const tester = IndiceTesterFactory.Create(indice) const tester = IndiceTesterFactory.Create(indice)
for(const person of personNetwork.getPersons().filter((p) => tab.includes(p) || tester.Works(p))){ 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"}) networkData.nodes.update({id: person.getId(), color: "#808080"})
} }
} }
} }
} }
}
}) })
socket.on("put imossible grey", ()=>{ socket.on("put imossible grey", ()=>{
@ -567,10 +766,12 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
first = true first = true
cptHistory = 0 cptHistory = 0
askedWrong=false askedWrongLocal=false
setAskedWrong(false)
askedWrongBot=false askedWrongBot=false
endgame = true endgame = true
firstHistory=true firstHistory=true
cptBug=0
try{ try{
if(isLoggedIn){ if(isLoggedIn){
if(!solo){ if(!solo){
@ -606,6 +807,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.off("put correct background") socket.off("put correct background")
socket.off("put grey background") socket.off("put grey background")
socket.off("put imossible grey") socket.off("put imossible grey")
socket.off("who plays")
navigate("/endgame") navigate("/endgame")
} }
@ -624,7 +826,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
if (a==indices.length){ if (a==indices.length){
//networkData.nodes.update({id: p.getId(), label: p.getName() + "\n🔵"}) //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) => { network.on("click", async (params) => {
if(params.nodes.length > 0){ if(params.nodes.length > 0){
console.log(touchedPlayer)
setNodeIdData(params.nodes[0]) setNodeIdData(params.nodes[0])
console.log(players)
// addToHistory("Le joueur a cliqué") //! TEST DEBUG // addToHistory("Le joueur a cliqué") //! TEST DEBUG
if (!solo){ if (!solo){
if (askedWrong){ if (askedWrongLocal){
//@ts-ignore
const person = personNetwork?.getPersons().find((p) => p.getId() == params.nodes[0]) 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) 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 playerIndex = actualPlayerIndex + 1
if(playerIndex == players.length){ if(playerIndex == players.length){
playerIndex = 0 playerIndex = 0
@ -660,13 +871,16 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("put correct background", socket.id) socket.emit("put correct background", socket.id)
touchedPlayer=-1 touchedPlayer=-1
askedPersons.push(person) askedPersons.push(person)
askedWrong = false askedWrongLocal=false
setAskedWrong(false)
} }
} }
} }
else if(touchedPlayer != -1 && playerIndex == actualPlayerIndex && touchedPlayer<players.length){ else if(touchedPlayer != -1 && playerIndex == actualPlayerIndex && touchedPlayer<players.length){
botIndex = -1 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 ind = indices[touchedPlayer]
const test = IndiceTesterFactory.Create(ind) const test = IndiceTesterFactory.Create(ind)
//@ts-ignore //@ts-ignore
@ -688,8 +902,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
} }
} }
else{ else{
if (touchedPlayer > 0){ if (touchedPlayer >= 0){
console.log(touchedPlayer) console.log("CE N'EST PAS UN BOT")
//@ts-ignore //@ts-ignore
socket.emit("ask player", params.nodes[0], players[touchedPlayer].id, players.find((p) => p.id === socket.id, actualPlayerIndex)) 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) socket.emit("put correct background", socket.id)

@ -7,57 +7,114 @@ import { useNavigate } from 'react-router-dom';
import Modal from 'react-bootstrap/Modal'; import Modal from 'react-bootstrap/Modal';
import Offcanvas from 'react-bootstrap/Offcanvas'; import Offcanvas from 'react-bootstrap/Offcanvas';
import Button from 'react-bootstrap/Button'; 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 { interface LobbyContainerProps {
roomNum : string roomNum : string
HeadPlayer : Player HeadPlayer : Player
nbPlayer : number nbPlayer : number
setFirst: (first: boolean) => void
started : boolean
//? mettre un "nbplayermax" si le nombre de joueur max peut etre fixé ? //? 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 theme=useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
const dest = '/lobby?room=' + roomNum; const dest = '/lobby?room=' + roomNum;
//* Modal //* Modal
const [show, setShow] = useState(false); const [showFull, setShowFull] = useState(false);
const [showStart, setShowStart] = useState(false);
const handleClose = () => {
setShowFull(false)
setShowStart(false)
};
const handleClose = () => setShow(false); const handleShowFull = () => setShowFull(true);
const handleShow = () => setShow(true); const handleShowStart = () => setShowStart(true);
const handleContainerClick = () => { const handleContainerClick = () => {
if (show){ if (showFull || showStart){
handleClose() handleClose()
} }
else{ else{
if (nbPlayer < 6) { if (nbPlayer < 6 && !started) {
socket.off("request lobbies")
setFirst(true)
navigate(dest); navigate(dest);
} else { }
handleShow() else if(started){
//alert('La salle est pleine. Impossible de rejoindre.'); 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 stylefull;
let colorfull; let colorfull;
let actualRender = renderTooltip;
let bgcol = 'white';
if (nbPlayer >= 6) { if (nbPlayer >= 6) {
stylefull = "darkred" stylefull = "darkred"
colorfull = "darkred" colorfull = "darkred"
actualRender = renderTooltipFull
} }
else { else {
stylefull = "whitesmoke" stylefull = "whitesmoke"
colorfull = "black" colorfull = "black"
} }
if(started){
bgcol = 'lightgrey' //! le hover ne marche plus
actualRender = renderTooltipInGame
}
return( return(
<div className='lobbyMainContainer' onClick={handleContainerClick} style={{borderColor:stylefull}}> <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'}}> <header style={{height:'20%', display:'flex', justifyContent:'end'}}>
<h6><i>Room : {roomNum}</i></h6> <h6><i>Room : {roomNum}</i></h6>
</header> </header>
@ -66,12 +123,9 @@ const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbP
<div style={{display:'flex', justifyContent:'end', alignItems:'end'}}> <div style={{display:'flex', justifyContent:'end', alignItems:'end'}}>
<h2 style={{color:colorfull}}>{nbPlayer}/6</h2> <h2 style={{color:colorfull}}>{nbPlayer}/6</h2>
</div> </div>
{/*
<Button onClick={handleContainerClick} variant='danger'>
click
</Button> */}
<Modal show={show} onHide={handleClose}> {/* Modals */}
<Modal show={showFull} onHide={handleClose}>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Salle pleine</Modal.Title> <Modal.Title>Salle pleine</Modal.Title>
</Modal.Header> </Modal.Header>
@ -83,7 +137,20 @@ const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbP
</Modal.Footer> </Modal.Footer>
</Modal> </Modal>
<Modal show={showStart} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>La partie a déjà commencée</Modal.Title>
</Modal.Header>
<Modal.Body>La partie a déjà commencée, il est impossible d'y aller pour le moment !</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Ok
</Button>
</Modal.Footer>
</Modal>
</div> </div>
</OverlayTrigger>
); );
} }

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

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

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

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

@ -1,4 +1,6 @@
import React, { createContext, useContext, useState, ReactNode } from 'react'; 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 Indice from '../model/Indices/Indice';
import Pair from '../model/Pair'; import Pair from '../model/Pair';
import Person from '../model/Person'; import Person from '../model/Person';
@ -23,6 +25,7 @@ interface GameContextProps {
temps : number temps : number
networkData: any networkData: any
seed: number | string; seed: number | string;
nodesC: NodePerson[]
setIndicesData: (newIndices: Indice[]) => void; setIndicesData: (newIndices: Indice[]) => void;
setIndiceData: (newIndice: Indice) => void; setIndiceData: (newIndice: Indice) => void;
setPersonData: (newPerson: Person) => void; setPersonData: (newPerson: Person) => void;
@ -41,6 +44,7 @@ interface GameContextProps {
settempsData: (newtemps : number) => void settempsData: (newtemps : number) => void
setNetworkDataData: (networkData: any) => void setNetworkDataData: (networkData: any) => void
setSeedData: (seed: number | string) => void setSeedData: (seed: number | string) => void
setNodesData: (nodes: NodePerson[]) => void
} }
const GameContext = createContext<GameContextProps | undefined>(undefined); const GameContext = createContext<GameContextProps | undefined>(undefined);
@ -67,6 +71,12 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
const [temps, settemps] = useState<number>(0); const [temps, settemps] = useState<number>(0);
const [networkData, setNetworkData] = useState<any>(null); const [networkData, setNetworkData] = useState<any>(null);
const [seed, setSeed] = useState<number | string>(0); const [seed, setSeed] = useState<number | string>(0);
const [nodesC, setNodes] = useState<NodePerson[]>([]);
const setNodesData = (nodes: NodePerson[]) => {
setNodes(nodes)
}
const setNetworkDataData = (networkData: any) => { const setNetworkDataData = (networkData: any) => {
setNetworkData(networkData); setNetworkData(networkData);
@ -155,7 +165,7 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
} }
return ( 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} {children}
</GameContext.Provider> </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 PersonNetwork from "./model/PersonsNetwork";
import Player from "./model/Player"; import Player from "./model/Player";
import User from "./model/User"; import User from "./model/User";
import NodePerson from "./model/Graph/NodePerson";
import Font from "./model/Graph/Font";
class JSONParser{ class JSONParser{
@ -93,6 +95,15 @@ class JSONParser{
throw new Error("PARSER unable to parse player: " + json.type); 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 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(); const theme = useTheme();
console.log(winner)
console.log(indices)
let indicenull = false; let indicenull = false;
if (indices.length == 0){ if (indices.length == 0){
@ -150,7 +148,7 @@ function EndGame() {
<div className="playerContainer" key={index}> <div className="playerContainer" key={index}>
{player.id !== winner?.id && ( {player.id !== winner?.id && (
<div> <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>)} {!indicenull && (<h6 className='indiceDisplay'>{indices[players.findIndex((p) => p.id == player?.id)].ToString("fr")}</h6>)}
</div> </div>
)} )}

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

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

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

@ -7,51 +7,154 @@ import { useTheme } from '../Style/ThemeContext';
import LobbyContainer from '../Components/LobbyContainer'; import LobbyContainer from '../Components/LobbyContainer';
import Player from '../model/Player'; import Player from '../model/Player';
import User from '../model/User'; 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() { function Lobbies() {
const theme=useTheme(); const theme=useTheme();
const lobbyData = [ const [first, setFirst] = useState(true)
{ 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 [lobbyData, setLobbyData] = useState<LobbyDataProps[]>([])
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [showAvailable, setShowAvailable] = useState(true);
const handleShowAllClick = () => {
setShowAvailable(false);
};
const handleShowAvailableClick = () => {
setShowAvailable(true);
};
const filteredLobbies = lobbyData.filter((lobby) => const filteredLobbies = lobbyData.filter((lobby) =>
lobby.roomNum.toLowerCase().includes(searchTerm.toLowerCase()) || lobby.roomNum.toLowerCase().includes(searchTerm.toLowerCase()) ||
lobby.headPlayer.pseudo.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( return(
<div style={{display:'flex', flexDirection:'column', alignItems:'center'}}> <div style={{display:'flex', flexDirection:'column', alignItems:'center'}}>
<h1>Bienvenue dans le lobby des lobbies</h1>
<input <input
type="text" type="text"
className='searchLobby' className='searchLobby'
placeholder="Rechercher un lobby..." placeholder="Rechercher un lobby..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
style={{width:'80%', margin:'10px'}}
/> />
<div style={{border:'solid 3px', borderColor:'lightgray', borderRadius:'20px', margin:'10px'}}>
<button
style={{
width:'120px',
border:'solid',
borderStyle:'none',
borderRadius: '15px 0px 0px 15px',
borderWidth: '2px',
padding: '10px 15px',
backgroundColor: !showAvailable ? 'white' : 'lightgray',
}}
onClick={handleShowAllClick}
>
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"> <div className="lobbyList">
{filteredLobbies.map((lobby, index) => ( {filteredLobbiesToShow.map((lobby, index) => (
<LobbyContainer <LobbyContainer
key={index} key={index}
roomNum={lobby.roomNum} roomNum={lobby.roomNum}
HeadPlayer={lobby.headPlayer} HeadPlayer={lobby.headPlayer}
nbPlayer={lobby.nbPlayer} nbPlayer={lobby.nbPlayer}
setFirst={setFirstData}
started={lobby.started}
/> />
))} ))}
</div> </div>
)}
</div> </div>
); );
} }

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

@ -45,15 +45,17 @@ import SessionService from '../services/SessionService';
import { useRef } from 'react'; import { useRef } from 'react';
import Button from 'react-bootstrap/Button'; import Button from 'react-bootstrap/Button';
import Overlay from 'react-bootstrap/Overlay'; import Overlay from 'react-bootstrap/Overlay';
import { DataSet } from 'vis-network';
let gameStarted = false let gameStarted = false
let firstLaunch = true
function Lobby() { function Lobby() {
const theme=useTheme(); const theme=useTheme();
const navigate = useNavigate(); 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() const {user, setUserData, manager, login} = useAuth()
let first = true let first = true
@ -130,25 +132,77 @@ function Lobby() {
setIndicesData(choosenIndices) setIndicesData(choosenIndices)
first = true first = true
gameStarted = true gameStarted = true
socket.off("player left") //socket.off("player left")
socket.off("new player") //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'); navigate('/game?solo=false&daily=false');
}); });
socket.on("new player", (tab) =>{ socket.on("new player", (tab) =>{
const tmpTab: Player[] = [] const tmpTab: Player[] = []
for (const p of tab){ for (const p of tab.tab){
tmpTab.push(JSONParser.JSONToPlayer(p)) tmpTab.push(JSONParser.JSONToPlayer(p))
} }
console.log(tmpTab) console.log(tmpTab)
setPlayersData(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) => { socket.on("player left", (tab, i) => {
const tmpTab: Player[] = [] const tmpTab: Player[] = []
for (const p of tab){ for (const p of tab.tab){
tmpTab.push(JSONParser.JSONToPlayer(p)) tmpTab.push(JSONParser.JSONToPlayer(p))
} }
console.log(tmpTab)
setPlayersData(tmpTab) setPlayersData(tmpTab)
}) })
@ -182,12 +236,25 @@ 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 [show, setShow] = useState(false);
const target = useRef(null); const target = useRef(null);
return ( return (
<div className='lobby-container'> <div className='lobby-container'>
<div className='left-part'> <div className='left-part'>
<div className='player-board'> <div className='player-board'>
<div>
<div className='codeDiv' onClick={() => setCodeShowed(!codeShowed)}> <div className='codeDiv' onClick={() => setCodeShowed(!codeShowed)}>
{ {
codeShowed ? ( codeShowed ? (
@ -197,12 +264,22 @@ function Lobby() {
) )
} }
</div> </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 (?)*/} {/* //! voir pour la gestion avec un liste, utilisateur avec le "+ (vous)" et les pdp avec les lettres grecs (?)*/}
{players.map((player, index) => ( {players.map((player, index) => (
// <PlayerItemList key={player.id} pdp={PersonImg} name={player.name} id={player.id}/> // <PlayerItemList key={player.id} pdp={PersonImg} name={player.name} id={player.id}/>
<PlayerItemList key={player.id} player={player} room={room}/> <PlayerItemList key={player.id} player={player} room={room}/>
))} ))}
<div className='centerButton'> {(players.length < 6) && <div className='centerButton'>
<button className='button' onClick={addBot} <button className='button' onClick={addBot}
style={{ style={{
backgroundColor: theme.colors.primary, backgroundColor: theme.colors.primary,
@ -210,34 +287,13 @@ function Lobby() {
+ +
</button> </button>
</div> </div>
}
</div> </div>
</div> </div>
<div className="lobby-vertical-divider" style={{backgroundColor: theme.colors.secondary}}></div> <div className="lobby-vertical-divider" style={{backgroundColor: theme.colors.secondary}}></div>
<div className='right-part'> <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' <div className='lobbyR'
style={{flexDirection:'column', style={{flexDirection:'column',
alignItems:'space-around'}}> alignItems:'space-around'}}>
@ -301,29 +357,6 @@ function Lobby() {
Démarrer la partie ! Démarrer la partie !
</button> </button>
</div> </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>
</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; display: flex;
justify-content: center; justify-content: center;
} }
/*
.MidContainer div {
display: flex;
justify-content: center;
flex-direction: column;
} */
.leftContainer{ .leftContainer{
width: 30%; width: 30%;
@ -35,7 +29,18 @@
width: 30%; width: 30%;
} }
.NewleftContainer{
margin: 20px 30px;
width: 70%;
}
.NewrightContainer{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 30%;
}
/* .textBoard div{ /* .textBoard div{
display: flex; display: flex;
@ -56,8 +61,15 @@
flex-direction: column; flex-direction: column;
} }
.NewbuttonGroupVertical{
display: flex;
justify-content:space-around;
align-items:start;
}
.ButtonNav{ .ButtonNav{
margin: 15px 0; margin: 15px 10px;
width:200px; width:200px;
height: 8vh; height: 8vh;
@ -71,3 +83,40 @@
font-size:larger; 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 */ /* Context */
import { useAuth } from '../Contexts/AuthContext'; import { useAuth } from '../Contexts/AuthContext';
/* Style */ /* Style */
import './Play.css'; import './Play.css';
import { useTheme } from '../Style/ThemeContext'; import { useTheme } from '../Style/ThemeContext';
@ -13,7 +12,7 @@ import ButtonImgNav from "../Components/ButtonImgNav";
/* Img */ /* Img */
/* Icon */ /* Icon */
import { socket } from '../SocketConfig'; import { socket } from '../SocketConfig';
import { useNavigate } from 'react-router-dom'; import { NavigationType, useNavigate, useNavigationType } from 'react-router-dom';
import GameCreator from '../model/GameCreator'; import GameCreator from '../model/GameCreator';
import { useGame } from '../Contexts/GameContext'; import { useGame } from '../Contexts/GameContext';
import ScoreBoard from '../Components/ScoreBoard'; import ScoreBoard from '../Components/ScoreBoard';
@ -29,6 +28,9 @@ import { loadImageAsync } from '../ImageHelper';
import { Overlay, ToggleButton, ToggleButtonGroup } from 'react-bootstrap'; import { Overlay, ToggleButton, ToggleButtonGroup } from 'react-bootstrap';
import Button from 'react-bootstrap/Button'; import Button from 'react-bootstrap/Button';
import ButtonGroup from 'react-bootstrap/ButtonGroup'; import ButtonGroup from 'react-bootstrap/ButtonGroup';
import Info from '../res/icon/infoGreen.png';
let cptNavigation = 0
function Play() { function Play() {
@ -39,6 +41,16 @@ function Play() {
const {setDailyEnigmeData, setIndicesData, setPersonData, setPersonNetworkData } = useGame() const {setDailyEnigmeData, setIndicesData, setPersonData, setPersonNetworkData } = useGame()
const target = useRef(null); const target = useRef(null);
const navigationType = useNavigationType()
cptNavigation++
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
}
}
useEffect(() => { useEffect(() => {
if (user == null){ if (user == null){
manager.userService.fetchUserInformation().then(([user, loggedIn]) =>{ manager.userService.fetchUserInformation().then(([user, loggedIn]) =>{
@ -48,6 +60,7 @@ function Play() {
if (loggedIn){ if (loggedIn){
login() login()
setUserData(user) setUserData(user)
socket.emit("join back game", user)
} }
else{ else{
loadImageAsync(defaultImg).then((blob) => { loadImageAsync(defaultImg).then((blob) => {
@ -58,8 +71,20 @@ function Play() {
} }
}) })
} }
else{
socket.emit("join back game", user)
}
}, [isLoggedIn]); }, [isLoggedIn]);
const [goBackRoom, setGoBackRoom] = useState(-1)
useEffect(() => {
socket.on("join back game", (room) => {
setGoBackRoom(room)
})
}, [])
const [room, setRoom] = useState(null); const [room, setRoom] = useState(null);
const navigate = useNavigate(); const navigate = useNavigate();
@ -67,10 +92,6 @@ function Play() {
socket.emit("lobby created") socket.emit("lobby created")
} }
useEffect(() => {
console.log(user)
}, [user])
function launchMastermind(){ function launchMastermind(){
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(3, 30) const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(3, 30)
setPersonData(choosenPerson) setPersonData(choosenPerson)
@ -112,6 +133,10 @@ function Play() {
} }
}, [room, navigate]); }, [room, navigate]);
const goBack = () => {
navigate("/lobby?room=" + goBackRoom)
}
const [showOverlay, setShowOverlay] = useState(false); const [showOverlay, setShowOverlay] = useState(false);
@ -159,10 +184,22 @@ function Play() {
<div className="MainContainer"> <div className="MainContainer">
<div className="leftContainer"> <div className="leftContainer">
{/* <button className='ButtonNav'> {goBackRoom != -1 &&
Param <div className='returnDiv'>
</button> */} <div style={{
{/* <ButtonImgNav dest='/signup' img={defaultImg} text="Gestion du compte"/> */} 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>
<div className="MidContainer"> <div className="MidContainer">
<div> <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={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> <button onClick= {() => navigate("/join")} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
</div> </div>
</div> </div>
<div className='rightContainer'> <div className='rightContainer'>

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

@ -2,10 +2,10 @@ import React, { useEffect, useState } from 'react';
import ProfilePDP from '../Components/ProfilePDP'; import ProfilePDP from '../Components/ProfilePDP';
import SessionService from '../services/SessionService'; import SessionService from '../services/SessionService';
import AuthService from '../services/AuthService';
import { PlayerProps } from '../types/Player'; import { PlayerProps } from '../types/Player';
import { delay, update } from 'lodash'; import { delay, set, update } from 'lodash';
import { socket } from '../SocketConfig'; import { socket } from '../SocketConfig';
import AuthService from '../services/AuthService';
/* Style */ /* Style */
@ -14,6 +14,9 @@ import Edit from "../res/icon/edit-pen.png"
import Coche from '../res/icon/coche.png' import Coche from '../res/icon/coche.png'
import Cancel from '../res/icon/cancel.png' import Cancel from '../res/icon/cancel.png'
/* Nav */
import { useNavigate } from 'react-router-dom';
/* Model */ /* Model */
import User from '../model/User'; import User from '../model/User';
@ -25,7 +28,8 @@ import Button from 'react-bootstrap/Button';
import Alert from 'react-bootstrap/Alert'; import Alert from 'react-bootstrap/Alert';
import Modal from 'react-bootstrap/Modal'; import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form'; import Form from 'react-bootstrap/Form';
import { useNavigate } from 'react-router-dom'; import ProgressBar from 'react-bootstrap/ProgressBar';
//@ts-ignore //@ts-ignore
const Profile = () => { const Profile = () => {
@ -34,11 +38,6 @@ const Profile = () => {
//let player; //let player;
const {user, logout} = useAuth() const {user, logout} = useAuth()
// let pseudoNotNull;
// if(user?.pseudo != null){
// pseudoNotNull = user.pseudo;
// }
const [editingUsername, setEditingUsername] = useState(false); const [editingUsername, setEditingUsername] = useState(false);
const [newUsername, setNewUsername] = useState(user?.pseudo); const [newUsername, setNewUsername] = useState(user?.pseudo);
@ -59,6 +58,100 @@ const Profile = () => {
}; };
//* 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 : //* Gestion Modal de suppression :
const [showDeleteModal, setShowDeleteModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false);
@ -84,7 +177,6 @@ const Profile = () => {
// Verification de la phrase // Verification de la phrase
if (confirmationPhrase.toLowerCase() === 'supprimer mon compte') { if (confirmationPhrase.toLowerCase() === 'supprimer mon compte') {
console.log('Compte supprimé !'); console.log('Compte supprimé !');
console.log(user);
if(user!= null){ if(user!= null){
const pseudo = user.pseudo; const pseudo = user.pseudo;
@ -108,7 +200,6 @@ const Profile = () => {
} }
}; };
return ( return (
<> <>
<center><h1>Mon Compte</h1></center> <center><h1>Mon Compte</h1></center>
@ -134,7 +225,7 @@ const Profile = () => {
</div> </div>
) : ( ) : (
<div className='username-display'> <div className='username-display'>
<h1>{user?.pseudo}</h1> <h1 className='pseudoDisplay'>{user?.pseudo}</h1>
<button className='editbutton' onClick={() => setEditingUsername(true)}> <button className='editbutton' onClick={() => setEditingUsername(true)}>
<img src={Edit} alt='edit' width='25' height='25'/> <img src={Edit} alt='edit' width='25' height='25'/>
</button> </button>
@ -143,16 +234,95 @@ const Profile = () => {
} }
<hr/> <hr/>
{!editingUsername ? ( {!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%'}}> <Alert key='info' variant='info' style={{width:'100%'}}>
Vous êtes en mode "édition". Vous êtes en mode "édition".
</Alert> </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'> <div className='bottom'>
<> <>
{!editingUsername && (
<Button variant="danger" onClick={handleShowDeleteModal}>Supprimer</Button> <Button variant="danger" onClick={handleShowDeleteModal}>Supprimer</Button>
) }
{/* Modal de suppression */}
<Modal show={showDeleteModal} onHide={handleCloseDeleteModal}> <Modal show={showDeleteModal} onHide={handleCloseDeleteModal}>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Confirmation de suppression</Modal.Title> <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) tabFilterPerson.push(p)
} }
}) })
if (tabFilterPerson.length == 0){
return -1
}
return tabFilterPerson[Math.floor(Math.random() * tabFilterPerson.length)].getId() return tabFilterPerson[Math.floor(Math.random() * tabFilterPerson.length)].getId()
} }

@ -107,6 +107,38 @@ class AuthService{
throw error; 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; export default AuthService;

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

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