Merge branch 'master' into weeklyDaily

pull/104/head^2
Baptiste MARCEL 1 year ago
commit 3a1a5c87fe

@ -34,7 +34,6 @@ steps:
from_secret: SECRET_SONAR_LOGIN_CRYPTIDE
#
- name: container-web
image: plugins/docker
settings:
@ -46,8 +45,12 @@ steps:
from_secret: SECRET_REGISTRY_USERNAME
password:
from_secret: SECRET_REGISTRY_PASSWORD
environment:
BASEPATH: "/containers/Crypteam-website"
#depends_on: [ build ]
when:
branch:
- master
#container deployment
@ -61,3 +64,6 @@ steps:
#PRIVATE: true
ADMINS: thomaschazot2,pierreferreira,baptistemarcel
depends_on: [ container-web ]
when:
branch:
- master

2
.gitignore vendored

@ -51,4 +51,4 @@ package-lock.json
socialgraph.db
# build
cryptide_project/build/
cryptide_project/build/*

@ -30,3 +30,4 @@ EXPOSE 80
# Définissez ENTRYPOINT pour démarrer Nginx lorsque le conteneur est lancé
ENTRYPOINT ["nginx", "-g", "daemon off;"]
#

@ -25,8 +25,8 @@ fi
npm start &
node $SCRIPT_DIR/../server/server.js &
node $SCRIPT_DIR/../server/socket_io/server.js &
node $SCRIPT_DIR/../src/server/server.js
node $SCRIPT_DIR/../server/api/server.js

@ -1,19 +0,0 @@
{
"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.

Before

Width:  |  Height:  |  Size: 3.8 KiB

@ -1 +0,0 @@
<!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.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

@ -1,25 +0,0 @@
{
"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"
}

@ -1,3 +0,0 @@
# 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

@ -1,2 +0,0 @@
"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

@ -1,123 +0,0 @@
/*!
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.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

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

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

@ -7,7 +7,7 @@ const app = express();
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: ["http://localhost:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
origin: "*", // Remplacez par l'URL de votre application React
methods: ["GET", "POST"],
credentials: true
}

@ -1,11 +1,15 @@
const ADRESSE_WEBSERVER = "http://localhost:3002"
const ADRESSE_WEBSERVER = "http://172.20.10.4:3002"
const ADRESSE_DBSERVER = "http://localhost:3003"
const ADRESSE_DBSERVER = "http://172.20.10.4:3003"
const tmp = ADRESSE_DBSERVER
const tmp2 = ADRESSE_WEBSERVER
const ADRESSE_WEBSITE = ""
const basePath = process.env.REACT_APP_BASE_PATH || '/containers/Crypteam-website';
export {ADRESSE_DBSERVER, ADRESSE_WEBSERVER, ADRESSE_WEBSITE}
const tmp3 = basePath
export {ADRESSE_DBSERVER, ADRESSE_WEBSERVER, ADRESSE_WEBSITE, basePath}

@ -41,6 +41,10 @@ import messagesEn from './Translations/en.json';
/* Gestion d' erreur */
import ErrorBoundary from './Error/ErrorBoundary';
import ErrorPage from './Error/ErrorPage';
import DeducCheck from './Pages/DeducCheck';
import {basePath} from "./AdressSetup"
const messages = {
fr: messagesFr,
@ -58,9 +62,11 @@ function App() {
setLocale(newLocale);
};
console.log(basePath)
//const location = useLocation();
const hasNavbarVisible = ["/", "/login", "/signup", "/play", "/lobby", "/endgame", "/deduc"]//.includes(window.location.pathname);
const hasNavbarVisible = [basePath + "/", basePath + "/login", basePath + "/signup", basePath + "/lobby", basePath + "/endgame", basePath + "/deduc"]//.includes(window.location.pathname);
return (
@ -73,17 +79,19 @@ function App() {
<BrowserRouter>
{hasNavbarVisible && <AppNavbar changeLocale={changeLocale} />}
<Routes>
<Route path="/" element={<NewPlay/>} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/presentation" element={<Home />} />
<Route path="/lobby" element={<Lobby/>} />
<Route path="/endgame" element={<EndGame/>} />
<Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/>
<Route path="/info" element={<InfoPage locale={locale} changeLocale={changeLocale}/>} />
<Route path="/deduc" element={<DeducGrid/>} />
<Route path="/profile" element={<Profile/>} />
<Route path="/join" element={<Lobbies/>}/>
<Route path={`${basePath}/`} element={<NewPlay/>} />
<Route path={`${basePath}/login`} element={<Login />} />
<Route path={`${basePath}/signup`} element={<SignUp />} />
<Route path={`${basePath}/presentation`} element={<Home />} />
<Route path={`${basePath}/lobby`} element={<Lobby/>} />
<Route path={`${basePath}/endgame`} element={<EndGame/>} />
<Route path={`${basePath}/game`} element={<InGame locale={locale} changeLocale={changeLocale}/>}/>
<Route path={`${basePath}/info`} element={<InfoPage locale={locale} changeLocale={changeLocale}/>} />
<Route path={`${basePath}/deduc`} element={<DeducCheck/>} />
<Route path={`${basePath}/TheRealDeduc`} element={<DeducGrid/>} />
<Route path={`${basePath}/profile`} element={<Profile/>} />
<Route path={`${basePath}/join`} element={<Lobbies/>}/>
{/* <Route path="/solo" element={<SoloGame locale={locale} changeLocale={changeLocale} />}/> */}
<Route path="*" element={<ErrorPage code="404" msg='not found' />} /> {/* page 404 */}

@ -5,6 +5,8 @@ import { FormattedMessage } from 'react-intl';
import { useTheme } from '../Style/ThemeContext';
import COLORS from '../Style/Color';
import {basePath} from "../AdressSetup"
//@ts-ignore
function BigButtonNav({ dest, img}) {
@ -15,7 +17,7 @@ function BigButtonNav({ dest, img}) {
// };
return (
<Link to={dest} className="link-without-underline">
<Link to={`${basePath}/${dest}`} className="link-without-underline">
<button className='bigbuttonNabImg' style={{ backgroundColor: theme.colors.primary }}>
<img src={img} alt="Button Image" height="100" width="100"/>
</button>

@ -4,12 +4,14 @@ import './ButtonImgNav.css';
import { FormattedMessage } from 'react-intl';
import { useTheme } from '../Style/ThemeContext';
import {basePath} from "../AdressSetup"
//@ts-ignore
function ButtonImgNav({ dest, img, text = "" }) {
const theme = useTheme();
return (
<Link to={dest} className="link-without-underline"> {/*target='_blank' ==> ouvre un nouvelle onglet*/ }
<Link to={`${basePath}/${dest}`} className="link-without-underline"> {/*target='_blank' ==> ouvre un nouvelle onglet*/ }
<button className='buttonNabImg' style={{ backgroundColor: theme.colors.primary, color: theme.colors.secondary}}>
<img src={img} alt="Button Image" height="50" width="50"/>
<p>{text}</p>

@ -20,6 +20,7 @@ import User from "../model/User";
import { json } from "body-parser";
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
import {basePath} from "../AdressSetup"
interface MyGraphComponentProps {
onNodeClick: (shouldShowChoiceBar: boolean) => void;
@ -819,7 +820,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.off("put imossible grey")
socket.off("who plays")
navigate("/endgame")
navigate(`${basePath}/endgame`)
}
}
})
@ -1031,14 +1032,13 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
testFirst = true
setElapsedTime(0)
endgame = true
navigate("/endgame?solo=true&daily=" + isDaily)
navigate(`${basePath}/endgame?solo=true&daily=${isDaily}`)
}
}
}
index++
}
addToHistory(person.getName() + " n'est pas le tueur !"); //TODO préciser le nombre d'indice qu'il a de juste
addToHistory(person.getName() + " n'est pas le coupable !"); //TODO préciser le nombre d'indice qu'il a de juste
cptTour ++; // On Incrémente le nombre de tour du joueur
const tour = cptTour+1;

@ -10,6 +10,7 @@ import Button from 'react-bootstrap/Button';
import { socket } from '../SocketConfig';
import Tooltip from 'react-bootstrap/esm/Tooltip';
import OverlayTrigger from 'react-bootstrap/esm/OverlayTrigger';
import {basePath} from "../AdressSetup"
interface LobbyContainerProps {
roomNum : string
@ -20,11 +21,12 @@ interface LobbyContainerProps {
//? mettre un "nbplayermax" si le nombre de joueur max peut etre fixé ?
}
const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbPlayer, setFirst, started}) => {
const theme=useTheme();
const navigate = useNavigate();
const dest = '/lobby?room=' + roomNum;
const dest = 'lobby?room=' + roomNum;
//* Modal
const [showFull, setShowFull] = useState(false);
@ -47,7 +49,7 @@ const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbP
if (nbPlayer < 6 && !started) {
socket.off("request lobbies")
setFirst(true)
navigate(dest);
navigate(`${basePath}/${dest}`);
}
else if(started){
handleShowStart()

@ -25,22 +25,24 @@ import { useTheme } from '../Style/ThemeContext';
import { useAuth } from '../Contexts/AuthContext';
import { useNavigate } from 'react-router-dom';
import {basePath} from "../AdressSetup"
// @ts-ignore
function AppNavbar({changeLocale}) {
const theme = useTheme();
const navigate = useNavigate();
const {user, isLoggedIn, logout} = useAuth();
function navigateToHome(){
navigate("/")
}
function navigateToProfile(){
navigate("/profile")
navigate(`${basePath}/profile`)
}
function navigateToLogin(){
navigate("/login")
navigate(`${basePath}/login`)
}
function navigateToHome(){
navigate(`${basePath}/`)
}
return (
@ -52,13 +54,13 @@ function AppNavbar({changeLocale}) {
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="/" style={{ color: theme.colors.text }}>
<Nav.Link href={`${basePath}/`} style={{ color: theme.colors.text }}>
Jouer
</Nav.Link>
<Nav.Link href="/presentation" style={{ color: theme.colors.text }}>
<Nav.Link href={`${basePath}/presentation`} style={{ color: theme.colors.text }}>
Présentation
</Nav.Link>
<Nav.Link href="/info" style={{ color: theme.colors.text }}>
<Nav.Link href={`${basePath}/info`} style={{ color: theme.colors.text }}>
Info
</Nav.Link>
</Nav>

@ -7,8 +7,14 @@ import { useTheme } from '../Style/ThemeContext';
/* Ressources */
import Person from '../res/img/Person.png'
import BotImg from '../res/img/bot.png'
import { useGame } from '../Contexts/GameContext';
/* Model */
import Bot from '../model/Bot';
/* Context */
import { useGame } from '../Contexts/GameContext';
import { positionToColor } from '../ColorHelper';
interface PlayerStatusProps {
img: any
state: any
@ -19,8 +25,9 @@ interface PlayerStatusProps {
showCircle: boolean
playerIndex: number
askedWrong: boolean
}
let touchedPlayer = -1
}
let touchedPlayer = -1
//@ts-ignore
const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person, name = "Dummy", index, playerTouched, setPlayerTouched, showCircle, playerIndex, askedWrong}) => {
@ -41,7 +48,7 @@ const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person,
useEffect(() => {
if (playerIndex===index){
setBuffer('solid 1px green')
setBuffer('solid 3px green')
}
else{
setBuffer('')
@ -52,31 +59,79 @@ const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person,
if (IsActualPlayer && !askedWrong){
setPlayerTouched(index)
setTouchedPlayer(index)
//setIsClicked(!isClicked);
}
}
//* Code pour le cercle
//const [isClicked, setIsClicked] = useState(false); // État du bouton, par défaut false
const handleClick = () => {
onTouch();
};
const circleStyle: React.CSSProperties = {
backgroundColor: touchedPlayer == index && showCircle ? 'gold' : positionToColor(index), // Changement de la couleur en fonction de la condition
borderRadius: '50%',
width: '80px',
height: '80px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
objectFit: 'cover'
};
const circleStyleInt: React.CSSProperties = {
backgroundColor:'white',
borderRadius: '50%',
width: '70px',
height: '70px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
objectFit: 'cover'
}
const imageStyle: React.CSSProperties = {
borderRadius: '50%',
width: '60px',
height: '60px',
objectFit: 'cover', // image est ajustée pour couvrir le cercle
position: 'relative',
};
return (
<div style={{border:buffer}}>
<div className='centerDivV' onClick={() => onTouch()}>
<img src={img} alt="player" height="60" width="60"/>
<h5>{name}</h5>
{IsActualPlayer && (
(touchedPlayer == index && showCircle) ?(
<div className='statusDiv' style={{ backgroundColor: "gold" }}>
<img src={state} alt="state" height="30" width="30"/>
<div className='centerDivV'>
{/* <div className='centerDivV' style={{border:buffer, borderRadius: '50%', padding:'1px'}}> */}
<div className='centerDivV' style={circleStyle} onClick={() => handleClick()}>
<div className='centerDivV' style={circleStyleInt}>
<img src={img} alt="player" height="40" width="40" style={{ ...imageStyle, objectFit: 'cover' }}/>
</div>
): showCircle &&
(
<div className='statusDiv' style={{ backgroundColor: theme.colors.primary }}>
<img src={state} alt="state" height="30" width="30"/>
{/* </div> */}
</div>
)
)}
<div className='playerNameDisplay' style={{border:buffer}}>
<h5>{actualPlayerIndex !== index ? (name.substring(0, name.length - 2).length > 7 ? name.substring(0, name.length - 2).substring(0, 7) + '...' : name) : 'vous'}</h5>
</div>
</div>
);
}
export default PersonStatus;
// {IsActualPlayer && (
// (touchedPlayer == index && showCircle) ?(
// <div className='statusDiv' style={{ backgroundColor: "gold" }}>
// <img src={state} alt="state" height="30" width="30"/>
// </div>
// ): showCircle &&
// (
// <div className='statusDiv' style={{ backgroundColor: theme.colors.primary }}>
// <img src={state} alt="state" height="30" width="30"/>
// </div>
// )
// )}

@ -29,7 +29,7 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
return (
<div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px' }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '20px' }}>
{
//@ts-ignore
players.map((player, index) => (
@ -56,6 +56,7 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
alignItems:"center",
margin: 10
}}>
{(playerTouched == players.length)
?(
<button style={{
@ -65,7 +66,7 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
border: "solid 1px",
textAlign: "center",
padding: "10px"}}
onClick={() => askEveryone()}>Ask everyone</button>
onClick={() => askEveryone()}>Guess !</button>
):
(
<button style={{

@ -6,7 +6,7 @@ import './ErrorStyle.css';
import { FormattedMessage } from 'react-intl';
import { Button } from 'react-bootstrap';
const basePath = process.env.REACT_APP_BASE_PATH || '/containers/Crypteam-website';
//@ts-ignore
function ErrorPage({ code = "", msg = "Something is wrong"}) {
@ -28,7 +28,7 @@ function ErrorPage({ code = "", msg = "Something is wrong"}) {
</div>
<div className='centerDivH' style={{margin: "20px"}}>
<Button href='/' variant='danger'>Retour à l'accueil</Button>
<Button href={`${basePath}/`} variant='danger'>Retour à l'accueil</Button>
</div>
</div>
);

@ -0,0 +1,120 @@
import React from 'react';
/* Style */
import './DeducGrid.css';
import { useTheme } from '../Style/ThemeContext';
/* Component */
/* Boostrap */
import Table from 'react-bootstrap/Table';
import Form from 'react-bootstrap/Form';
/* lang */
import { FormattedMessage } from 'react-intl';
/* model */
import Stub from '../model/Stub';
import { useGame } from '../Contexts/GameContext';
import { positionToEmoji } from '../ColorHelper';
function DeducCheck() {
const theme = useTheme();
//const indices = Stub.GenerateIndice();
const params = new URLSearchParams(window.location.search);
const NbPlayer = params.get('nbPlayer');
const actualPlayerIndex = params.get('actualId') ?? '0';
//const { actualPlayerIndex, players } = useGame();
// let playerstmp
// if (players.length == 0) playerstmp = ["1", "2", "3", "4", "5", "4"];
// else { playerstmp = players}
//* Gestion players
const playerList = Array.from({ length: parseInt(NbPlayer ?? '1') }, (_, index) => (index + 1).toString());
const playerColors = playerList.map((_, index) => positionToEmoji(index, true));
const players = playerColors.filter((_, index) => index !== parseInt(actualPlayerIndex ?? '0'));
// const players = [
// "🔵",
// "🟢",
// "🟡",
// "🟣",
// "🔴"
//]
//console.log(players)
// console.log(playerColors)
// console.log(actualPlayerIndex)
//* Gestion indices
const indices = Stub.GenerateIndice();
const halfLength = Math.ceil(indices.length / 2);
const firstHalfIndices = indices.slice(0, halfLength);
const secondHalfIndices = indices.slice(halfLength);
return (
<div style={{ margin: '20px', display: 'flex', flexDirection: 'column' }}>
<div style={{ display: 'flex', flexDirection: 'row', overflowX: 'auto' }}>
{/* Premier tableau */}
<Table striped bordered hover style={{ marginRight: '20px' }}>
<thead>
<tr>
<th>Indices</th>
{players.map((player, index) => (
<th key={index}>{player}</th>
))}
</tr>
</thead>
<tbody>
{firstHalfIndices.map((indice, rowIndex) => (
<tr key={rowIndex}>
<td>{indice.ToString("fr")}</td>
{players.map((player, colIndex) => (
<td key={colIndex}>
{/* <input type="checkbox"/> */}
<Form.Check aria-label="option 1" />
</td>
))}
</tr>
))}
</tbody>
</Table>
{/* Deuxième tableau */}
<Table striped bordered hover>
<thead>
<tr>
<th>Indices</th>
{players.map((player, index) => (
<th key={index}>{player}</th>
))}
</tr>
</thead>
<tbody>
{secondHalfIndices.map((indice, rowIndex) => (
<tr key={rowIndex}>
<td>{indice.ToString("fr")}</td>
{players.map((player, colIndex) => (
<td key={colIndex}>
{/* <input type="checkbox"/> */}
<Form.Check aria-label="option 1" />
</td>
))}
</tr>
))}
</tbody>
</Table>
</div>
</div>
);
}
export default DeducCheck;

@ -34,6 +34,8 @@ import { useGame } from '../Contexts/GameContext';
/* Boostrap */
import { Button } from 'react-bootstrap';
import Bot from '../model/Bot';
import {basePath} from "../AdressSetup"
function EndGame() {
@ -131,7 +133,7 @@ function EndGame() {
<div className="head">
<header className='leaderboard-header' style={{ borderColor: theme.colors.primary }}>
<h1>{winner?.pseudo} a gagné !</h1>
<h3>Le tueur était <u>{person?.getName()}</u></h3>
<h3>Le coupable était <u>{person?.getName()}</u></h3>
</header>
</div>
<div className='winner'>
@ -162,7 +164,7 @@ function EndGame() {
<div className="head">
<header className='leaderboard-header' style={{ borderColor: theme.colors.primary }}>
<h1>Vous avez gagné !</h1>
<h3>Le tueur était <u>{person?.getName()}</u></h3>
<h3>Le coupable était <u>{person?.getName()}</u></h3>
</header>
</div>
<div className='winner'>
@ -194,7 +196,7 @@ function EndGame() {
<div id="vis-graph"/>
<div className='centerDivH' onClick={resetAll} style={{margin: "20px"}}>
<Button href='/'>Retour à l'accueil</Button>
<Button href={`${basePath}/`}>Retour à l'accueil</Button>
</div>
</div>

@ -12,6 +12,8 @@ import {loadImageAsync} from "../ImageHelper"
import { socket } from '../SocketConfig';
import JSONParser from '../JSONParser';
import {basePath} from "../AdressSetup"
// @ts-ignore
function Home() {
@ -49,7 +51,7 @@ function Home() {
<h2>Introduction</h2>
<p>
{/* <FormattedMessage id="home.histoire" /> */}
Bienvenue dans notre jeu de déduction captivant, où l'intrigue et la malice se rejoignent dans une aventure palpitante ! Plongez-vous dans un monde de mystère et d'intrigue, où chaque interaction compte, et chaque indice vous rapproche de la vérité.Imaginez un graphique complexe où chaque sommet représente une personne, chaque axe une relation, et chaque détail compte. Vous êtes plongé dans un défi stimulant pour découvrir qui parmi ces individus est le mystérieux tueur. Chaque joueur détient un indice crucial, et seul le partage stratégique de ces indices vous mènera à la résolution du mystère. Explorez notre page de règles pour comprendre les subtilités du jeu, découvrez les indices qui peuvent vous guider, et élaborez des stratégies intelligentes pour identifier le coupable. Manipuler vos amis, afin d'être le premier à découvrir qui est le meurtrier ! Êtes-vous prêt à relever le défi et à démasquer le tueur caché dans le graphe ? Que l'enquête commence !
Bienvenue dans notre jeu de déduction captivant, où l'intrigue et la malice se rejoignent dans une aventure palpitante ! Plongez-vous dans un monde de mystère et d'intrigue, où chaque interaction compte, et chaque indice vous rapproche de la vérité.Imaginez un graphique complexe où chaque sommet représente une personne, chaque axe une relation, et chaque détail compte. Vous êtes plongé dans un défi stimulant pour découvrir qui parmi ces individus est le mystérieux coupable. Chaque joueur détient un indice crucial, et seul le partage stratégique de ces indices vous mènera à la résolution du mystère. Explorez notre page de règles pour comprendre les subtilités du jeu, découvrez les indices qui peuvent vous guider, et élaborez des stratégies intelligentes pour identifier le coupable. Manipuler vos amis, afin d'être le premier à découvrir qui est le meurtrier ! Êtes-vous prêt à relever le défi et à démasquer le coupable caché dans le graphe ? Que l'enquête commence !
</p>
</div>
<div>
@ -65,7 +67,7 @@ function Home() {
Si un joueur place un jeton carré, le questionneur doit également jouer son jeu en plaçant un jeton carré de sa couleur sur un nœud du graphique. La contre-manipulation devient ainsi une arme redoutable pour détourner l'accusation et semer la confusion. Pour en savoir plus, plongez-vous dans les détails de ce passionnant récit sur une autre page.
</p>
<br/>
<p>Pour des informations plus détaillées, consulter les <Link to="/info">règles</Link>.</p>
<p>Pour des informations plus détaillées, consulter les <Link to={`${basePath}/info`}>règles</Link>.</p>
<br/>
</div>
<div>
@ -100,7 +102,7 @@ function Home() {
{/* <h3> <u><FormattedMessage id="game.illustratedBy"/></u><br/> Kwanchai Moriya</h3> */}
{/* <button>Jouer au jeu</button> */}
<br/>
<Link to="/play" className='button'
<Link to={`${basePath}/`} className='button'
style={{
backgroundColor: theme.colors.primary,
borderColor: theme.colors.secondary

@ -72,8 +72,8 @@
.playerlistDiv{
position: absolute;
z-index: 1;
left: 10px;
top :50px;
left: 30px;
top : 30px;
}
.nbLaps{ /*nombre de tour*/
@ -137,21 +137,43 @@
/** Historique*/
.historique{
.historique {
position: absolute;
z-index: 1;
bottom: 2%;
left: 2%;
display: flex;
flex-direction: column;
/* justify-content: end; */
padding: 15px 25px;
background-color: #d9d9d9;
border-radius: 15px;
border: solid;
border-width: 0.5px 0.5px 5px 0.5px;
border-color: whitesmoke lightgray gray whitesmoke;
border-radius: 0 5% 15px 0;
height: 250px;
width: 20%;
overflow-y:auto;
direction: rtl;
overflow-y: auto;
}
.historique div{
direction: ltr;
}
.historique::-webkit-scrollbar {
width: 10px;
}
.historique::-webkit-scrollbar-thumb {
background-color: lightgray;
border-radius: 5px;
}
.historique::-webkit-scrollbar-track {
background-color: whitesmoke;
}
.historique::-webkit-scrollbar-corner {
background-color: whitesmoke;
}

@ -49,6 +49,8 @@ import { Network } from 'vis-network';
import {generateLatexCode, generateLatexCodeEnigme} from '../Script/LatexScript';
import Pair from '../model/Pair';
import Indice from '../model/Indices/Indice';
import {basePath} from "../AdressSetup"
let cptNavigation = 0
@ -66,7 +68,7 @@ const InGame = ({locale, changeLocale}) => {
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
navigate("/play")
navigate(`${basePath}/`)
}
}
@ -278,8 +280,10 @@ const InGame = ({locale, changeLocale}) => {
const [SwitchEnabled, setSwitchEnabled] = useState(false)
const allIndices = Stub.GenerateIndice()
const { indice, players } = useGame();
const { indice, players, actualPlayerIndex} = useGame();
const nbPlayer = players.length;
const navdeduc = 'deduc?actualId=' + actualPlayerIndex + '&nbPlayer=' + nbPlayer;
return (
<div id="mainDiv">
@ -364,7 +368,7 @@ const InGame = ({locale, changeLocale}) => {
{/* <Link to='/info#indice-possible' target='_blank'>
//? redirection impossible apparament (securité des navigateur
*/}
<Link to='/info' target='_blank'>
<Link to={`${basePath}/info`} target='_blank'>
<button className='button'
style={{
backgroundColor: theme.colors.tertiary,
@ -373,12 +377,9 @@ const InGame = ({locale, changeLocale}) => {
<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> */}
{!IsSolo &&
<Link to='/deduc' target='_blank'>
<Link to={`${basePath}/${navdeduc}`} target='_blank'>
<button className='button'
style={{
backgroundColor: theme.colors.tertiary,

@ -140,7 +140,7 @@ function Lobbies() {
{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>
<button onClick={createLobby} className='ButtonNav' style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}>Créez en un !</button>
</div>
) : (
<div className="lobbyList">

@ -46,6 +46,8 @@ import { useRef } from 'react';
import Button from 'react-bootstrap/Button';
import Overlay from 'react-bootstrap/Overlay';
import { DataSet } from 'vis-network';
import {basePath} from "../AdressSetup"
let gameStarted = false
@ -134,7 +136,7 @@ function Lobby() {
gameStarted = true
//socket.off("player left")
//socket.off("new player")
navigate('/game?solo=false&daily=false');
navigate(`${basePath}/game?solo=false&daily=false`);
});
@ -170,7 +172,7 @@ function Lobby() {
setIndicesData(choosenIndices)
first = true
gameStarted = true
navigate('/game?solo=false&daily=false');
navigate(`${basePath}/game?solo=false&daily=false`)
});
socket.on("new player", (tab) =>{
@ -185,17 +187,17 @@ function Lobby() {
socket.on("room full", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
navigate(`${basePath}/`)
})
socket.on("game started", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
navigate(`${basePath}/`)
})
socket.on("game already started", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
navigate(`${basePath}/`)
})
socket.on("player left", (tab, i) => {
@ -227,7 +229,7 @@ function Lobby() {
const copyGameLink = () => {
setShow(!show)
const gameLink = "http://localhost:3000/lobby?room="+ room;
const gameLink = "http://172.20.10.4:3000/lobby?room="+ room;
navigator.clipboard.writeText(gameLink)
.then(() => {
console.log('Lien copié avec succès !');
@ -238,7 +240,7 @@ function Lobby() {
};
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const linkToCopy = "http://localhost:3000/lobby?room="+ room
const linkToCopy = "http://172.20.10.4:3000/lobby?room="+ room
const handleCopyClick = () => {
setShow(!show)
if(textAreaRef.current != null){
@ -336,9 +338,10 @@ function Lobby() {
style={{borderColor:theme.colors.secondary}}> - </button>
<input
// type="number"
style={{textAlign:'center'}}
id="numberInput"
disabled
value={ "Nombre de noeuds : " + enteredNumber}
value={enteredNumber}
onChange={handleNumberChange}
min={20}
max={60}/>

@ -5,6 +5,8 @@ import { useAuth } from '../Contexts/AuthContext';
import AuthService from '../services/AuthService';
import '../Style/Global.css';
import { Link } from 'react-router-dom';
import {basePath} from "../AdressSetup"
const SignIn = () => {
const navigate = useNavigate();
@ -35,7 +37,7 @@ const SignIn = () => {
setShowConfirmation(true);
setTimeout(async () => {
await login();
navigate('/');
navigate(`${basePath}/`);
}, 1250);
}
} catch (error: any) {
@ -78,7 +80,7 @@ const SignIn = () => {
</button>
</div>
<p className="forgot-password text-right">
<Link to="/signup">Pas encore inscrit ?</Link>
<Link href={`${basePath}/signup`}>Pas encore inscrit ?</Link>
</p>
</form>

@ -30,6 +30,8 @@ import { Overlay, ToggleButton, ToggleButtonGroup } from 'react-bootstrap';
import Button from 'react-bootstrap/Button';
import ButtonGroup from 'react-bootstrap/ButtonGroup';
import Lobbies from './Lobbies';
import {basePath} from "../AdressSetup"
let cptNavigation = 0
@ -97,7 +99,7 @@ function NewPlay() {
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=false');
navigate(`${basePath}/game?solo=true&daily=false`);
}
@ -128,12 +130,12 @@ function NewPlay() {
useEffect(() => {
if (room !== null) {
const nouvelleURL = `/lobby?room=${room}`;
navigate(nouvelleURL);
navigate(`${basePath}${nouvelleURL}`)
}
}, [room, navigate]);
const goBack = () => {
navigate("/lobby?room=" + goBackRoom)
navigate(`${basePath}/lobby?room=${goBackRoom}`)
}
@ -156,7 +158,7 @@ function NewPlay() {
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=true&easy=true');
navigate(`${basePath}/game?solo=true&daily=true&easy=true`);
setShowOverlay(false);
};
@ -174,7 +176,7 @@ function NewPlay() {
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
setDailyEnigmeData(map)
}
navigate('/game?solo=true&daily=true&easy=false');
navigate(`${basePath}/game?solo=true&daily=true&easy=false`);
setShowOverlay(false);
};

@ -30,6 +30,8 @@ import Button from 'react-bootstrap/Button';
import ButtonGroup from 'react-bootstrap/ButtonGroup';
import Info from '../res/icon/infoGreen.png';
import {basePath} from "../AdressSetup"
let cptNavigation = 0
@ -98,7 +100,7 @@ function Play() {
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=false');
navigate(`${basePath}/game?solo=true&daily=false`);
}
@ -129,12 +131,12 @@ function Play() {
useEffect(() => {
if (room !== null) {
const nouvelleURL = `/lobby?room=${room}`;
navigate(nouvelleURL);
navigate(`${basePath}${nouvelleURL}`);
}
}, [room, navigate]);
const goBack = () => {
navigate("/lobby?room=" + goBackRoom)
navigate(`${basePath}/lobby?room=${goBackRoom}`)
}
@ -157,7 +159,7 @@ function Play() {
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=true&easy=true');
navigate(`${basePath}/game?solo=true&daily=true&easy=true`);
setShowOverlay(false);
};
@ -175,7 +177,7 @@ function Play() {
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
setDailyEnigmeData(map)
}
navigate('/game?solo=true&daily=true&easy=false');
navigate(`${basePath}/game?solo=true&daily=true&easy=false`);
setShowOverlay(false);
};
@ -238,7 +240,7 @@ function Play() {
<button onClick={createLobby} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Créer une partie </button>
<button onClick= {() => navigate("/join")} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
<button onClick= {() => navigate(`${basePath}/join`)} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
</div>
</div>
<div className='rightContainer'>

@ -25,6 +25,8 @@ import Form from 'react-bootstrap/Form';
import ProgressBar from 'react-bootstrap/ProgressBar';
import {basePath} from "../AdressSetup"
//@ts-ignore
const Profile = () => {
const navigate = useNavigate();
@ -199,7 +201,7 @@ const Profile = () => {
}
handleCloseDeleteModal();
navigate("/")
navigate(`${basePath}/`)
} else {
console.error('Phrase de confirmation incorrecte.');

@ -4,6 +4,9 @@ import { useNavigate } from 'react-router-dom';
import AuthService from '../services/AuthService';
import '../Style/Global.css';
import {basePath} from "../AdressSetup"
const SignUp = () => {
const navigate = useNavigate();
const [error, setError] = useState<string | null>(null);
@ -31,7 +34,7 @@ const SignUp = () => {
setShowConfirmation(true);
setTimeout(() => {
navigate('/login'); // 3 secondes avant de rediriger vers la page de connexion
navigate(`${basePath}/login`); // 3 secondes avant de rediriger vers la page de connexion
}, 1250);
}
} catch (error: any) {
@ -88,7 +91,7 @@ const SignUp = () => {
</button>
</div>
<p className="forgot-password text-right">
Vous avez déjà un <a href="/login">compte</a> ?
Vous avez déjà un <a href={`${basePath}/login`}>compte</a> ?
</p>
</form>

@ -59,6 +59,16 @@
justify-content: center;
}
.playerNameDisplay{
display: flex;
align-items: center;
justify-content: center;
background-color:#fff;
border: solid 3px #0064E0;
border-radius: 15px;
width: 100%;
}
/**Form**/
.form-container {
/* background-color: #D7D4C6; */
@ -74,6 +84,8 @@ form{
columns: 2 auto;
}
/* LeaderBoard */
.LeaderBoardiv{
border: solid;

@ -76,7 +76,7 @@
"informations" : "Informations",
"info.intro.title":"Introduction au jeu :",
"info.intro.text":"Bienvenue dans notre jeu de déduction captivant, où l'intrigue et la malice se rejoignent dans une aventure palpitante ! Plongez-vous dans un monde de mystère et d'intrigue, où chaque interaction compte, et chaque indice vous rapproche de la vérité.Imaginez un graphique complexe où chaque sommet représente une personne, chaque axe une relation, et chaque détail compte. Vous êtes plongé dans un défi stimulant pour découvrir qui parmi ces individus est le mystérieux tueur. Chaque joueur détient un indice crucial, et seul le partage stratégique de ces indices vous mènera à la résolution du mystère. Explorez notre page de règles pour comprendre les subtilités du jeu, découvrez les indices qui peuvent vous guider, et élaborez des stratégies intelligentes pour identifier le coupable. Manipuler vos amis, afin d'être le premier à découvrir qui est le meurtrier ! Êtes-vous prêt à relever le défi et à démasquer le tueur caché dans le graphe ? Que l'enquête commence !",
"info.intro.text":"Bienvenue dans notre jeu de déduction captivant, où l'intrigue et la malice se rejoignent dans une aventure palpitante ! Plongez-vous dans un monde de mystère et d'intrigue, où chaque interaction compte, et chaque indice vous rapproche de la vérité.Imaginez un graphique complexe où chaque sommet représente une personne, chaque axe une relation, et chaque détail compte. Vous êtes plongé dans un défi stimulant pour découvrir qui parmi ces individus est le mystérieux coupable. Chaque joueur détient un indice crucial, et seul le partage stratégique de ces indices vous mènera à la résolution du mystère. Explorez notre page de règles pour comprendre les subtilités du jeu, découvrez les indices qui peuvent vous guider, et élaborez des stratégies intelligentes pour identifier le coupable. Manipuler vos amis, afin d'être le premier à découvrir qui est le meurtrier ! Êtes-vous prêt à relever le défi et à démasquer le coupable caché dans le graphe ? Que l'enquête commence !",
"info.sommaire":"Sommaire",
@ -122,7 +122,7 @@
"info.objectif.intro":"Bienvenue dans l'univers astucieux de notre jeu de déduction, où la tromperie et la ruse sont les clés du succès. Votre mission est de démêler le mystère qui se cache derrière chaque interaction du graphique complexe représentant les relations entre les individus.",
"info.objectif.t1":"Manipulation Subtile",
"info.objectif.t1.text":"Le but ultime est de découvrir qui parmi les individus est le tueur, mais pas par une collaboration ouverte. Au contraire, vous utiliserez la manipulation subtile pour brouiller les pistes et détourner l'attention de vos adversaires. Posez des questions stratégiques, répondez avec malice, et plantez des indices trompeurs pour vous rapprocher du dénouement.",
"info.objectif.t1.text":"Le but ultime est de découvrir qui parmi les individus est le coupable, mais pas par une collaboration ouverte. Au contraire, vous utiliserez la manipulation subtile pour brouiller les pistes et détourner l'attention de vos adversaires. Posez des questions stratégiques, répondez avec malice, et plantez des indices trompeurs pour vous rapprocher du dénouement.",
"info.objectif.t2":"Jeu de Duperie",
"info.objectif.t2.text":"Chaque tour offre l'opportunité de semer le doute parmi vos adversaires. Lorsqu'un joueur vous interroge, répondez en plaçant habilement un jeton carré pour indiquer que 'selon votre indice, cette personne ne peut être le coupable' ou un jeton rond pour suggérer qu'elle reste dans la liste des suspects. Soyez prudent, car chaque geste peut être interprété, et la vérité est souvent cachée derrière une façade d'indices trompeurs.",
"info.objectif.t3":"Contre-manipulation",
@ -135,7 +135,7 @@
"info.deroulement.e2":"Contre-manipulation et Contre-questions",
"info.deroulement.e2.text":"Si un joueur place un jeton carré, le questionneur doit également poser un jeton carré sur un nœud du graphique. Les contre-questions sont un moyen de semer la confusion parmi les joueurs et de détourner l'accusation.",
"info.deroulement.e3":"Le 'Guess' Final",
"info.deroulement.e3.text":"La partie atteint son apogée lorsqu'un joueur tente le 'Guess' final, affirmant que telle personne est le tueur. Les autres joueurs peuvent alors contredire cette affirmation en plaçant leurs propres jetons carrés. Si aucune réfutation n'est faite, le joueur ayant fait le 'Guess' remporte la partie, démontrant ainsi sa maîtrise dans l'art de la manipulation.",
"info.deroulement.e3.text":"La partie atteint son apogée lorsqu'un joueur tente le 'Guess' final, affirmant que telle personne est le coupable. Les autres joueurs peuvent alors contredire cette affirmation en plaçant leurs propres jetons carrés. Si aucune réfutation n'est faite, le joueur ayant fait le 'Guess' remporte la partie, démontrant ainsi sa maîtrise dans l'art de la manipulation.",
"info.indice-possible.age":"Âge d'une personne",
"info.indice-possible.hair":"Couleur de cheveux d'une personne",

Loading…
Cancel
Save