Compare commits

...

35 Commits

Author SHA1 Message Date
Thomas Chazot 2b31997bc7 remove bots on empty lobby
7 months ago
Thomas Chazot 19957da05c script pour setUp + fix pour localhost
7 months ago
Thomas Chazot f48168639a script pour setUp les adresses
7 months ago
Thomas Chazot d68b80d96d Merge branch 'notPossibleOnSquare' into demo_bourges
7 months ago
Thomas Chazot cb2e6570e3 Les bots ne peuvent plus le faire non plus
7 months ago
Pierre Ferreira 9b05d184ce changement de logique pour le partage du lien, cela devrait marcher sur Mac 🧪
7 months ago
Pierre Ferreira aaa2f237b7 affichage du nombre de tour dans le mode Enigme du jour
7 months ago
Pierre FERREIRA 7e46ea6e74 fix du problème qui empêché le joueur 1 à être demandé. 🚑
7 months ago
Thomas Chazot e1e7d6ef5c Utilisateur ne peut plus poser un carré lorsqu'il y a des déjà un carré et s'ils ne peuvent plus en poser passe son tour
7 months ago
Thomas Chazot 54f8f715b0 Pdp qui ne devrait pas bugger
7 months ago
Thomas Chazot d8b9337236 fix lorsque l'on doit poser un carré
7 months ago
Baptiste MARCEL e655ae2ab5 Merge branch 'modifNavbar' into demo_bourges
7 months ago
Baptiste MARCEL 3f9878bad0 Merge branch 'demo_bourges' of https://codefirst.iut.uca.fr/git/Crypteam/Cryptid into demo_bourges
7 months ago
Baptiste MARCEL 2faaaafa72 visualisation graphe sur la page endgame
7 months ago
Thomas CHAZOT be4b6db1b7 Mise à jour de 'cryptide_project/social_graph.sh'
7 months ago
Thomas Chazot 07ffe52c2b Suppression du log de la personne recherchée
7 months ago
Thomas Chazot 4836fff541 Bug fix des noms undefined
7 months ago
Pierre Ferreira cb31635a22 Merge branch 'demo_bourges' of https://codefirst.iut.uca.fr/git/Crypteam/Cryptid into demo_bourges
7 months ago
Pierre Ferreira 470899897b tueur -> coupable ✏️
7 months ago
Thomas Chazot 3aa121a2c2 Merge branch 'todoS5' into demo_bourges
7 months ago
Baptiste MARCEL d57416b9f8 Merge branch 'modifNavbar' into demo_bourges
7 months ago
Thomas Chazot c692f7b2ad Merge remote-tracking branch 'origin/demo_bourges' into testTodoS5
7 months ago
Baptiste MARCEL cbeb14257a bon affichage endgame même pas connecté
7 months ago
Thomas Chazot 466e3b7d0e fichier zip fini correctement + énigme différente avec téléchargement différente
7 months ago
Pierre Ferreira 6ddd2e5a29 changement du upperinfo 🎨
7 months ago
Baptiste MARCEL 92fa06313c Enlever choix niveau bot + correction faute
7 months ago
Thomas Chazot 3632320ffd Merge branch 'master' into testTodoS5
7 months ago
Baptiste MARCEL 86c4edfb94 Merge branch 'demo_bourges' of https://codefirst.iut.uca.fr/git/Crypteam/Cryptid into demo_bourges
7 months ago
Baptiste MARCEL a8409743e7 Bouton qui redirige à l'accueil sur page inGame
7 months ago
Thomas Chazot 9e928e624a Latex pour enigme facile et difficile + zip
7 months ago
Baptiste MARCEL be5c80de86 modification temps insc et connexion, modif redirection suppression compte
7 months ago
Baptiste MARCEL 33b2a6e3f3 Uniquement bouton retour accueil sur page endgame
7 months ago
Pierre Ferreira d747f63318 nettoyage des pages lobby, ingame, play et scoreboard :minus:
7 months ago
Baptiste MARCEL cff2a9b085 modification navbar + info dynamique
7 months ago
Baptiste MARCEL 2f4e0fc300 Suppression du choix des langues
7 months ago

@ -25,8 +25,11 @@
"express": "^4.18.2",
"express-session": "^1.17.3",
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
"jzip": "^1.0.0",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"path": "^0.12.7",
"react": "^18.2.0",
"react-bootstrap": "^2.9.1",
"react-country-flag": "^3.1.0",
@ -9905,6 +9908,11 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"node_modules/immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
@ -12612,6 +12620,54 @@
"node": ">=4.0"
}
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/jszip/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/jszip/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/jszip/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/jszip/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/jzip": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/jzip/-/jzip-1.0.0.tgz",
"integrity": "sha512-pyDHf5zvxE5DC47ftNff2AU3UdJe0TYSFki0Ji6GapuZC7p2EizIbPHV7dkLj43RPv2Vj3p1xwC11kDv6dyCrA=="
},
"node_modules/keycharm": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.4.0.tgz",
@ -12706,6 +12762,14 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@ -13939,6 +14003,11 @@
"node": ">=6"
}
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
},
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
@ -13998,6 +14067,15 @@
"tslib": "^2.0.3"
}
},
"node_modules/path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
"dependencies": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -15434,6 +15512,14 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -16744,6 +16830,11 @@
"node": ">= 0.4"
}
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@ -18357,6 +18448,14 @@
"requires-port": "^1.0.0"
}
},
"node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"dependencies": {
"inherits": "2.0.3"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -18376,6 +18475,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/util/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
},
"node_modules/utila": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",

@ -19,8 +19,11 @@
"express": "^4.18.2",
"express-session": "^1.17.3",
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
"jzip": "^1.0.0",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"path": "^0.12.7",
"react": "^18.2.0",
"react-bootstrap": "^2.9.1",
"react-country-flag": "^3.1.0",
@ -31,9 +34,9 @@
"react-router-hash-link": "^2.4.3",
"react-scripts": "5.0.1",
"react-switch": "^7.0.0",
"sqlite3": "^5.1.6",
"socket.io": "^4.7.2",
"socket.io-client": "^4.7.2",
"sqlite3": "^5.1.6",
"typescript": "^5.2.2",
"vis-network": "^9.1.9",
"web-vitals": "^2.1.4"

@ -7,7 +7,7 @@ const app = express();
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: ["http://172.20.10.4:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
origin: ["http://localhost:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
methods: ["GET", "POST"],
credentials: true
}
@ -93,6 +93,9 @@ io.on('connection', (socket) => {
if (tab[i].id === socket.id){
tab.splice(i, 1)
io.to(k).emit("player left", tab, i)
if (tab.filter((p) => p.type=="User").length == 0){
map.delete(k)
}
}
}
}
@ -114,6 +117,10 @@ io.on('connection', (socket) => {
io.to(id).emit("put imossible grey")
})
socket.on("can't put square", (askingPlayer, room) => {
io.to(room).emit("can't put square" , askingPlayer)
})
socket.on("opacity activated", (id) => {
io.to(id).emit("opacity activated")
})

@ -0,0 +1,15 @@
#!/bin/bash
# Vérifier si l'adresse IP est fournie en tant que paramètre
if [ -z "$1" ]; then
echo "Usage: $0 <adresse_ip>"
exit 1
fi
# Stocker l'adresse IP fournie en tant que variable
adresse_ip="$1"
# Utiliser l'adresse IP dans la commande find avec Perl
find . -type f -exec perl -pi -e 's|http://[0-9.]+:([0-9]+)|http://localhost:$1|g' {} +
find . -type f -exec perl -pi -e "s|http://localhost:([0-9]+)|http://$adresse_ip:\$1|g" {} +

@ -1,5 +1,6 @@
#!/bin/sh
npm install --force
if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null; then
# Tuer le processus associé au port

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

@ -77,10 +77,10 @@ function App() {
<BrowserRouter>
{hasNavbarVisible && <AppNavbar changeLocale={changeLocale} />}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/" element={<Play />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/play" element={<Play/>} />
<Route path="/home" element={<Home/>} />
<Route path="/lobby" element={<Lobby/>} />
<Route path="/endgame" element={<EndGame/>} />
<Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/>

@ -4,7 +4,7 @@ import GraphCreator from "../model/Graph/GraphCreator";
import "./GraphContainer.css";
import IndiceTesterFactory from "../model/Factory/IndiceTesterFactory";
import Person from "../model/Person";
import { Navigate, useLocation, useNavigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { useGame } from "../Contexts/GameContext";
import { socket } from "../SocketConfig"
import { colorToEmoji, positionToColor, positionToEmoji } from "../ColorHelper";
@ -12,6 +12,9 @@ import { ColorToHexa } from "../model/EnumExtender";
import Bot from "../model/Bot";
import NodePerson from "../model/Graph/NodePerson";
import { useAuth } from "../Contexts/AuthContext";
import Indice from "../model/Indices/Indice";
import Pair from "../model/Pair";
import { tab } from "@testing-library/user-event/dist/tab";
interface MyGraphComponentProps {
onNodeClick: (shouldShowChoiceBar: boolean) => void;
@ -27,12 +30,15 @@ interface MyGraphComponentProps {
setNetwork: (network: Network) => void
showLast: boolean
setPlayerIndex: (playerIndex: number) => void
setNetworkEnigme: (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => void
askedWrong: boolean
setAskedWrong: (askedWrong: boolean) => void
}
let lastAskingPlayer = 0
let lastNodeId = -1
let first = true
let askedWrong = false
let askedWrongLocal = false
let mapIndexPersons: Map<number, Person[]> = new Map<number, Person[]>()
let touchedPlayer = -1
let botIndex = -1
@ -46,16 +52,18 @@ let firstEnigme = true
let firstIndex = true
let endgame= false
let firstHistory = true
let cptSquare = 0
let cptOnAskedWrong = 0
const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleShowTurnBar, handleTurnBarTextChange, playerTouched, setPlayerTouched, changecptTour, solo, isDaily, isEasy, addToHistory, showLast, setNetwork, setPlayerIndex}) => {
const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleShowTurnBar, handleTurnBarTextChange, playerTouched, setPlayerTouched, changecptTour, solo, isDaily, isEasy, addToHistory, showLast, setNetwork, setPlayerIndex, setNetworkEnigme, askedWrong, setAskedWrong}) => {
let cptTour: number = 0
//* Gestion du temps :
let initMtn = 0
const {isLoggedIn, user, manager} = useAuth();
const { indices, indice, person, personNetwork, setNodeIdData, players, askedPersons, setActualPlayerIndexData, room, actualPlayerIndex, turnPlayerIndex, setTurnPlayerIndexData, setWinnerData, dailyEnigme, setNbCoupData, settempsData} = useGame();
const { indices, indice, person, personNetwork, setNodeIdData, players, askedPersons, setActualPlayerIndexData, room, actualPlayerIndex, turnPlayerIndex, setTurnPlayerIndexData, setWinnerData, dailyEnigme, setNbCoupData, settempsData, setNetworkDataData, setSeedData} = useGame();
const params = new URLSearchParams(window.location.search);
const navigate = useNavigate();
@ -83,12 +91,12 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
useEffect(() =>{
touchedPlayer=playerTouched
if (touchedPlayer == -1){
if (!askedWrong){
if (!askedWrongLocal){
socket.emit("put correct background", socket.id)
}
}
else if (touchedPlayer < players.length && touchedPlayer>=0){
if(!askedWrong){
if(!askedWrongLocal){
socket.emit("put correct background", socket.id)
socket.emit("put grey background", socket.id, touchedPlayer)
}
@ -165,6 +173,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
if(!works){
socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex)
const ind = bot.placeSquare(personNetwork, players)
if (ind == -1 ){
addToHistory(lastIndex.toString() + "177")
socket.emit("can't put square", lastIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -195,6 +208,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
console.log(lastIndex + " interroge " + choosedPlayerIndex + " a propos de " + person.getName() + " et dit non")
socket.emit("node checked", personIndex, false, choosedPlayerIndex, room, lastIndex)
const ind = bot.placeSquare(personNetwork, players)
if (ind == -1 ){
addToHistory(lastIndex.toString() + "212")
socket.emit("can't put square", playerIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -210,6 +228,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex])
if (!tester.Works(person)){
const ind = bot.placeSquare(personNetwork, players)
if (ind == -1 ){
addToHistory(lastIndex.toString() + "232")
socket.emit("can't put square", playerIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -282,16 +305,22 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
gravitationalConstant: -1000,
springConstant: 0.001,
springLength: 100
},
solver: "repulsion",
repulsion: {
nodeDistance: 100 // Put more distance between the nodes.
}
}
};
const networkData = { nodes: nodes, edges: graph.edges };
const network = new Network(container, networkData, initialOptions);
network.stabilize();
setNetwork(network)
setSeedData(network.getSeed())
if (isDaily){
setNetworkEnigme(dailyEnigme)
if (!isEasy){
dailyEnigme.forEach((pairs, index) => {
pairs.forEach((pair) => {
@ -391,11 +420,60 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
})
socket.on("asked wrong", () =>{
askedWrong = true
askedWrongBot=true
handleShowTurnBar(true)
handleTurnBarTextChange("Mauvais choix, posez un carré !")
socket.emit("put grey background", socket.id, actualPlayerIndex)
cptSquare++
if (cptSquare % 2 == 0){
if (indice==null){
return
}
const tester = IndiceTesterFactory.Create(indice)
const tabPossible: Person[] = []
for(const person of personNetwork.getPersons()){
const node = nodes.get().find((n) => n.id == person.getId())
if (node != undefined) {
let isSquare = false
players.forEach((p, index) => {
if (node.label.includes(positionToEmoji(index, false))){
isSquare=true
}
})
if (!tester.Works(person) && !isSquare){
tabPossible.push(person)
}
}
}
if (tabPossible.length>0){
askedWrongLocal= true
setAskedWrong(true)
askedWrongBot=true
handleShowTurnBar(true)
handleTurnBarTextChange("Mauvais choix, posez un carré !")
socket.emit("put grey background", socket.id, actualPlayerIndex)
}
else{
socket.emit("can't put square", actualPlayerIndex, room)
}
}
})
socket.on("can't put square", (askingPlayer) => {
cptOnAskedWrong ++
if (cptOnAskedWrong % 2 == 0){
addToHistory(players[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)
}
}
})
@ -414,7 +492,6 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
const node = nodes.get().find((n) => nodeId == n.id)
if (node != undefined && indice != null){
var tester = IndiceTesterFactory.Create(indice)
let maybe = actualPlayerIndex
if (tester.Works(pers)){
playerIndex = playerIndex + 1
if(playerIndex == players.length){
@ -423,10 +500,6 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("node checked", nodeId, true, actualPlayerIndex, room, playerIndex)
}
else{
maybe = actualPlayerIndex - 1
if(maybe == 0){
maybe = players.length - 1
}
let index = players.findIndex((p) => p.id == askingPlayer.id)
if (players[index] instanceof Bot){
index = playerIndex + 1
@ -474,9 +547,20 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
else if(indice != null){
//Pour poser un carré
const tester = IndiceTesterFactory.Create(indice)
for(const person of personNetwork.getPersons().filter((p) => tab.includes(p) || tester.Works(p))){
networkData.nodes.update({id: person.getId(), color: "#808080"})
for(const person of personNetwork.getPersons()){
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"})
}
}
}
}
@ -510,7 +594,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
cptEndgame++;
const currentPlayer = players[actualPlayerIndex];
const winner = players[winnerIndex];
setNetworkDataData(networkData)
setNodeIdData(-1)
setActualPlayerIndexData(-1)
setLastIndex(-1)
@ -520,7 +604,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
first = true
cptHistory = 0
askedWrong=false
askedWrongLocal=false
setAskedWrong(false)
askedWrongBot=false
endgame = true
firstHistory=true
@ -579,7 +664,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
if (a==indices.length){
//networkData.nodes.update({id: p.getId(), label: p.getName() + "\n🔵"})
console.log(p)
//console.log(p)
}
});
@ -601,11 +686,18 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
setNodeIdData(params.nodes[0])
// addToHistory("Le joueur a cliqué") //! TEST DEBUG
if (!solo){
if (askedWrong){
if (askedWrongLocal){
const person = personNetwork?.getPersons().find((p) => p.getId() == params.nodes[0])
if (person !== undefined && indice !== null){
const node = nodes.get().find((n) => n.id == params.nodes[0])
if (person !== undefined && indice !== null && node!=undefined){
const tester = IndiceTesterFactory.Create(indice)
if (!tester.Works(person) && !askedPersons.includes(person)){
let isSquare = false
players.forEach((p, index) => {
if (node.label.includes(positionToEmoji(index, false))){
isSquare=true
}
})
if (!tester.Works(person) && !askedPersons.includes(person) && !isSquare){
playerIndex = actualPlayerIndex + 1
if(playerIndex == players.length){
playerIndex = 0
@ -614,7 +706,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("put correct background", socket.id)
touchedPlayer=-1
askedPersons.push(person)
askedWrong = false
askedWrongLocal=false
setAskedWrong(false)
}
}
}
@ -641,7 +734,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
else{
if (touchedPlayer > 0){
if (touchedPlayer >= 0){
console.log(touchedPlayer)
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)
@ -721,6 +814,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
if (user!=null){
setWinnerData(user)
setNetworkDataData(networkData)
}
cptTour ++;
setNbCoupData(cptTour)
@ -749,7 +843,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
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;

@ -32,9 +32,6 @@ function AppNavbar({changeLocale}) {
const navigate = useNavigate();
useEffect(() => {
console.log(user)
}, [user])
function navigateToProfile(){
navigate("/profile")
@ -53,12 +50,15 @@ function AppNavbar({changeLocale}) {
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<NavDropdown title={<span style={{ color: theme.colors.text }}><FormattedMessage id="play" /></span>} className="navbar-title" id="basic-nav-dropdown">
<NavDropdown.Item href="play"><FormattedMessage id="play_solo" /> </NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="play"><FormattedMessage id="create_room" /> </NavDropdown.Item>
<NavDropdown.Item href="play"><FormattedMessage id="join" /> </NavDropdown.Item>
</NavDropdown>
<Nav.Link href="/" style={{ color: theme.colors.text }}>
Jouer
</Nav.Link>
<Nav.Link href="/home" style={{ color: theme.colors.text }}>
Présentation
</Nav.Link>
<Nav.Link href="/info" style={{ color: theme.colors.text }}>
Info
</Nav.Link>
</Nav>
<div className='leftdiv'>
<Nav className="ml-auto navbar-title-dd">
@ -70,7 +70,7 @@ function AppNavbar({changeLocale}) {
drop='down-centered'
>
<NavDropdown.Item onClick={navigateToProfile}>Profil</NavDropdown.Item>
<LanguageNavItem
{/* <LanguageNavItem
countryCode="FR"
languageKey="languageSelector.french"
onClick={() => changeLocale('fr')}
@ -79,7 +79,7 @@ function AppNavbar({changeLocale}) {
countryCode="GB"
languageKey="languageSelector.english"
onClick={() => changeLocale('en')}
/>
/> */}
<NavDropdown.Divider />
<NavDropdown.Item onClick={logout}>Déconnexion</NavDropdown.Item>
</NavDropdown>
@ -93,7 +93,7 @@ function AppNavbar({changeLocale}) {
<BsFillPersonPlusFill />
<FormattedMessage id="sign_up" />
</Nav.Link>
<LangDropDown changeLocale={changeLocale}/>
{/* <LangDropDown changeLocale={changeLocale}/> */}
</>
)}
</Nav>

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

@ -31,7 +31,7 @@ const PlayerItemList:React.FC<MyPlayerItemListProps> =({ player, room }) => {
// const isBot = pdp === Bot;
let pdp;
const isBot = player instanceof Bot;
isBot ? pdp = BotPDP : pdp = player.profilePicture;
isBot ? pdp = BotPDP : pdp = PersonPDP;
const delBot = () => {
@ -55,7 +55,7 @@ const PlayerItemList:React.FC<MyPlayerItemListProps> =({ player, room }) => {
</Button>
)}
</div>
{isBot && (
{/* {isBot && (
<ToggleButtonGroup type='radio' name={`options-${player.id}`} defaultValue={1}>
<ToggleButton id={`tbg-radio-1-${player.id}`} value={1}>
Facile
@ -67,7 +67,7 @@ const PlayerItemList:React.FC<MyPlayerItemListProps> =({ player, room }) => {
Fort
</ToggleButton>
</ToggleButtonGroup>
)}
)} */}
</div>
)
}

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

@ -32,11 +32,19 @@ const ScoreBoard: React.FC<{ Player: User }> = ({ Player }) => {
// <div className='LeaderBoardiv'>
<div className='LeaderBoardiv'>
<Tabs style={{width:"100%"}}
defaultActiveKey="daily"
defaultActiveKey="perso"
id="ScoreBoard"
className="mb-3">
<Tab eventKey="perso" title="Vos Stats" disabled = { !Player.pseudo.startsWith("Guest_") ? false : true}>
<Container fluid>
<Tab eventKey="perso" title="Vos Stats">
{ Player.pseudo.startsWith("Guest_") ? (
<div className='guestDisplay'>
<h4>
<i>Veuillez vous connecter pour bénéficier des statistiques personnalisées.</i>
</h4>
</div>
) : (
<Container fluid>
<Row>Stats en solo :</Row>
<Row>
<Col sm={10}>Partie Jouées :</Col>
@ -65,8 +73,9 @@ const ScoreBoard: React.FC<{ Player: User }> = ({ Player }) => {
<Col className='leftRow'>{Player !== null ? Player.onlineStats.ratio : "0"}</Col>
</Row>
</Container>
)}
</Tab>
<Tab eventKey="daily" title="Daily"
{/* <Tab eventKey="daily" title="Daily"
style={{display:"flex", flexDirection:'column', alignItems:'center'}}>
<img src={trophy}
height='100'
@ -101,10 +110,10 @@ const ScoreBoard: React.FC<{ Player: User }> = ({ Player }) => {
height='100'
width='100'
alt="Person2"/>
</Tab>
</Tab> */}
</Tabs>
<ButtonImgNav dest='/' img={share}/>
{/* <ButtonImgNav dest='/' img={share}/> */}
</div>
//</div>
);

@ -21,6 +21,8 @@ interface GameContextProps {
dailyEnigme: Map<number, Pair<Indice, boolean>[]>
nbCoup : number
temps : number
networkData: any
seed: number | string;
setIndicesData: (newIndices: Indice[]) => void;
setIndiceData: (newIndice: Indice) => void;
setPersonData: (newPerson: Person) => void;
@ -37,6 +39,8 @@ interface GameContextProps {
setDailyEnigmeData: (map: Map<number, Pair<Indice, boolean>[]>) => void
setNbCoupData: (newNbCoup : number) => void
settempsData: (newtemps : number) => void
setNetworkDataData: (networkData: any) => void
setSeedData: (seed: number | string) => void
}
const GameContext = createContext<GameContextProps | undefined>(undefined);
@ -61,7 +65,16 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
const [dailyEnigme, setDailyEnigme] = useState<Map<number, Pair<Indice, boolean>[]>>(new Map())
const [nbCoup, setNbCoup] = useState<number>(0);
const [temps, settemps] = useState<number>(0);
const [networkData, setNetworkData] = useState<any>(null);
const [seed, setSeed] = useState<number | string>(0);
const setNetworkDataData = (networkData: any) => {
setNetworkData(networkData);
}
const setSeedData = (seed: number | string) => {
setSeed(seed);
}
const setIndicesData = (newIndices: Indice[]) => {
setIndices(newIndices);
@ -142,7 +155,7 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
}
return (
<GameContext.Provider value={{ indices, setIndicesData, indice, setIndiceData, person, setPersonData, personNetwork, setPersonNetworkData, players, setPlayersData, nodeId, setNodeIdData, askedPersons, setAskedPersonsData, actualPlayerIndex, setActualPlayerIndexData, turnPlayerIndex, setTurnPlayerIndexData, room, setRoomData, onlyFalse, setOnlyFalseData, winner, setWinnerData, reset, dailyEnigme, setDailyEnigmeData, nbCoup, setNbCoupData, temps, settempsData}}>
<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}}>
{children}
</GameContext.Provider>
);

@ -1,4 +1,3 @@
.head{
display: flex;
justify-content: center;
@ -114,4 +113,11 @@
background-color: white;
padding: 10px;
}
}
#vis-graph {
height: 500px;
margin: 50px;
border: 2px solid #ccc;
overflow: hidden;
}

@ -1,4 +1,4 @@
import React from 'react';
import React, {useEffect} from 'react';
/* Style */
@ -15,20 +15,50 @@ import Replay from '../res/icon/replay.png';
import PersonStatus from '../Components/PersonStatus';
import ButtonImgNav from '../Components/ButtonImgNav';
import BigButtonNav from '../Components/BigButtonNav';
import { Button } from 'react-bootstrap';
import { Network } from "vis-network/standalone/esm/vis-network";
/* nav */
import { Link } from 'react-router-dom';
/* lang */
import { FormattedMessage } from 'react-intl';
import { useGame } from '../Contexts/GameContext';
import { map } from 'lodash';
import Player from '../model/Player';
function EndGame() {
const {networkData, seed} = useGame();
const params = new URLSearchParams(window.location.search);
const initialOptions = {
layout: {
improvedLayout: true,
randomSeed: seed,
hierarchical: {
enabled: false,
direction: 'LR', // LR (Left to Right) ou autre selon votre préférence
sortMethod: 'hubsize'
},
//randomSeed: 2
},
physics: {
enabled: true,
barnesHut: {
gravitationalConstant: -1000,
springConstant: 0.001,
springLength: 100
}
}
};
useEffect(() => {
const container = document.getElementById("vis-graph");
if (!container) {
console.error("Container not found");
return;
}
const network = new Network(container, networkData, initialOptions);
console.log(networkData)
}, []);
//* Gestion solo
let IsSolo: boolean = false
@ -73,8 +103,6 @@ function EndGame() {
}
const theme = useTheme();
console.log(winner)
console.log(indices)
return (
<div>
{!IsSolo ? (
@ -82,7 +110,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'>
@ -90,24 +118,24 @@ function EndGame() {
<h3 className='indiceDisplay'>{indices[players.findIndex((p) => p.id == winner?.id)].ToString("fr")}</h3>
</div>
<div className='bottomEnd'>
<div className='centerDivH' onClick={resetAll}>
{/* <div className='centerDivH' onClick={resetAll}>
<BigButtonNav dest="/play" img={Leave}/>
</div>
</div> */}
<div className="losingPlayersContainer">
{losingPlayers.map((player, index) => (
<div className="playerContainer" key={index}>
{player.id !== winner?.id && (
<div>
<PersonStatus img={Person} state={Person} key={index} name={player.pseudo} playerTouched={1} setPlayerTouched={() => {}} index={index} playerIndex={-2} showCircle={false}/>
<PersonStatus img={Person} state={Person} key={index} name={player.pseudo} playerTouched={1} setPlayerTouched={() => {}} index={index} playerIndex={-2} showCircle={false} askedWrong={false}/>
<h6 className='indiceDisplay'>{indices[players.findIndex((p) => p.id == player?.id)].ToString("fr")}</h6>
</div>
)}
</div>
))}
</div>
<div className='centerDivH'>
{/* <div className='centerDivH'>
<BigButtonNav dest="/lobby" img={Replay}/>
</div>
</div> */}
</div>
</div>
): (
@ -115,7 +143,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'>
@ -124,9 +152,6 @@ function EndGame() {
</div>
<div className='bottomEnd'>
<div className='centerDivH' onClick={resetAll}>
<BigButtonNav dest="/play" img={Leave}/>
</div>
<div className="SoloContainer">
<div className='solostat'>
{!IsDaily && <p>Nombre de coups : {nbCoup}</p> }
@ -143,12 +168,20 @@ function EndGame() {
}
</div>
</div>
<div className='centerDivH'>
{/* <div className='centerDivH'>
<BigButtonNav dest="/lobby" img={Replay}/>
</div>
</div> */}
</div>
</div>
)}
<div id="vis-graph"/>
<div className='centerDivH' onClick={resetAll} style={{margin: "20px"}}>
<Button href='/'>Retour à l'accueil</Button>
</div>
</div>
);
}

@ -9,6 +9,8 @@ import { FormattedMessage } from 'react-intl';
import ButtonImgNav from '../Components/ButtonImgNav';
import defaultImg from "../res/img/Person.png"
import {loadImageAsync} from "../ImageHelper"
import { socket } from '../SocketConfig';
import JSONParser from '../JSONParser';
// @ts-ignore
@ -47,7 +49,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>

@ -1,10 +1,11 @@
.upperInfo{
display: flex;
justify-content: center;
flex-direction: column;
justify-content: center;
align-items: center;
width: 30%;
width: 35%;
height: 50px;
border-radius: 0px 0px 30px 30px;
border: solid;
@ -12,9 +13,9 @@
background-color: white;
font-size: 30px;
font-size: 25px;
top: 20px;;
top: 0;
}
#mainDiv{
@ -154,4 +155,21 @@
height: 250px;
width: 20%;
overflow-y:auto;
}
}
#bottom-container {
/* Ajout du style pour le conteneur en bas à droite */
position: fixed;
bottom: 0;
right: 0;
margin: 20px;
}
.bottomRightButton {
/* Style pour le bouton en bas à droite */
position: absolute;
bottom: 0;
right: 0;
margin: 10px;
}

@ -25,6 +25,12 @@ import Download from "../res/icon/download.png"
import Reset from "../res/icon/reset.png";
import Oeye from "../res/icon/eye.png";
import Ceye from "../res/icon/hidden.png";
import JSZip from 'jszip';
import ballonDeBasket from '../Script/ballon-de-basket.png';
import ballonDeFoot from '../Script/ballon-de-foot.png';
import baseball from '../Script/baseball.png';
import bowling from '../Script/bowling.png';
import tennis from '../Script/tennis.png';
/* nav */
import { Link } from 'react-router-dom';
@ -40,12 +46,11 @@ import { Nav, NavDropdown, Spinner } from 'react-bootstrap';
import { FormattedMessage } from 'react-intl';
import Color from '../model/Color';
import { useGame } from '../Contexts/GameContext';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { NavLink } from 'react-router-dom';
import { last } from 'lodash';
import { socket } from '../SocketConfig';
import { Network } from 'vis-network';
import generateLatexCode from '../Script/LatexScript';
import {generateLatexCode, generateLatexCodeEnigme} from '../Script/LatexScript';
import Pair from '../model/Pair';
import Indice from '../model/Indices/Indice';
//@ts-ignore
const InGame = ({locale, changeLocale}) => {
@ -77,6 +82,7 @@ const InGame = ({locale, changeLocale}) => {
//* Historique
const [history, setHistory] = useState<string[]>([]);
const [showLast, setShowLast] = useState(false)
const [askedWrong, setAskedWrong] = useState(false)
// Fonction pour ajouter un élément à l'historique
const addToHistory = (message: string) => {
@ -88,6 +94,10 @@ const InGame = ({locale, changeLocale}) => {
setShowLast(!showLast);
}
const setAskedWrongData = (askedWrong: boolean) => {
setAskedWrong(askedWrong)
}
useEffect(() => {
const historyContainer = document.getElementById('history-container');
if (historyContainer) {
@ -106,11 +116,16 @@ const InGame = ({locale, changeLocale}) => {
const [network, setNetwork] = useState<Network | null>(null)
const [networkEnigme, setNetworkEnigme] = useState<Map<number, Pair<Indice, boolean>[]> | null>(null)
const setNetworkData = (network: Network) => {
setNetwork(network)
}
const setNetworkEnigmeData = (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => {
setNetworkEnigme(networkEnigme)
}
const handleNodeClick = (shouldShowChoiceBar: boolean) => {
setShowChoiceBar(shouldShowChoiceBar);
};
@ -132,16 +147,42 @@ const InGame = ({locale, changeLocale}) => {
setPlayerIndex(playerIndex)
}
const generateTEX = () => {
const generateTEX = async () => {
if (network != null && personNetwork != null && person != null){
const tex = generateLatexCode(personNetwork, person, indices, network)
const blob = new Blob([tex], { type: 'application/x-latex;charset=utf-8' });
// Utiliser FileSaver pour télécharger le fichier
saveAs(blob, 'socialGraph.tex');
const zip = new JSZip();
if (isDaily && !isEasy && networkEnigme != null){
const tex = generateLatexCodeEnigme(personNetwork, person, indices, network, networkEnigme)
const blob = new Blob([tex], { type: 'application/x-latex;charset=utf-8' });
zip.file('socialGraph.tex', tex);
}
else{
const tex = generateLatexCode(personNetwork, person, indices, network)
const blob = new Blob([tex], { type: 'application/x-latex;charset=utf-8' });
zip.file('socialGraph.tex', tex);
}
zip.file('ballon-de-basket.png', await fetchImage(ballonDeBasket));
zip.file('ballon-de-foot.png', await fetchImage(ballonDeFoot));
zip.file('baseball.png', await fetchImage(baseball));
zip.file('bowling.png', await fetchImage(bowling));
zip.file('tennis.png', await fetchImage(tennis));
const content = await zip.generateAsync({ type: 'blob' });
// Enregistre l'archive en tant que fichier
saveAs(content, 'social_graph.zip');
}
}
const fetchImage = async (imageUrl: string) => {
const response = await fetch(imageUrl);
const blob = await response.blob();
return blob;
};
const resetGraph = () => {
setisLoading(true);
socket.emit("reset graph", socket.id)
@ -235,12 +276,15 @@ const InGame = ({locale, changeLocale}) => {
setPlayerTouched={handleSetPlayerTouched}
playerTouched={playerTouched}
setNetwork={setNetworkData}
setNetworkEnigme={setNetworkEnigmeData}
showLast={showLast}
setPlayerIndex={setPlayerIndexData}/>
setPlayerIndex={setPlayerIndexData}
askedWrong={askedWrong}
setAskedWrong={setAskedWrongData}/>
</div>
{IsSolo && !isDaily &&
{IsSolo &&
<div className='nbLaps' style={{
backgroundColor: theme.colors.primary,
borderColor: theme.colors.secondary
@ -257,7 +301,7 @@ const InGame = ({locale, changeLocale}) => {
</div>
}
<div className='paramDiv'>
{/* <div className='paramDiv'>
<button className='button'
style={{
backgroundColor: theme.colors.tertiary,
@ -266,7 +310,7 @@ const InGame = ({locale, changeLocale}) => {
onClick={handleChangeS}>
<img src={Param} alt="paramètres" height='40'/>
</button>
</div>
</div> */}
@ -365,7 +409,7 @@ const InGame = ({locale, changeLocale}) => {
{ !IsSolo &&
<div className='playerlistDiv'>
<PlayerList players={players} setPlayerTouched={handleSetPlayerTouched} playerTouched={playerTouched} playerIndex={playerIndex}/>
<PlayerList players={players} setPlayerTouched={handleSetPlayerTouched} playerTouched={playerTouched} playerIndex={playerIndex} askedWrong={askedWrong}/>
</div>
}
@ -374,7 +418,7 @@ const InGame = ({locale, changeLocale}) => {
placement='end'
scroll={true}
backdrop={false}
style={{ height: '20%', width: '25%', top: '60vh' }}>
style={{ height: '20%', width: '25%', top: '0' }}>
<Offcanvas.Header closeButton>
<Offcanvas.Title>Indice</Offcanvas.Title>
</Offcanvas.Header>
@ -420,6 +464,12 @@ const InGame = ({locale, changeLocale}) => {
<ButtonImgNav dest="/endgame" img={Leave} text='endgame'/>
</div>
*/}
<div id="bottom-container">
{/* Ajout du bouton en bas à droite */}
<div className='bottomRightButton'>
<Button href='/'>Retour à l'accueil</Button>
</div>
</div>
</div>
);
};

@ -24,12 +24,13 @@ import Alert from 'react-bootstrap/Alert';
import MGlass from "../res/icon/magnifying-glass.png";
import Param from "../res/icon/param.png";
import Info from "../res/icon/infoGreen.png"; //todo changer la couleur de l'icon
import { useAuth } from '../Contexts/AuthContext';
import { useEffect } from 'react';
//@ts-ignore
function InfoPage({locale, changeLocale}) {
function InfoPage({locale, changeLocale}) {
const theme = useTheme();
const {isLoggedIn, login, user, setUserData, manager } = useAuth();
const styles = {
roux: { backgroundColor: ColorToHexa(Color.REDHEAD), width: '15px', height: '15px', display: 'inline-block', marginRight: '5px' },
blond: { backgroundColor: ColorToHexa(Color.BLOND), width: '15px', height: '15px', display: 'inline-block', marginRight: '5px' },
@ -37,6 +38,20 @@ function InfoPage({locale, changeLocale}) {
blanc: { backgroundColor: ColorToHexa(Color.WHITE), border: '1px solid #ccc', width: '15px', height: '15px', display: 'inline-block', marginRight: '5px' },
chatain: { backgroundColor: ColorToHexa(Color.BROWN), width: '15px', height: '15px', display: 'inline-block', marginRight: '5px' },
};
useEffect(() => {
if (user == null){
manager.userService.fetchUserInformation().then(([user, loggedIn]) =>{
if (user!=null){
if (loggedIn){
login()
setUserData(user)
}
}
})
}
}, [isLoggedIn]);
return (
//! Il faudra possiblement faire une gestion des mode de jeu, pour modifier les regles en fonction de ce dernier.
<div className='infoPage'>

@ -59,4 +59,14 @@
.centerButton {
display: flex;
justify-content: center;
}
.lobbyR{
display: flex;
flex-direction: column;
align-items: center;
}
.lobbyR *{
margin: 20px 10px;
}

@ -43,6 +43,11 @@ import { random } from 'lodash';
import SessionService from '../services/SessionService';
import { useRef } from 'react';
import Button from 'react-bootstrap/Button';
import Overlay from 'react-bootstrap/Overlay';
let gameStarted = false
function Lobby() {
@ -159,6 +164,36 @@ function Lobby() {
socket.emit('network created', JSON.stringify(networkPerson, null, 2), JSON.stringify(choosenPerson), JSON.stringify(choosenIndices), room, start);
}
const copyGameLink = () => {
setShow(!show)
const gameLink = "http://localhost:3000/lobby?room="+ room;
navigator.clipboard.writeText(gameLink)
.then(() => {
console.log('Lien copié avec succès !');
})
.catch((err) => {
console.error('Erreur lors de la copie du lien :', err);
});
};
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const linkToCopy = "http://localhost:3000/lobby?room="+ room
const handleCopyClick = () => {
setShow(!show)
if(textAreaRef.current != null){
textAreaRef.current.select();
document.execCommand('copy');
}
};
const [show, setShow] = useState(false);
const target = useRef(null);
return (
<div className='lobby-container'>
<div className='left-part'>
@ -191,22 +226,22 @@ function Lobby() {
<div className="lobby-vertical-divider" style={{backgroundColor: theme.colors.secondary}}></div>
<div className='right-part'>
<div className='title-param-div'>
{/* <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>
<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> {/* mettre un dropdown ou un swiper */}
<li><h4>Thèmes : basique </h4></li> {/* mettre un dropdown*/}
<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>
{/* </ul> */}
{/* <center >
<button className='buttonNabImg' onClick={StartGame}>
<img src={cible} alt="Button Image" height="50" width="50" />
@ -214,13 +249,58 @@ function Lobby() {
</button>
</center> */}
<div className='centerDivH'>
<div className='lobbyR'
style={{flexDirection:'column',
alignItems:'space-around'}}>
<h3>Bienvenue dans votre lobby !</h3>
<p>Attendez que tous vos amis rejoignent avant de lancer la partie.</p>
{/* Bouton pour copier le lien */}
{/* <Button variant="primary" ref={target} onClick={copyGameLink}>
Inviter des amis
</Button> */}
<div>
<textarea
ref={textAreaRef}
readOnly
value={linkToCopy}
style={{ position: 'absolute', left: '-9999px' }}
/>
<Button onClick={handleCopyClick}>Inviter des amis</Button>
</div>
<Overlay target={target.current} show={show} placement="top">
{({
placement: _placement,
arrowProps: _arrowProps,
show: _show,
popper: _popper,
hasDoneInitialMeasure: _hasDoneInitialMeasure,
...props
}) => (
<div
{...props}
style={{
position: 'absolute',
backgroundColor: theme.colors.secondary,
padding: '2px 10px',
color: 'white',
borderRadius: 3,
...props.style,
}}
>
Lien copié
</div>
)}
</Overlay>
<button className='button' onClick={StartGame}
style={{
backgroundColor: theme.colors.tertiary,
borderColor: theme.colors.secondary
borderColor: theme.colors.secondary,
width: 'auto',
height: 'auto'
}}>
<img src={cible} alt="cible" height="40"/>
Démarrer la partie !
</button>
</div>
</div>

@ -36,8 +36,8 @@ const SignIn = () => {
setShowConfirmation(true);
setTimeout(async () => {
await login();
navigate('/play'); // 3 secondes avant de rediriger vers la page de connexion
}, 3000);
navigate('/'); // 3 secondes avant de rediriger vers la page de connexion
}, 1250);
}
} catch (error: any) {
setError(error.message);
@ -103,8 +103,8 @@ const SignIn = () => {
)}
{showConfirmation && (
<div className="alert alert-success" role="alert">
Connexion réussie ! Vous serez redirigé vers votre profil dans 3 secondes.
<div className="alert alert-success text-center" role="alert">
Connexion réussie ! Vous allez être redirigé vers la page principale.
</div>
)}
</div>

@ -70,4 +70,18 @@
border-width: 2px;
font-size:larger;
}
.guestDisplay{
display: flex;
justify-content: center;
align-items: center;
/* flex-direction: column; */
margin: 20px;
padding: 15px;
border: solid 1px whitesmoke;
border-radius: 15px;
background-color: white;
}

@ -119,14 +119,12 @@ function Play() {
socket.emit("lobby created")
}
useEffect(() => {
console.log(user)
}, [user])
function launchMastermind(){
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(3, 30)
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
console.log(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=false');
@ -182,8 +180,6 @@ function Play() {
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=true&easy=true');
setShowOverlay(false);
};
@ -196,7 +192,6 @@ function Play() {
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
if (first){
first = false
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
@ -253,7 +248,7 @@ function Play() {
<button onClick={createLobby} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Créer une partie </button>
<button className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
{/* <button className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button> */}
</div>
</div>

@ -84,7 +84,6 @@ const Profile = () => {
// Verification de la phrase
if (confirmationPhrase.toLowerCase() === 'supprimer mon compte') {
console.log('Compte supprimé !');
console.log(user);
if(user!= null){
const pseudo = user.pseudo;
@ -97,7 +96,7 @@ const Profile = () => {
}
handleCloseDeleteModal();
navigate("/play")
navigate("/")
} else {
console.error('Phrase de confirmation incorrecte.');

@ -33,7 +33,7 @@ const SignUp = () => {
setShowConfirmation(true);
setTimeout(() => {
navigate('/login'); // 3 secondes avant de rediriger vers la page de connexion
}, 3000);
}, 1250);
}
} catch (error: any) {
setError(error.message);
@ -100,8 +100,8 @@ const SignUp = () => {
)}
{showConfirmation && (
<div className="alert alert-success" role="alert">
Inscription réussie ! Vous serez redirigé vers la page de connexion dans 3 secondes.
<div className="alert alert-success text-center" role="alert">
Inscription réussie ! Vous serez redirigé vers la page de connexion.
</div>
)}
</div>

@ -10,19 +10,18 @@ import Indice from "../model/Indices/Indice";
import { ColorToString, SportToString } from "../model/EnumExtender";
import GraphCreator from "../model/Graph/GraphCreator";
import { DataSet, Network } from "vis-network";
import Pair from "../model/Pair";
function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, choosenIndices : Indice[], network: Network): string {
let latexCode = "";
//*Setup
latexCode += "\\documentclass[11pt]{article}\n"
latexCode += "\\usepackage[landscape]{geometry}\n"
latexCode += "\\usepackage{fullpage}\n"
latexCode += "\\usepackage{times}\n"
latexCode += "\\usepackage{tikz}\n"
latexCode += "\\usepackage{paralist}\n"
latexCode += "\\usepackage{geometry}\n"
latexCode += "\\usetikzlibrary {shapes.multipart}\n"
latexCode += "\\geometry{margin=0.5cm}\n"
latexCode += "\\newcommand{\\Basketball}{\\includegraphics[width=.5cm]{ballon-de-basket.png}}\n"
@ -37,7 +36,8 @@ function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, c
latexCode+= "\\thispagestyle{empty}\n"
latexCode+= "Voici le graphe de SocialGraphe\n"
latexCode+= "\\begin{center}\n"
latexCode+= "\\begin{tikzpicture}[scale=.17]\n"
latexCode+= "\\resizebox{.65\\textwidth}{!}{\n"
latexCode+= "\\begin{tikzpicture}[scale=.18]\n"
personsNet.getPersons().forEach((person, index) => {
@ -47,8 +47,8 @@ function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, c
const nodeId = person.getId().toString();
const position = nodesData[nodeId];
if (position) {
const x = (position.x / 9).toFixed(2); // Arrondir à 2 décimales
const y = (position.y / 9).toFixed(2);
const x = (position.x / 5).toFixed(2); // Arrondir à 2 décimales
const y = (position.y / 5).toFixed(2);
latexCode += ` \\node[draw, circle split, align=center] (${person.getId()}) at (${x},${y}) { ${person.getName()} ${person.getAge()} \\nodepart{lower}`;
latexCode += `${ColorToString(person.getColor(), "fr")} \\\\`
@ -63,10 +63,10 @@ function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, c
person.getFriends().forEach((friend) => {
latexCode += ` \\draw (${person.getId()}) -- (${friend.getId()});\n`;
});
console.log(person.getFriends().length);
});
latexCode += "\\end{tikzpicture}\n";
latexCode += "}\n"
latexCode += "\\end{center}\n";
//* Zone d'énoncé :
@ -81,6 +81,114 @@ function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, c
choosenIndices.forEach((indice, index) => {
latexCode += `\\item Indice ${index + 1} : ${indice.ToString('fr')}.\n`
console.log("coucou")
console.log(indice.ToString("fr"))
})
latexCode += "\\end{compactitem}\n"
//* Solution
latexCode += "% Solution : " + choosenPerson.getName() + "\n";
latexCode += "\\end{document}\n"
return latexCode
}
function generateLatexCodeEnigme(personsNet : PersonNetwork, choosenPerson : Person, choosenIndices : Indice[], network: Network, map : Map<number, Pair<Indice, boolean>[]>): string {
let latexCode = "";
//*Setup
latexCode += "\\documentclass[11pt]{article}\n"
latexCode += "\\usepackage[landscape]{geometry}\n"
latexCode += "\\usepackage{fullpage}\n"
latexCode += "\\usepackage{times}\n"
latexCode += "\\usepackage{tikz}\n"
latexCode += "\\usepackage{paralist}\n"
latexCode += "\\usepackage{geometry}\n"
latexCode += "\\usetikzlibrary {shapes.multipart}\n"
latexCode += "\\geometry{margin=0.5cm}\n"
latexCode += "\\newcommand{\\Basketball}{\\includegraphics[width=.5cm]{ballon-de-basket.png}}\n"
latexCode += "\\newcommand{\\Football}{\\includegraphics[width=.4cm]{ballon-de-foot.png}}\n"
latexCode += "\\newcommand{\\Bowling}{\\includegraphics[width=.5cm]{bowling.png}}\n"
latexCode += "\\newcommand{\\Baseball}{\\includegraphics[width=.5cm]{baseball.png}}\n"
latexCode += "\\newcommand{\\Tennis}{\\includegraphics[width=.5cm]{tennis.png}}\n"
//** Header
latexCode+= "\\begin{document}\n"
latexCode+= "\\thispagestyle{empty}\n"
latexCode+= "Voici le graphe de SocialGraphe\n"
latexCode+= "\\begin{center}\n"
latexCode+= "\\resizebox{.65\\textwidth}{!}{\n"
latexCode+= "\\begin{tikzpicture}[scale=.18]\n"
personsNet.getPersons().sort().forEach((person, index) => {
var nodesData = network.getPositions();
// Obtenir les coordonnées du nœud
const nodeId = person.getId().toString();
const position = nodesData[nodeId];
if (position) {
const x = (position.x / 9).toFixed(2); // Arrondir à 2 décimales
const y = (position.y / 9).toFixed(2);
latexCode += ` \\node[draw, circle split, align=center] (${person.getId()}) at (${x},${y}) { ${person.getName()} ${person.getAge()} \\nodepart{lower}`;
latexCode += `${ColorToString(person.getColor(), "fr")} \\\\`
person.getSports().forEach((sport) => { latexCode += ` \\${SportToString(sport, 'fr')}{}` });
latexCode += "};\n";
} else {
console.error(`Les coordonnées du nœud ${nodeId} ne sont pas disponibles.`);
}
});
personsNet.getPersons().forEach((person) => {
person.getFriends().forEach((friend) => {
latexCode += ` \\draw (${person.getId()}) -- (${friend.getId()});\n`;
});
});
latexCode += "\\end{tikzpicture}\n";
latexCode += "}\n"
latexCode += "\\end{center}\n";
//* Zone d'énoncé :
latexCode += "\n\n\\paragraph{Première énigme}\n"
latexCode += "Trouver qui est le coupable avec les indices suivants.\n"
latexCode += "\\begin{compactitem}\n"
const personIndice = new Map<number, string[]>()
choosenIndices.forEach((i, index) => {
personIndice.set(index, [])
})
map.forEach((pairs, index) => {
pairs.forEach((pair) => {
const person = personsNet.getPersons().find((n) => index == n.getId())
const indice = choosenIndices.findIndex((i) => pair.first.getId() == i.getId())
if (person != undefined && indice != -1){
let string = "L'indice numéro " + (indice + 1) + " répond "
if (pair.second){
string += "vrai "
}
else{
string += "faux "
}
string += "pour " + person.getName()
personIndice.get(indice)?.push(string)
}
})
});
personIndice.forEach((indices, index) => {
latexCode += `\\item Indice ${index + 1}:\n`
indices.forEach((string) => {
latexCode += `\\item ${string}.\n`
})
})
latexCode += "\\end{compactitem}\n"
@ -92,4 +200,4 @@ function generateLatexCode(personsNet : PersonNetwork, choosenPerson : Person, c
return latexCode
}
export default generateLatexCode
export {generateLatexCode, generateLatexCodeEnigme}

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

@ -13,8 +13,6 @@ class EnigmeDuJourCreator{
map.set(p.getId(), [])
})
console.log("START ENIGME")
choosenIndices.forEach((choosenIndice) => {
const choosenIndiceTester = IndiceTesterFactory.Create(choosenIndice)
const modifiedPersons: Pair<Person, boolean>[] = []

@ -17,7 +17,7 @@ class NetworkGenerator{
const tabPerson: Person[] = []
const tabNames = json.names
const tabNames = [...json.names]
/*
let id = 0

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

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