versionpostpull
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:latest
|
image: nginx:latest
|
||||||
|
|||||||
@ -6,7 +6,7 @@ DJANGO_ALLOWED_HOSTS=['*']
|
|||||||
# PostgreSQL settings
|
# PostgreSQL settings
|
||||||
POSTGRES_DB=players_db
|
POSTGRES_DB=players_db
|
||||||
POSTGRES_USER=42student
|
POSTGRES_USER=42student
|
||||||
POSTGRES_PASSWORD=postgre_pass
|
POSTGRES_PASSWORD=
|
||||||
|
|
||||||
# Django settings
|
# Django settings
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
@ -20,11 +20,11 @@ CLUSTER_NAME=docker-cluster
|
|||||||
LICENSE=basic
|
LICENSE=basic
|
||||||
|
|
||||||
ELASTIC_USERNAME=elastic
|
ELASTIC_USERNAME=elastic
|
||||||
ELASTIC_PASSWORD=elastic_pass
|
ELASTIC_PASSWORD=
|
||||||
|
|
||||||
# Kibana settings
|
# Kibana settings
|
||||||
KIBANA_PORT=5601
|
KIBANA_PORT=5601
|
||||||
KIBANA_USERNAME=kibana_system
|
KIBANA_USERNAME=kibana_system
|
||||||
KIBANA_PASSWORD=kibana_pass
|
KIBANA_PASSWORD=
|
||||||
|
|
||||||
ENCRYPTION_KEY=c34d38b3a14956121ff2170e5030b471551370178f43e5626eec58b04a30fae2
|
ENCRYPTION_KEY=c34d38b3a14956121ff2170e5030b471551370178f43e5626eec58b04a30fae2
|
||||||
|
|||||||
53
logs/172.31.141.12-1726534356068.log
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: v
|
||||||
|
game.js:134 User existence check response: {exists: false}
|
||||||
|
game.js:143 handleRegister called
|
||||||
|
game.js:148 Nickname: v
|
||||||
|
game.js:149 Password: v
|
||||||
|
game.js:150 Confirm Password: v
|
||||||
|
game.js:154 Attempting to register user: v
|
||||||
|
game.js:156 Register result: {registered: true, token: '7ab181bc-7bf7-4ac0-a562-23e1c455ca23'}
|
||||||
|
game.js:160 Token stored: 7ab181bc-7bf7-4ac0-a562-23e1c455ca23
|
||||||
|
game.js:161 User registered successfully
|
||||||
|
game.js:166 ChatManager initialized: null
|
||||||
|
game.js:168 Initializing ChatManager with username: v and token: 7ab181bc-7bf7-4ac0-a562-23e1c455ca23
|
||||||
|
game.js:732 ChatManager initialized for user: v
|
||||||
|
game.js:170 ChatManager initialized: ChatManager {username: 'v', token: '7ab181bc-7bf7-4ac0-a562-23e1c455ca23', roomSockets: {…}, blockedUsers: Array(0), activeRoom: null, …}
|
||||||
|
game.js:173 chatManager is defined: ChatManager {username: 'v', token: '7ab181bc-7bf7-4ac0-a562-23e1c455ca23', roomSockets: {…}, blockedUsers: Array(0), activeRoom: null, …}
|
||||||
|
game.js:178 Joining room: main_room
|
||||||
|
game.js:983 Joining room: main_room with username: v and token: 7ab181bc-7bf7-4ac0-a562-23e1c455ca23
|
||||||
|
game.js:991 Joining new room: main_room
|
||||||
|
game.js:910 createRoomTab: main_room with username: v and token: 7ab181bc-7bf7-4ac0-a562-23e1c455ca23
|
||||||
|
game.js:920 Tab for room main_room already exists.
|
||||||
|
game.js:933 Showing tab for room: main_room
|
||||||
|
game.js:747 Initializing chat WebSocket...
|
||||||
|
game.js:748 Initializing chat WebSocket for room: main_room with username: v
|
||||||
|
game.js:753 startChatWebSocket: main_room with username: v and token: 7ab181bc-7bf7-4ac0-a562-23e1c455ca23
|
||||||
|
game.js:1012 ChatInput initialized for room: main_room, username: v
|
||||||
|
game.js:945 Attempting to switch to room: main_room
|
||||||
|
game.js:951 Switching from room null to room main_room
|
||||||
|
game.js:759 WebSocket ouvert pour l'utilisateur v dans la room main_room
|
||||||
|
game.js:767 Authentication message sent for room: main_room with username: v
|
||||||
|
game.js:773 Message received from server in room main_room: {type: 'chat_message', username: 'v', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:798 Message displayed in chat log for room: main_room
|
||||||
|
game.js:773 Message received from server in room main_room: {type: 'chat_message', username: 'f', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:798 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1019 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1032 Attempting to send message: /s f
|
||||||
|
game.js:1045 Detected stats command for user: f
|
||||||
|
game.js:677 Fetching stats for user: f
|
||||||
|
game.js:1057 Message input cleared.
|
||||||
|
game.js:680
|
||||||
|
|
||||||
|
|
||||||
|
POST http://172.31.141.12:8080/game_server/get_player_stats/ 404 (Not Found)
|
||||||
|
fetchPlayerStatsFromGameServer @ game.js:680
|
||||||
|
sendMessage @ game.js:1046
|
||||||
|
(anonymous) @ game.js:1020
|
||||||
|
game.js:689 Failed to fetch stats for f. HTTP error! Status: 404
|
||||||
|
fetchPlayerStatsFromGameServer @ game.js:689
|
||||||
|
await in fetchPlayerStatsFromGameServer
|
||||||
|
sendMessage @ game.js:1046
|
||||||
|
(anonymous) @ game.js:1020
|
||||||
41
logs/172.31.141.12-1726534693901.log
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: g
|
||||||
|
game.js:134 User existence check response: {exists: true}
|
||||||
|
game.js:224 Initializing ChatManager...
|
||||||
|
game.js:732 ChatManager initialized for user: g
|
||||||
|
game.js:983 Joining room: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:991 Joining new room: main_room
|
||||||
|
game.js:910 createRoomTab: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:920 Tab for room main_room already exists.
|
||||||
|
game.js:933 Showing tab for room: main_room
|
||||||
|
game.js:747 Initializing chat WebSocket...
|
||||||
|
game.js:748 Initializing chat WebSocket for room: main_room with username: g
|
||||||
|
game.js:753 startChatWebSocket: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:1012 ChatInput initialized for room: main_room, username: g
|
||||||
|
game.js:945 Attempting to switch to room: main_room
|
||||||
|
game.js:951 Switching from room null to room main_room
|
||||||
|
game.js:759 WebSocket ouvert pour l'utilisateur g dans la room main_room
|
||||||
|
game.js:767 Authentication message sent for room: main_room with username: g
|
||||||
|
game.js:773 Message received from server in room main_room: {type: 'chat_message', username: 'g', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:798 Message displayed in chat log for room: main_room
|
||||||
|
game.js:773 Message received from server in room main_room: {type: 'chat_message', username: 'h', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:798 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1019 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1032 Attempting to send message: /s h
|
||||||
|
game.js:1045 Detected stats command for user: h
|
||||||
|
game.js:677 Fetching stats for user: h
|
||||||
|
game.js:1057 Message input cleared.
|
||||||
|
game.js:680
|
||||||
|
|
||||||
|
|
||||||
|
POST http://172.31.141.12:8080/get_player_stats/ 404 (Not Found)
|
||||||
|
fetchPlayerStatsFromGameServer @ game.js:680
|
||||||
|
sendMessage @ game.js:1046
|
||||||
|
(anonymous) @ game.js:1020
|
||||||
|
game.js:689 Failed to fetch stats for h. HTTP error! Status: 404
|
||||||
|
fetchPlayerStatsFromGameServer @ game.js:689
|
||||||
|
await in fetchPlayerStatsFromGameServer
|
||||||
|
sendMessage @ game.js:1046
|
||||||
|
(anonymous) @ game.js:1020
|
||||||
6
logs/172.31.141.12-1726536620868.log
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
get_player_stats/:1
|
||||||
|
|
||||||
|
|
||||||
|
GET http://172.31.141.12:8080/get_player_stats/ 405 (Method Not Allowed)
|
||||||
|
get_player_stats/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
get_player_stats/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
33
logs/172.31.141.12-1726538690438.log
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: vv
|
||||||
|
game.js:134 User existence check response: {exists: true}
|
||||||
|
game.js:224 Initializing ChatManager...
|
||||||
|
game.js:748 ChatManager initialized for user: vv
|
||||||
|
game.js:999 Joining room: main_room with username: vv and token: 51edbeca-570d-4536-b81d-4eaa64051300
|
||||||
|
game.js:1007 Joining new room: main_room
|
||||||
|
game.js:926 createRoomTab: main_room with username: vv and token: 51edbeca-570d-4536-b81d-4eaa64051300
|
||||||
|
game.js:936 Tab for room main_room already exists.
|
||||||
|
game.js:949 Showing tab for room: main_room
|
||||||
|
game.js:763 Initializing chat WebSocket...
|
||||||
|
game.js:764 Initializing chat WebSocket for room: main_room with username: vv
|
||||||
|
game.js:769 startChatWebSocket: main_room with username: vv and token: 51edbeca-570d-4536-b81d-4eaa64051300
|
||||||
|
game.js:1042 ChatInput initialized for room: main_room, username: vv
|
||||||
|
game.js:961 Attempting to switch to room: main_room
|
||||||
|
game.js:967 Switching from room null to room main_room
|
||||||
|
game.js:775 WebSocket ouvert pour l'utilisateur vv dans la room main_room
|
||||||
|
game.js:783 Authentication message sent for room: main_room with username: vv
|
||||||
|
game.js:789 Message received from server in room main_room: {type: 'chat_message', username: 'vv', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:814 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1049 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1062 Attempting to send message: /s v
|
||||||
|
game.js:1075 Detected stats command for user: v
|
||||||
|
game.js:721 Player stats not loaded yet. Fetching all player stats...
|
||||||
|
game.js:1087 Message input cleared.
|
||||||
|
game.js:708 All player stats received: {players: Array(0)}
|
||||||
|
game.js:732 Player with username v not found.
|
||||||
|
getPlayerStatsByUsername @ game.js:732
|
||||||
|
await in getPlayerStatsByUsername
|
||||||
|
sendMessage @ game.js:1076
|
||||||
|
(anonymous) @ game.js:1050
|
||||||
47
logs/172.31.141.12-1726541943958.log
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: x
|
||||||
|
game.js:134 User existence check response: {exists: false}
|
||||||
|
game.js:143 handleRegister called
|
||||||
|
game.js:148 Nickname: x
|
||||||
|
game.js:149 Password: x
|
||||||
|
game.js:150 Confirm Password: x
|
||||||
|
game.js:154 Attempting to register user: x
|
||||||
|
game.js:156 Register result: {registered: true, token: '7dfe4c69-eaf0-49ca-b914-3f69bc9dda57'}
|
||||||
|
game.js:160 Token stored: 7dfe4c69-eaf0-49ca-b914-3f69bc9dda57
|
||||||
|
game.js:161 User registered successfully
|
||||||
|
game.js:166 ChatManager initialized: null
|
||||||
|
game.js:168 Initializing ChatManager with username: x and token: 7dfe4c69-eaf0-49ca-b914-3f69bc9dda57
|
||||||
|
game.js:753 ChatManager initialized for user: x
|
||||||
|
game.js:170 ChatManager initialized: ChatManager {username: 'x', token: '7dfe4c69-eaf0-49ca-b914-3f69bc9dda57', roomSockets: {…}, blockedUsers: Array(0), activeRoom: null, …}
|
||||||
|
game.js:173 chatManager is defined: ChatManager {username: 'x', token: '7dfe4c69-eaf0-49ca-b914-3f69bc9dda57', roomSockets: {…}, blockedUsers: Array(0), activeRoom: null, …}
|
||||||
|
game.js:178 Joining room: main_room
|
||||||
|
game.js:1018 Joining room: main_room with username: x and token: 7dfe4c69-eaf0-49ca-b914-3f69bc9dda57
|
||||||
|
game.js:1026 Joining new room: main_room
|
||||||
|
game.js:945 createRoomTab: main_room with username: x and token: 7dfe4c69-eaf0-49ca-b914-3f69bc9dda57
|
||||||
|
game.js:955 Tab for room main_room already exists.
|
||||||
|
game.js:968 Showing tab for room: main_room
|
||||||
|
game.js:782 Initializing chat WebSocket...
|
||||||
|
game.js:783 Initializing chat WebSocket for room: main_room with username: x
|
||||||
|
game.js:788 startChatWebSocket: main_room with username: x and token: 7dfe4c69-eaf0-49ca-b914-3f69bc9dda57
|
||||||
|
game.js:1061 ChatInput initialized for room: main_room, username: x
|
||||||
|
game.js:980 Attempting to switch to room: main_room
|
||||||
|
game.js:986 Switching from room null to room main_room
|
||||||
|
game.js:794 WebSocket ouvert pour l'utilisateur x dans la room main_room
|
||||||
|
game.js:802 Authentication message sent for room: main_room with username: x
|
||||||
|
game.js:808 Message received from server in room main_room: {type: 'chat_message', username: 'x', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:833 Message displayed in chat log for room: main_room
|
||||||
|
game.js:808 Message received from server in room main_room: {type: 'chat_message', username: 'w', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:833 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1068 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1081 Attempting to send message: /s w
|
||||||
|
game.js:1094 Detected stats command for user: w
|
||||||
|
game.js:660 Detected stats command for user: w
|
||||||
|
game.js:663 Uncaught ReferenceError: fetchPlayers is not defined
|
||||||
|
at sendStatsCommand (game.js:663:6)
|
||||||
|
at ChatInput.sendMessage (game.js:1095:6)
|
||||||
|
at HTMLInputElement.<anonymous> (game.js:1069:11)
|
||||||
|
sendStatsCommand @ game.js:663
|
||||||
|
sendMessage @ game.js:1095
|
||||||
|
(anonymous) @ game.js:1069
|
||||||
46
logs/172.31.141.12-1726542449903.log
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: g
|
||||||
|
game.js:134 User existence check response: {exists: true}
|
||||||
|
game.js:224 Initializing ChatManager...
|
||||||
|
game.js:765 ChatManager initialized for user: g
|
||||||
|
game.js:1030 Joining room: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:1038 Joining new room: main_room
|
||||||
|
game.js:957 createRoomTab: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:967 Tab for room main_room already exists.
|
||||||
|
game.js:980 Showing tab for room: main_room
|
||||||
|
game.js:794 Initializing chat WebSocket...
|
||||||
|
game.js:795 Initializing chat WebSocket for room: main_room with username: g
|
||||||
|
game.js:800 startChatWebSocket: main_room with username: g and token: 458f5428-2c48-4dbe-b126-815da541e7fb
|
||||||
|
game.js:1073 ChatInput initialized for room: main_room, username: g
|
||||||
|
game.js:992 Attempting to switch to room: main_room
|
||||||
|
game.js:998 Switching from room null to room main_room
|
||||||
|
game.js:806 WebSocket ouvert pour l'utilisateur g dans la room main_room
|
||||||
|
game.js:814 Authentication message sent for room: main_room with username: g
|
||||||
|
game.js:820 Message received from server in room main_room: {type: 'chat_message', username: 'g', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:845 Message displayed in chat log for room: main_room
|
||||||
|
game.js:820 Message received from server in room main_room: {type: 'chat_message', username: 'h', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:845 Message displayed in chat log for room: main_room
|
||||||
|
game.js:820 Message received from server in room main_room: {type: 'chat_message', username: 'h', message: 'ggg', room: 'main_room'}
|
||||||
|
game.js:845 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1080 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1093 Attempting to send message: /s h
|
||||||
|
game.js:1106 Detected stats command for user: h
|
||||||
|
game.js:672 Detected stats command for user: h
|
||||||
|
game.js:659 Fetching players...
|
||||||
|
game.js:675 Uncaught TypeError: Cannot read properties of undefined (reading 'then')
|
||||||
|
at sendStatsCommand (game.js:675:20)
|
||||||
|
at ChatInput.sendMessage (game.js:1107:6)
|
||||||
|
at HTMLInputElement.<anonymous> (game.js:1081:11)
|
||||||
|
sendStatsCommand @ game.js:675
|
||||||
|
sendMessage @ game.js:1107
|
||||||
|
(anonymous) @ game.js:1081
|
||||||
|
game.js:667 Error fetching match data: ReferenceError: displayPlayers is not defined
|
||||||
|
at game.js:664:21
|
||||||
|
(anonymous) @ game.js:667
|
||||||
|
Promise.catch
|
||||||
|
fetchPlayers @ game.js:667
|
||||||
|
sendStatsCommand @ game.js:675
|
||||||
|
sendMessage @ game.js:1107
|
||||||
|
(anonymous) @ game.js:1081
|
||||||
37
logs/172.31.141.12-1726543072083.log
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
:8080/:1 The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.
|
||||||
|
game.js:3 DOM fully loaded and parsed
|
||||||
|
game.js:43 DOM elements initialized
|
||||||
|
game.js:118 checkUserExists called with username: h
|
||||||
|
game.js:134 User existence check response: {exists: true}
|
||||||
|
game.js:224 Initializing ChatManager...
|
||||||
|
game.js:753 ChatManager initialized for user: h
|
||||||
|
game.js:1018 Joining room: main_room with username: h and token: 27cda257-bf3c-4523-82e3-28bafd5a6ad2
|
||||||
|
game.js:1026 Joining new room: main_room
|
||||||
|
game.js:945 createRoomTab: main_room with username: h and token: 27cda257-bf3c-4523-82e3-28bafd5a6ad2
|
||||||
|
game.js:955 Tab for room main_room already exists.
|
||||||
|
game.js:968 Showing tab for room: main_room
|
||||||
|
game.js:782 Initializing chat WebSocket...
|
||||||
|
game.js:783 Initializing chat WebSocket for room: main_room with username: h
|
||||||
|
game.js:788 startChatWebSocket: main_room with username: h and token: 27cda257-bf3c-4523-82e3-28bafd5a6ad2
|
||||||
|
game.js:1061 ChatInput initialized for room: main_room, username: h
|
||||||
|
game.js:980 Attempting to switch to room: main_room
|
||||||
|
game.js:986 Switching from room null to room main_room
|
||||||
|
game.js:794 WebSocket ouvert pour l'utilisateur h dans la room main_room
|
||||||
|
game.js:802 Authentication message sent for room: main_room with username: h
|
||||||
|
game.js:808 Message received from server in room main_room: {type: 'chat_message', username: 'h', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:833 Message displayed in chat log for room: main_room
|
||||||
|
game.js:808 Message received from server in room main_room: {type: 'chat_message', username: 't', message: 'Authentication successful', room: 'main_room'}
|
||||||
|
game.js:833 Message displayed in chat log for room: main_room
|
||||||
|
game.js:1068 Enter key pressed, attempting to send message...
|
||||||
|
game.js:1081 Attempting to send message: /s t
|
||||||
|
game.js:1094 Detected stats command for user: t
|
||||||
|
game.js:660 Detected stats command for user: t
|
||||||
|
burger.js:79 Fetching players...
|
||||||
|
game.js:663 Uncaught TypeError: Cannot read properties of undefined (reading 'then')
|
||||||
|
at sendStatsCommand (game.js:663:20)
|
||||||
|
at ChatInput.sendMessage (game.js:1095:6)
|
||||||
|
at HTMLInputElement.<anonymous> (game.js:1069:11)
|
||||||
|
sendStatsCommand @ game.js:663
|
||||||
|
sendMessage @ game.js:1095
|
||||||
|
(anonymous) @ game.js:1069
|
||||||
|
burger.js:136 Displaying players:
|
||||||
1223
logs/172.31.141.12-1726543851799.log
Normal file
1826
logs/django.log
Normal file
0
logs/django_errors.log
Normal file
1
makefile
@ -81,3 +81,4 @@ help:
|
|||||||
|
|
||||||
.PHONY: up build start stop down destroy logs ps db-shell help
|
.PHONY: up build start stop down destroy logs ps db-shell help
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -28,3 +28,4 @@ application = ProtocolTypeRouter({
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
# /pong/game/consumers.py
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from channels.generic.websocket import AsyncWebsocketConsumer
|
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||||
|
from asgiref.sync import sync_to_async
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from channels.db import database_sync_to_async
|
from channels.db import database_sync_to_async
|
||||||
from .matchmaking import match_maker
|
from .matchmaking import match_maker
|
||||||
from .tournament import tournament_match_maker
|
from .tournament import tournament_match_maker
|
||||||
|
from .models import Player
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class GameConsumer(AsyncWebsocketConsumer):
|
class GameConsumer(AsyncWebsocketConsumer):
|
||||||
async def connect(self):
|
async def connect(self):
|
||||||
@ -104,3 +107,312 @@ class GameConsumer(AsyncWebsocketConsumer):
|
|||||||
async def set_game(self, game):
|
async def set_game(self, game):
|
||||||
print(f"({self.user}) Game set to: {game}")
|
print(f"({self.user}) Game set to: {game}")
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|
||||||
|
###################################################################CHAT###################################################################
|
||||||
|
class ChatConsumer(AsyncWebsocketConsumer):
|
||||||
|
async def connect(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Récupérer le nom de la room à partir de l'URL
|
||||||
|
self.room_group_name = self.scope['url_route']['kwargs']['room_name']
|
||||||
|
|
||||||
|
# Accepter la connexion WebSocket
|
||||||
|
await self.accept()
|
||||||
|
# Ajouter l'utilisateur au groupe (room)
|
||||||
|
await self.channel_layer.group_add(
|
||||||
|
self.room_group_name,
|
||||||
|
self.channel_name
|
||||||
|
)
|
||||||
|
|
||||||
|
self.username = self.scope['user'].username # Assurez-vous d'avoir un utilisateur lié à la connexion
|
||||||
|
logger.info(f"Connexion de l'utilisateur {self.username} à la room {self.room_group_name}")
|
||||||
|
# Ajouter l'utilisateur à son propre groupe personnel (pour messages directs)
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la connexion WebSocket: {str(e)}")
|
||||||
|
|
||||||
|
async def disconnect(self, close_code):
|
||||||
|
try:
|
||||||
|
# Retirer l'utilisateur du groupe (room)
|
||||||
|
await self.channel_layer.group_discard(
|
||||||
|
self.room_group_name,
|
||||||
|
self.channel_name
|
||||||
|
)
|
||||||
|
|
||||||
|
# Retirer l'utilisateur de son groupe personnel
|
||||||
|
await self.channel_layer.group_discard(
|
||||||
|
f"user_{self.username}",
|
||||||
|
self.channel_name
|
||||||
|
)
|
||||||
|
|
||||||
|
# Envoyer un message indiquant que l'utilisateur a quitté la room
|
||||||
|
await self.chat_message(
|
||||||
|
'chat_message',
|
||||||
|
self.user.username if hasattr(self, "user") else "Unknown",
|
||||||
|
f'{self.user.username if hasattr(self, "user") else "Unknown"} a quitté le chat',
|
||||||
|
self.room_group_name
|
||||||
|
)
|
||||||
|
logger.info(f"{self.user.username if hasattr(self, 'user') else 'Unknown'} déconnecté de la room {self.room_group_name}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la déconnexion WebSocket: {str(e)}")
|
||||||
|
|
||||||
|
async def receive(self, text_data):
|
||||||
|
try:
|
||||||
|
# Convertir les données JSON reçues en dictionnaire Python
|
||||||
|
data = json.loads(text_data)
|
||||||
|
message_type = data.get('type')
|
||||||
|
username = data.get('username')
|
||||||
|
message = data.get('message', None)
|
||||||
|
target_user = data.get('target_user', None)
|
||||||
|
|
||||||
|
logger.info(f"Message reçu: {data}")
|
||||||
|
|
||||||
|
# Gestion des différents types de messages
|
||||||
|
if message_type == 'authenticate':
|
||||||
|
logger.info(f"Authentification demandée pour {username}")
|
||||||
|
await self.authenticate(data.get('token'), username)
|
||||||
|
return
|
||||||
|
|
||||||
|
elif message_type == 'chat_message':
|
||||||
|
logger.info(f"Message de chat envoyé par {username}: {message}")
|
||||||
|
await self.chat_message('chat_message', username, message, self.room_group_name)
|
||||||
|
|
||||||
|
elif message_type == 'block_user':
|
||||||
|
logger.info(f"{username} tente de bloquer {target_user}")
|
||||||
|
await self.handle_block_user(data)
|
||||||
|
|
||||||
|
elif message_type == 'invite':
|
||||||
|
await self.handle_invite_user(data)
|
||||||
|
|
||||||
|
elif message_type == 'invite_response':
|
||||||
|
await self.handle_invite_response(data)
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.warning(f"Type de message non géré: {message_type}")
|
||||||
|
await self.chat_message('error', 'server', f"Unhandled message type: {message_type}", self.room_group_name)
|
||||||
|
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(f"Erreur de décodage JSON : {str(e)} - Données reçues : {text_data}")
|
||||||
|
await self.chat_message('error', 'server', 'Invalid JSON format', self.room_group_name)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de la réception du message: {str(e)}")
|
||||||
|
await self.chat_message('error', 'server', 'Internal server error', self.room_group_name)
|
||||||
|
|
||||||
|
async def chat_message(self, message_type, username, message, room):
|
||||||
|
"""
|
||||||
|
Fonction générale pour envoyer tout type de message via WebSocket à tous les utilisateurs dans la room.
|
||||||
|
"""
|
||||||
|
logger.info(f"Envoi d'un message de type {message_type} de {username} dans la room {room}")
|
||||||
|
|
||||||
|
# Utilisation de channel_layer pour envoyer le message à tout le groupe (room)
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
room,
|
||||||
|
{
|
||||||
|
'type': 'send_group_message', # Nom de la méthode qui va gérer ce message
|
||||||
|
'username': username,
|
||||||
|
'message': message,
|
||||||
|
'room': room
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def send_group_message(self, event):
|
||||||
|
"""
|
||||||
|
Cette fonction est appelée par channel_layer pour envoyer des messages à tous les utilisateurs dans une room.
|
||||||
|
"""
|
||||||
|
message = event['message']
|
||||||
|
username = event.get('username', 'Anonyme')
|
||||||
|
room = event.get('room', 'unknown')
|
||||||
|
|
||||||
|
logger.info(f"Diffusion d'un message de {username} à la room {room}: {message}")
|
||||||
|
|
||||||
|
# Envoi du message à chaque utilisateur dans la room via WebSocket
|
||||||
|
await self.send(text_data=json.dumps({
|
||||||
|
'type': 'chat_message', # Le type de message qui sera renvoyé au client
|
||||||
|
'username': username,
|
||||||
|
'message': message,
|
||||||
|
'room': room
|
||||||
|
}))
|
||||||
|
|
||||||
|
async def handle_block_user(self, data):
|
||||||
|
username = data['username']
|
||||||
|
target_user = data['target_user']
|
||||||
|
|
||||||
|
logger.info(f"handle_block_user appelé avec : {data}")
|
||||||
|
|
||||||
|
if target_user == username:
|
||||||
|
logger.warning(f"{username} a tenté de se bloquer lui-même.")
|
||||||
|
await self.send(text_data=json.dumps({'type': 'error', 'message': 'You cannot block yourself'}))
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"{username} a bloqué {target_user}")
|
||||||
|
|
||||||
|
# Utilisation correcte de l' f-string pour inclure la valeur de target_user
|
||||||
|
await self.send(text_data=json.dumps({
|
||||||
|
'type': 'block_user',
|
||||||
|
'message': f'Vous avez bloqué les messages de {target_user}'
|
||||||
|
}))
|
||||||
|
|
||||||
|
async def handle_invite_user(self, data):
|
||||||
|
# Récupération des informations de l'invitation
|
||||||
|
inviter = data.get('username')
|
||||||
|
target_user = data.get('target_user')
|
||||||
|
room = data.get('room')
|
||||||
|
|
||||||
|
# Validation des paramètres
|
||||||
|
if not inviter:
|
||||||
|
logger.error("Invitant manquant dans le message d'invitation")
|
||||||
|
await self.chat_message('error', 'server', 'Invitant manquant', self.room_group_name)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not target_user:
|
||||||
|
logger.error("Utilisateur cible manquant dans le message d'invitation")
|
||||||
|
await self.chat_message('error', 'server', 'Utilisateur cible manquant', self.room_group_name)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not room:
|
||||||
|
logger.error("Room manquante dans le message d'invitation")
|
||||||
|
await self.chat_message('error', 'server', 'Room manquante', self.room_group_name)
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Invitation envoyée de {inviter} à {target_user} dans la room {room}")
|
||||||
|
await self.chat_message('chat_message', 'server', f'{inviter} a invité {target_user} à rejoindre une partie {room}', room)
|
||||||
|
|
||||||
|
# Envoi de l'invitation
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
room,
|
||||||
|
{
|
||||||
|
'type': 'invite',
|
||||||
|
'inviter': inviter,
|
||||||
|
'target_user': target_user,
|
||||||
|
'room': room,
|
||||||
|
'message': f'{inviter} vous a invité à rejoindre la room {room}.'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def handle_invite_response(self, data):
|
||||||
|
inviter = data.get('inviter')
|
||||||
|
username = data.get('username') # L'utilisateur invité qui répond
|
||||||
|
response = data.get('response')
|
||||||
|
room = data.get('room')
|
||||||
|
|
||||||
|
logger.info(f"{username} a répondu '{response}' à l'invitation de {inviter}")
|
||||||
|
await self.chat_message('chat_message', 'server', f'{username} a répondu {response} à l\'invitation.', room)
|
||||||
|
|
||||||
|
# Si la réponse est 'yes', informer l'invitant que l'invité a accepté
|
||||||
|
if response.lower() == 'yes':
|
||||||
|
try:
|
||||||
|
# Informer l'invitant que l'invitation a été acceptée
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
room,
|
||||||
|
{
|
||||||
|
'type': 'invite_response',
|
||||||
|
'inviter': inviter,
|
||||||
|
'username': username,
|
||||||
|
'response': response,
|
||||||
|
'room': room,
|
||||||
|
'message': f'{username} a accepté l\'invitation.'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Informer à la fois l'invité et l'invitant que le jeu va commencer
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
room,
|
||||||
|
{
|
||||||
|
'type': 'start_quick_match',
|
||||||
|
'inviter': inviter,
|
||||||
|
'username': username,
|
||||||
|
'message': 'La partie va démarrer pour vous deux.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error while sending invite response: {str(e)}")
|
||||||
|
await self.chat_message('error', 'server', f'Internal server error: {str(e)}', room)
|
||||||
|
|
||||||
|
# Méthode appelée pour envoyer l'invitation à l'utilisateur invité (target_user)
|
||||||
|
async def invite(self, event):
|
||||||
|
inviter = event['inviter']
|
||||||
|
message = event['message']
|
||||||
|
room = event['room']
|
||||||
|
target_user = event['target_user']
|
||||||
|
logger.info(f"invite: Envoi de l'invitation à l'utilisateur via WebSocket. Inviter={inviter}, Room={room}, Message={message}")
|
||||||
|
|
||||||
|
# Envoyer le message d'invitation via WebSocket
|
||||||
|
await self.send(text_data=json.dumps({
|
||||||
|
'type': 'invite',
|
||||||
|
'inviter': inviter,
|
||||||
|
'target_user': target_user,
|
||||||
|
'message': message,
|
||||||
|
'room': room
|
||||||
|
}))
|
||||||
|
|
||||||
|
async def handle_invite_response(self, data):
|
||||||
|
inviter = data.get('inviter')
|
||||||
|
username = data.get('username') # L'utilisateur invité qui répond
|
||||||
|
response = data.get('response')
|
||||||
|
room = data.get('room')
|
||||||
|
|
||||||
|
logger.info(f"{username} a répondu '{response}' à l'invitation de {inviter}")
|
||||||
|
await self.chat_message('chat_message', 'server', f'{username} a répondu {response} à l\'invitation.', room)
|
||||||
|
|
||||||
|
# Envoi de la réponse directement à l'invitant dans la room
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
room,
|
||||||
|
{
|
||||||
|
'type': 'invite_response', # Type de message 'invite_response'
|
||||||
|
'inviter': inviter,
|
||||||
|
'username': username,
|
||||||
|
'room': room,
|
||||||
|
'message': f'{username} a répondu {response} à l\'invitation.',
|
||||||
|
'response': response # Ajout de la réponse 'yes' ou 'no'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def invite_response(self, event):
|
||||||
|
message = event['message']
|
||||||
|
response = event.get('response')
|
||||||
|
inviter = event.get('inviter') # Récupérer l'inviteur
|
||||||
|
|
||||||
|
logger.info(f"invite_response: Envoi de la réponse à l'invitation via WebSocket. Message={message}, Response={response}, Inviter={inviter}")
|
||||||
|
|
||||||
|
# Envoyer la réponse à l'invitation via WebSocket à l'invitant
|
||||||
|
await self.send(text_data=json.dumps({
|
||||||
|
'type': 'invite_response',
|
||||||
|
'message': message,
|
||||||
|
'response': response,
|
||||||
|
'inviter': inviter
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
async def authenticate(self, token, username):
|
||||||
|
if not token:
|
||||||
|
logger.error("Token est manquant, l'authentification ne peut pas se poursuivre.")
|
||||||
|
await self.chat_message('error', 'server', 'Token is missing', self.room_group_name)
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Tentative d'authentification avec le token: {token} pour l'utilisateur: {username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = await self.get_user_from_token(token)
|
||||||
|
if user:
|
||||||
|
self.user = user
|
||||||
|
logger.info(f"Utilisateur {username} authentifié avec succès")
|
||||||
|
await self.chat_message('authenticated', username, 'Authentication successful', self.room_group_name)
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.warning(f"Échec de l'authentification pour le token: {token}")
|
||||||
|
await self.chat_message('error', username, 'Authentication failed', self.room_group_name)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lors de l'authentification : {str(e)}")
|
||||||
|
await self.chat_message('error', 'server', 'Internal server error', self.room_group_name)
|
||||||
|
|
||||||
|
@sync_to_async
|
||||||
|
def get_user_from_token(self, token):
|
||||||
|
try:
|
||||||
|
user = User.objects.filter(auth_token=token).first()
|
||||||
|
logger.debug(f"Utilisateur trouvé : {user} pour le token : {token}")
|
||||||
|
return user
|
||||||
|
except User.DoesNotExist:
|
||||||
|
logger.warning(f"Utilisateur non trouvé pour le token : {token}")
|
||||||
|
return None
|
||||||
@ -9,7 +9,6 @@ from asgiref.sync import sync_to_async
|
|||||||
from .models import Tournoi
|
from .models import Tournoi
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
|
|
||||||
def __init__(self, game_id, player1, player2, localgame):
|
def __init__(self, game_id, player1, player2, localgame):
|
||||||
self.game_id = game_id
|
self.game_id = game_id
|
||||||
self.player1 = player1
|
self.player1 = player1
|
||||||
@ -51,7 +50,6 @@ class Game:
|
|||||||
self.bt1 = 0
|
self.bt1 = 0
|
||||||
self.bt2 = 0
|
self.bt2 = 0
|
||||||
self.start_time = datetime.now()
|
self.start_time = datetime.now()
|
||||||
self.future_ball_position = {'x': 390, 'y': 190}
|
|
||||||
|
|
||||||
async def start_game(self):
|
async def start_game(self):
|
||||||
print(f"- Game #{self.game_id} STARTED ({self.game_state['player1_name']} vs {self.game_state['player2_name']}) --- ({self})")
|
print(f"- Game #{self.game_id} STARTED ({self.game_state['player1_name']} vs {self.game_state['player2_name']}) --- ({self})")
|
||||||
@ -60,42 +58,41 @@ class Game:
|
|||||||
|
|
||||||
async def game_loop(self):
|
async def game_loop(self):
|
||||||
print(" In the game loop..")
|
print(" In the game loop..")
|
||||||
x = 59
|
x = 0
|
||||||
while not self.ended:
|
while not self.ended:
|
||||||
if self.botgame:
|
if self.botgame:
|
||||||
x += 1
|
x += 1
|
||||||
if x == 60:
|
if x == 60:
|
||||||
# Random BOT difficulty..
|
|
||||||
steps = 60#random.randint(10, 60)
|
|
||||||
self.future_ball_position = await self.predict_ball_trajectory(steps)
|
|
||||||
x = 0
|
|
||||||
if self.botgame:
|
|
||||||
await self.update_bot_position()
|
await self.update_bot_position()
|
||||||
|
x = 0
|
||||||
await self.handle_pad_movement()
|
await self.handle_pad_movement()
|
||||||
await self.update_game_state()
|
await self.update_game_state()
|
||||||
await self.send_game_state()
|
await self.send_game_state()
|
||||||
await asyncio.sleep(1/60) # Around 60 FPS
|
await asyncio.sleep(1/60) # Around 60 FPS
|
||||||
|
|
||||||
async def update_bot_position(self):
|
async def update_bot_position(self):
|
||||||
#future_ball_position = self.predict_ball_trajectory()
|
future_ball_position = self.predict_ball_trajectory()
|
||||||
target_y = self.future_ball_position['y']
|
|
||||||
|
target_y = future_ball_position['y']
|
||||||
player2_position = self.game_state['player2_position']
|
player2_position = self.game_state['player2_position']
|
||||||
|
|
||||||
# Adjusts bot position based on expected ball position
|
# Adjusts bot position based on expected ball position
|
||||||
if player2_position < target_y < player2_position + 80:
|
if player2_position < target_y < player2_position + 80:
|
||||||
pass #bot already placed
|
pass #bot already placed
|
||||||
elif player2_position < target_y:
|
elif player2_position < target_y:
|
||||||
self.p2_mov = 1
|
#self.p2_mov = 1
|
||||||
#self.game_state['player2_position'] = min(player2_position + (50 * self.speed), 300)
|
self.game_state['player2_position'] = min(player2_position + (50 * self.speed), 300)
|
||||||
elif player2_position + 80 > target_y:
|
elif player2_position + 80 > target_y:
|
||||||
self.p2_mov = -1
|
#self.p2_mov = -1
|
||||||
#self.game_state['player2_position'] = max(player2_position - (50 * self.speed), 0)
|
self.game_state['player2_position'] = max(player2_position - (50 * self.speed), 0)
|
||||||
|
|
||||||
|
def predict_ball_trajectory(self, steps=60):
|
||||||
|
|
||||||
async def predict_ball_trajectory(self, steps=60):
|
|
||||||
future_x = self.game_state['ball_position']['x']
|
future_x = self.game_state['ball_position']['x']
|
||||||
future_y = self.game_state['ball_position']['y']
|
future_y = self.game_state['ball_position']['y']
|
||||||
velocity_x = self.game_state['ball_velocity']['x']
|
velocity_x = self.game_state['ball_velocity']['x']
|
||||||
velocity_y = self.game_state['ball_velocity']['y']
|
velocity_y = self.game_state['ball_velocity']['y']
|
||||||
|
|
||||||
for _ in range(steps):
|
for _ in range(steps):
|
||||||
future_x += velocity_x
|
future_x += velocity_x
|
||||||
if future_x <= 10:
|
if future_x <= 10:
|
||||||
@ -105,9 +102,11 @@ class Game:
|
|||||||
future_x = 790
|
future_x = 790
|
||||||
else:
|
else:
|
||||||
future_y += velocity_y
|
future_y += velocity_y
|
||||||
|
|
||||||
# Dealing with bounces off walls
|
# Dealing with bounces off walls
|
||||||
if future_y <= 10 or future_y >= 390:
|
if future_y <= 10 or future_y >= 390:
|
||||||
velocity_y = -velocity_y # Reverse the direction of vertical movement
|
velocity_y = -velocity_y # Reverse the direction of vertical movement
|
||||||
|
|
||||||
return {'x': future_x, 'y': future_y}
|
return {'x': future_x, 'y': future_y}
|
||||||
|
|
||||||
async def update_game_state(self):
|
async def update_game_state(self):
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
# /pong/game/routing.py
|
# /pong/game/routing.py
|
||||||
|
|
||||||
from django.urls import re_path
|
from django.urls import re_path
|
||||||
from . import consumers
|
from . import consumers
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
logger.debug("Configuring WebSocket routing patterns")
|
||||||
|
|
||||||
websocket_urlpatterns = [
|
websocket_urlpatterns = [
|
||||||
re_path(r'ws/game/$', consumers.GameConsumer.as_asgi()),
|
re_path(r'ws/game/$', consumers.GameConsumer.as_asgi(), name='game_ws'),
|
||||||
|
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
logger.info("WebSocket routing patterns configured successfully")
|
||||||
|
|||||||
@ -10,6 +10,13 @@ from .models import Tournoi
|
|||||||
from .utils import create_tournament, update_tournament, getlen
|
from .utils import create_tournament, update_tournament, getlen
|
||||||
from asgiref.sync import sync_to_async
|
from asgiref.sync import sync_to_async
|
||||||
|
|
||||||
|
|
||||||
|
TOURNAMENT_NAMES = [
|
||||||
|
"Champions Clash", "Ultimate Showdown", "Battle Royale",
|
||||||
|
"Victory Cup", "Legends Tournament", "Elite Series", "Clash of 42",
|
||||||
|
"Shibuya incident", "Cunning Game", "Elite of the Stars"
|
||||||
|
]
|
||||||
|
|
||||||
TOURNAMENT_NAMES = [
|
TOURNAMENT_NAMES = [
|
||||||
"Champion's Clash", "Ultimate Showdown", "Battle Royale",
|
"Champion's Clash", "Ultimate Showdown", "Battle Royale",
|
||||||
"Victory's Cup", "Legends Tournament", "Elite Series", "Clash of 42",
|
"Victory's Cup", "Legends Tournament", "Elite Series", "Clash of 42",
|
||||||
@ -82,13 +89,13 @@ class TournamentMatchMaker:
|
|||||||
|
|
||||||
# Tournament start method
|
# Tournament start method
|
||||||
async def start_tournament(self):
|
async def start_tournament(self):
|
||||||
if len(self.waiting_players) < 3:
|
|
||||||
|
if len(self.waiting_players) < 2:
|
||||||
return False
|
return False
|
||||||
random.shuffle(self.waiting_players)
|
if len(self.waiting_players) % 2 == 0:
|
||||||
'''if (len(self.waiting_players) % 2) != 0:
|
await self.add_player(None)
|
||||||
print("Adding a BYE to the tournament..")
|
|
||||||
await self.add_player(None)'''
|
|
||||||
self.tournament_state = "in_progress"
|
self.tournament_state = "in_progress"
|
||||||
|
random.shuffle(self.waiting_players)
|
||||||
self.current_round = 0
|
self.current_round = 0
|
||||||
len_tournament = await sync_to_async(getlen)()
|
len_tournament = await sync_to_async(getlen)()
|
||||||
self.final_name = self.name + " #" + str(len_tournament + 1)
|
self.final_name = self.name + " #" + str(len_tournament + 1)
|
||||||
@ -171,12 +178,16 @@ class TournamentMatchMaker:
|
|||||||
print(f"Starting TOURNAMENT round #{self.current_round}")
|
print(f"Starting TOURNAMENT round #{self.current_round}")
|
||||||
for match in self.rounds[-1]:
|
for match in self.rounds[-1]:
|
||||||
if match.player1 and match.player2:
|
if match.player1 and match.player2:
|
||||||
|
# Envoyer un message pour indiquer les prochains joueurs du tournoi
|
||||||
|
message = f"Prochain match: {match.player1.user.username} contre {match.player2.user.username}"
|
||||||
|
await self.send_to_player(match.player2, {'type': 'tournament_match', 'message': message})
|
||||||
await match_maker.notify_players(match.player1, match.player2, match.game_id, False)
|
await match_maker.notify_players(match.player1, match.player2, match.game_id, False)
|
||||||
asyncio.create_task(match.start_game())
|
asyncio.create_task(match.start_game())
|
||||||
elif match.player1:
|
elif match.player1:
|
||||||
# Handle BYE match
|
# Gestion du BYE
|
||||||
|
message = f"Prochain match: {match.player1.user.username} contre Bot"
|
||||||
|
await self.send_to_player(match.player1, {'type': 'tournament_match', 'message': message})
|
||||||
await match_maker.notify_players(match.player1, match.player2, match.game_id, False)
|
await match_maker.notify_players(match.player1, match.player2, match.game_id, False)
|
||||||
#asyncio.create_task(match.start_game())
|
|
||||||
match.game_state['player1_score'] = 3
|
match.game_state['player1_score'] = 3
|
||||||
match.game_state['player2_score'] = 0
|
match.game_state['player2_score'] = 0
|
||||||
await match.end_game()
|
await match.end_game()
|
||||||
@ -215,7 +226,6 @@ class TournamentMatchMaker:
|
|||||||
self.rounds = []
|
self.rounds = []
|
||||||
self.current_round = 0
|
self.current_round = 0
|
||||||
self.games = 0
|
self.games = 0
|
||||||
self.tournament_state = "waiting"
|
|
||||||
|
|
||||||
async def handle_match_end(self, match):
|
async def handle_match_end(self, match):
|
||||||
await self.update_brackets()
|
await self.update_brackets()
|
||||||
|
|||||||
@ -12,9 +12,7 @@ def handle_game_data(p1, p2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tour
|
|||||||
player_1 = get_or_create_player(p1)
|
player_1 = get_or_create_player(p1)
|
||||||
player_2 = get_or_create_player(p2)
|
player_2 = get_or_create_player(p2)
|
||||||
|
|
||||||
print("CHAKU & THEOUCHE are the BEST")
|
|
||||||
create_match(player_1, player_2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament)
|
create_match(player_1, player_2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament)
|
||||||
print("and ADRIANO is the PEST")
|
|
||||||
|
|
||||||
update_player_statistics(p1)
|
update_player_statistics(p1)
|
||||||
print("UPDATE PLAYER 1")
|
print("UPDATE PLAYER 1")
|
||||||
|
|||||||
@ -95,22 +95,15 @@ def player_list_json(request):
|
|||||||
}
|
}
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
def get_tournoi_data(tournoi):
|
|
||||||
return {
|
|
||||||
"id": tournoi.id,
|
|
||||||
"name": tournoi.name,
|
|
||||||
"nbr_player": tournoi.nbr_player,
|
|
||||||
"date": tournoi.date,
|
|
||||||
"winner": {
|
|
||||||
"id": tournoi.winner.id,
|
|
||||||
"name": tournoi.winner.name
|
|
||||||
} if tournoi.winner else None
|
|
||||||
}
|
|
||||||
|
|
||||||
def tournoi_list_json(request):
|
def tournoi_list_json(request):
|
||||||
tournois = Tournoi.objects.select_related('winner').all() # Charge les données du gagnant
|
tournois = Tournoi.objects.all()
|
||||||
tournois_data = [get_tournoi_data(tournoi) for tournoi in tournois]
|
|
||||||
return JsonResponse({"tournois": tournois_data})
|
data = {
|
||||||
|
'tournois': list(tournois.values(
|
||||||
|
'id', 'name', 'nbr_player', 'date', 'winner'
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return JsonResponse(data)
|
||||||
|
|
||||||
|
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
|
|||||||
@ -121,10 +121,6 @@ USE_L10N = True
|
|||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'pong/static')]
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'pong/static')]
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||||
@ -136,6 +132,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||||||
|
|
||||||
# Channels
|
# Channels
|
||||||
# Define the channel layers for WebSockets
|
# Define the channel layers for WebSockets
|
||||||
|
# Define the channel layers for WebSockets
|
||||||
CHANNEL_LAYERS = {
|
CHANNEL_LAYERS = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'channels.layers.InMemoryChannelLayer',
|
'BACKEND': 'channels.layers.InMemoryChannelLayer',
|
||||||
|
|||||||
@ -77,16 +77,29 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
function fetchPlayers() {
|
function fetchPlayers() {
|
||||||
console.log('Fetching players...');
|
console.log('Fetching players...');
|
||||||
fetch('/api/player_list/')
|
// Retourner la promesse pour permettre l'utilisation de .then() plus tard
|
||||||
.then(response => response.json())
|
return fetch('/api/player_list/')
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.players) {
|
if (data.players) {
|
||||||
displayPlayers(data.players);
|
displayPlayers(data.players); // Affiche les joueurs récupérés
|
||||||
|
return data.players; // Retourne les joueurs pour permettre de les traiter dans un .then
|
||||||
|
} else {
|
||||||
|
throw new Error('No players found.');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error fetching match data:', error));
|
.catch(error => {
|
||||||
|
console.error('Error fetching match data:', error);
|
||||||
|
return null; // En cas d'erreur, retourne null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
// Expose fetchPlayers globalement
|
||||||
|
window.fetchPlayers = fetchPlayers;
|
||||||
function fetchTournois(){
|
function fetchTournois(){
|
||||||
console.log('Fetching tournois...');
|
console.log('Fetching tournois...');
|
||||||
fetch('/api/tournoi_list/')
|
fetch('/api/tournoi_list/')
|
||||||
@ -103,11 +116,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
console.log('Displaying matches:');
|
console.log('Displaying matches:');
|
||||||
const matchListBody = document.querySelector('#match-list tbody');
|
const matchListBody = document.querySelector('#match-list tbody');
|
||||||
matchListBody.innerHTML = '';
|
matchListBody.innerHTML = '';
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
|
||||||
if (matches.length != 0) {
|
if (matches.length != 0) {
|
||||||
matches.forEach(match => {
|
matches.forEach(match => {
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td>${match.id}</td>
|
<td>${match.id}</td>
|
||||||
<td>${match.player1__name}</td>
|
<td>${match.player1__name}</td>
|
||||||
@ -125,7 +137,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
matchListBody.appendChild(row);
|
matchListBody.appendChild(row);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td colspan="12">No matches found.</td>
|
<td colspan="12">No matches found.</td>
|
||||||
`;
|
`;
|
||||||
@ -137,11 +148,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
console.log('Displaying players:');
|
console.log('Displaying players:');
|
||||||
const playersListBody = document.querySelector('#player-list tbody');
|
const playersListBody = document.querySelector('#player-list tbody');
|
||||||
playersListBody.innerHTML = '';
|
playersListBody.innerHTML = '';
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
|
||||||
if (players.length != 0) {
|
if (players.length != 0) {
|
||||||
players.forEach(player => {
|
players.forEach(player => {
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td>${player.id}</td>
|
<td>${player.id}</td>
|
||||||
<td>${player.name}</td>
|
<td>${player.name}</td>
|
||||||
@ -160,9 +170,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
playersListBody.appendChild(row);
|
playersListBody.appendChild(row);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td colspan="12">No player found.</td>
|
<td colspan="12">No matches found.</td>
|
||||||
`
|
`
|
||||||
playersListBody.appendChild(row);
|
playersListBody.appendChild(row);
|
||||||
}
|
}
|
||||||
@ -172,25 +181,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
console.log('Displaying tournois:');
|
console.log('Displaying tournois:');
|
||||||
const tournoisListBody = document.querySelector('#tournoi-list tbody');
|
const tournoisListBody = document.querySelector('#tournoi-list tbody');
|
||||||
tournoisListBody.innerHTML = '';
|
tournoisListBody.innerHTML = '';
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
|
||||||
if (tournois.length != 0) {
|
if (tournois.length != 0) {
|
||||||
tournois.forEach(tournoi => {
|
tournois.forEach(tournoi => {
|
||||||
console.log('Winner:', tournoi.winner); //debug !!!!!!!!!!!!!!!!!
|
|
||||||
console.log('Winner:', tournoi.winner__name); //debug !!!!!!!!!!!!!!!!!
|
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td>${tournoi.id}</td>
|
<td>${tournoi.id}</td>
|
||||||
<td>${tournoi.name}</td>
|
<td>${tournoi.name}</td>
|
||||||
<td>${tournoi.nbr_player}</td>
|
<td>${tournoi.nbr_player}</td>
|
||||||
<td>${tournoi.date}</td>
|
<td>${tournoi.date}</td>
|
||||||
<td>${tournoi.winner ? tournoi.winner.name : 'No one yet ...'}</td>
|
<td>${tournoi.winner ? tournoi.winner.name : 'None'}</td>
|
||||||
`;
|
`;
|
||||||
tournoisListBody.appendChild(row);
|
tournoisListBody.appendChild(row);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const row = document.createElement('tr');
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td colspan="12">No tournoi found.</td>
|
<td colspan="12">No matches found.</td>
|
||||||
`
|
`
|
||||||
tournoisListBody.appendChild(row);
|
tournoisListBody.appendChild(row);
|
||||||
}
|
}
|
||||||
|
|||||||
0
pong/static/flags/de.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
pong/static/flags/es.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 415 KiB After Width: | Height: | Size: 415 KiB |
0
pong/static/flags/fr.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 946 B After Width: | Height: | Size: 946 B |
0
pong/static/flags/it.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 959 B |
0
pong/static/flags/us.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
console.log("DOM fully loaded and parsed");
|
||||||
const formBlock = document.getElementById('block-form');
|
const formBlock = document.getElementById('block-form');
|
||||||
|
|
||||||
const authForm = document.getElementById('auth-form');
|
const authForm = document.getElementById('auth-form');
|
||||||
@ -38,17 +40,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const quickMatchButton = document.getElementById('quick-match');
|
const quickMatchButton = document.getElementById('quick-match');
|
||||||
const tournamentButton = document.getElementById('tournament');
|
const tournamentButton = document.getElementById('tournament');
|
||||||
|
|
||||||
let socket;
|
console.log("DOM elements initialized");
|
||||||
let token;
|
|
||||||
let gameState;
|
|
||||||
let saveData = null;
|
|
||||||
|
|
||||||
// Auto-focus and key handling for AUTH-FORM
|
// Auto-focus and key handling for AUTH-FORM
|
||||||
nicknameInput.focus();
|
nicknameInput.focus();
|
||||||
nicknameInput.addEventListener('keypress', function (event) {
|
nicknameInput.addEventListener('keypress', function (event) {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
checkNicknameButton.click();
|
handleCheckNickname(); // Appeler directement la fonction au lieu de simuler un clic
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,6 +63,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
quickMatchButton.addEventListener('click', startQuickMatch);
|
quickMatchButton.addEventListener('click', startQuickMatch);
|
||||||
tournamentButton.addEventListener('click', startTournament);
|
tournamentButton.addEventListener('click', startTournament);
|
||||||
|
|
||||||
|
let socket;
|
||||||
|
let gameState;
|
||||||
|
let activeRoom = null; // Stocker la room active
|
||||||
|
let roomSockets = {}; // Stocker les connexions WebSocket par room
|
||||||
|
let token = null;
|
||||||
|
let username = null;
|
||||||
|
let saveData = null;
|
||||||
|
let roomName = null;
|
||||||
|
let chatManager = null;
|
||||||
|
|
||||||
|
|
||||||
async function handleCheckNickname() {
|
async function handleCheckNickname() {
|
||||||
const nickname = nicknameInput.value.trim();
|
const nickname = nicknameInput.value.trim();
|
||||||
if (nickname) {
|
if (nickname) {
|
||||||
@ -105,6 +115,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function checkUserExists(username) {
|
async function checkUserExists(username) {
|
||||||
|
console.log("checkUserExists called with username:", username);
|
||||||
|
try {
|
||||||
const response = await fetch('/check_user_exists/', {
|
const response = await fetch('/check_user_exists/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -112,22 +124,61 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({ username })
|
body: JSON.stringify({ username })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error(`HTTP error! Status: ${response.status}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log("User existence check response:", data);
|
||||||
return data.exists;
|
return data.exists;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during user existence check:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleRegister() {
|
async function handleRegister() {
|
||||||
|
console.log("handleRegister called");
|
||||||
const nickname = nicknameInput.value.trim();
|
const nickname = nicknameInput.value.trim();
|
||||||
const password = passwordInput.value.trim();
|
const password = passwordInput.value.trim();
|
||||||
const confirmPassword = confirmPasswordInput.value.trim();
|
const confirmPassword = confirmPasswordInput.value.trim();
|
||||||
|
|
||||||
|
console.log("Nickname:", nickname);
|
||||||
|
console.log("Password:", password);
|
||||||
|
console.log("Confirm Password:", confirmPassword);
|
||||||
|
|
||||||
if (password === confirmPassword) {
|
if (password === confirmPassword) {
|
||||||
try {
|
try {
|
||||||
|
console.log("Attempting to register user:", nickname);
|
||||||
const result = await registerUser(nickname, password);
|
const result = await registerUser(nickname, password);
|
||||||
if (result) {
|
console.log("Register result:", result);
|
||||||
|
|
||||||
|
if (result.registered) { // Vérifiez que result contient bien un champ registered
|
||||||
|
token = result.token; // Assurez-vous que le token est bien stocké ici
|
||||||
|
console.log("Token stored:", token);
|
||||||
|
console.log("User registered successfully");
|
||||||
registerForm.style.display = 'none';
|
registerForm.style.display = 'none';
|
||||||
document.getElementById("post-form-buttons").style.display = 'block';
|
document.getElementById("post-form-buttons").style.display = 'block';
|
||||||
|
username = nickname;
|
||||||
|
roomName = 'main_room'; // Nom de la room principale
|
||||||
|
console.log("ChatManager initialized:", chatManager);
|
||||||
|
|
||||||
|
console.log("Initializing ChatManager with username:", username, "and token:", token);
|
||||||
|
chatManager = new ChatManager(username, token); // Initialiser ChatManager
|
||||||
|
console.log("ChatManager initialized:", chatManager);
|
||||||
|
// Ajoutez un log pour vérifier si chatManager est défini
|
||||||
|
if (chatManager) {
|
||||||
|
console.log("chatManager is defined:", chatManager);
|
||||||
} else {
|
} else {
|
||||||
|
console.error("chatManager is not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Joining room:", roomName);
|
||||||
|
chatManager.joinRoom(roomName); // Utilisez ChatManager pour rejoindre la room
|
||||||
|
} else {
|
||||||
|
console.error('Registration failed. No token received.');
|
||||||
alert('Registration failed. Please try again.');
|
alert('Registration failed. Please try again.');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -135,6 +186,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Passwords do not match.');
|
alert('Passwords do not match.');
|
||||||
|
console.error('Passwords do not match.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,9 +200,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.registered) {
|
if (data.registered) {
|
||||||
token = data.token;
|
return { registered: true, token: data.token };
|
||||||
|
} else {
|
||||||
|
return { registered: false };
|
||||||
}
|
}
|
||||||
return data.registered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleLogin() {
|
async function handleLogin() {
|
||||||
@ -161,6 +214,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (result) {
|
if (result) {
|
||||||
loginForm.style.display = 'none';
|
loginForm.style.display = 'none';
|
||||||
document.getElementById("post-form-buttons").style.display = 'block';
|
document.getElementById("post-form-buttons").style.display = 'block';
|
||||||
|
|
||||||
|
// Gérer la connexion WebSocket de chat
|
||||||
|
if (chatManager && chatManager.roomSockets['main_room'] && chatManager.roomSockets['main_room'].readyState !== WebSocket.OPEN) {
|
||||||
|
console.log('Rejoining chat room...');
|
||||||
|
chatManager.startChatWebSocket('main_room'); // Relance la connexion WebSocket si nécessaire
|
||||||
|
} else if (!chatManager) {
|
||||||
|
username = nickname;
|
||||||
|
console.log('Initializing ChatManager...');
|
||||||
|
chatManager = new ChatManager(username, token); // Réinitialisation du ChatManager si nécessaire
|
||||||
|
chatManager.joinRoom('main_room');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Authentication failed. Please try again.');
|
alert('Authentication failed. Please try again.');
|
||||||
}
|
}
|
||||||
@ -224,6 +288,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function checkUserExists2(username) {
|
async function checkUserExists2(username) {
|
||||||
|
console.log("checkUserExists2 called with username:", username);
|
||||||
|
try {
|
||||||
const response = await fetch('/check_user_exists/', {
|
const response = await fetch('/check_user_exists/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -231,29 +297,45 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({ username })
|
body: JSON.stringify({ username })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error(`HTTP error! Status: ${response.status}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log("User existence check response (checkUserExists2):", data);
|
||||||
return data.exists;
|
return data.exists;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during user existence check (checkUserExists2):', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleRegister2() {
|
async function handleRegister2() {
|
||||||
|
console.log("handleRegister2 called");
|
||||||
const nickname2 = nicknameInput2.value.trim();
|
const nickname2 = nicknameInput2.value.trim();
|
||||||
const password2 = passwordInput2.value.trim();
|
const password2 = passwordInput2.value.trim();
|
||||||
const confirmPassword2 = confirmPasswordInput2.value.trim();
|
const confirmPassword2 = confirmPasswordInput2.value.trim();
|
||||||
|
|
||||||
if (password2 === confirmPassword2) {
|
if (password2 === confirmPassword2) {
|
||||||
try {
|
try {
|
||||||
|
console.log("Attempting to register user (handleRegister2):", nickname2);
|
||||||
const result = await registerUser2(nickname2, password2);
|
const result = await registerUser2(nickname2, password2);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
console.log("User registered successfully (handleRegister2)");
|
||||||
registerForm2.style.display = 'none';
|
registerForm2.style.display = 'none';
|
||||||
startLocalGame2();
|
startLocalGame2();
|
||||||
} else {
|
} else {
|
||||||
|
console.error('Registration failed (handleRegister2).');
|
||||||
alert('Registration failed. Please try again.');
|
alert('Registration failed. Please try again.');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error registering user:', error);
|
console.error('Error registering user (handleRegister2):', error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Passwords do not match.');
|
alert('Passwords do not match.');
|
||||||
|
console.error('Passwords do not match (handleRegister2).');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,32 +417,61 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
saveData = {
|
saveData = {
|
||||||
type: 'quick'
|
type: 'quick'
|
||||||
}
|
}
|
||||||
|
console.log("Starting quick match...(fonction startquickmatch)");
|
||||||
|
// Masquer les éléments inutiles et afficher le conteneur de jeu
|
||||||
gameContainer.style.display = 'flex';
|
gameContainer.style.display = 'flex';
|
||||||
logo.style.display = 'none';
|
logo.style.display = 'none';
|
||||||
pongElements.style.display = 'none';
|
pongElements.style.display = 'none';
|
||||||
formBlock.style.display = 'none';
|
formBlock.style.display = 'none';
|
||||||
document.getElementById('player1-name').textContent = "player 1";
|
// Vérification si une connexion WebSocket est déjà active avant d'initialiser
|
||||||
document.getElementById('player2-name').textContent = "player 2";
|
if (roomSockets["quick_match"] && roomSockets["quick_match"].readyState === WebSocket.OPEN)
|
||||||
document.getElementById('game-text').textContent = "";
|
{
|
||||||
document.getElementById('player1-score').textContent = 0;
|
console.warn("WebSocket for quick_match already open.");
|
||||||
document.getElementById('player2-score').textContent = 0;
|
// On laisse startWebSocketConnection se lancer malgré la WebSocket ouverte
|
||||||
|
|
||||||
startWebSocketConnection(token, 1);
|
startWebSocketConnection(token, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
roomName = "quick_match"; // Nom de la room principale
|
||||||
|
chatManager = new ChatManager(username, token); // Initialiser ChatManager
|
||||||
|
chatManager.joinRoom(roomName); // Utilisez ChatManager pour rejoindre la room
|
||||||
|
console.log("Starting WebSocket connection for quick match...");
|
||||||
|
startWebSocketConnection(token, 1); // Le "1" pourrait être un identifiant pour le mode Quick Match
|
||||||
}
|
}
|
||||||
|
|
||||||
function startTournament() {
|
// Fonction pour démarrer un tournoi
|
||||||
|
function startTournament()
|
||||||
|
{
|
||||||
saveData = {
|
saveData = {
|
||||||
type: 'tournoi'
|
type: 'tournoi'
|
||||||
}
|
};
|
||||||
|
// Masquer les éléments inutiles et afficher le conteneur du tournoi
|
||||||
tournamentContainer.style.display = 'flex';
|
tournamentContainer.style.display = 'flex';
|
||||||
logo.style.display = 'none';
|
logo.style.display = 'none';
|
||||||
pongElements.style.display = 'none';
|
pongElements.style.display = 'none';
|
||||||
formBlock.style.display = 'none';
|
formBlock.style.display = 'none';
|
||||||
|
// Log pour vérifier le token avant l'authentification WebSocket
|
||||||
|
// Vérification si une connexion WebSocket est déjà active avant d'initialiser
|
||||||
|
if (roomSockets["tournament"] && roomSockets["tournament"].readyState === WebSocket.OPEN)
|
||||||
|
{
|
||||||
|
console.warn("WebSocket for tournament already open.");
|
||||||
|
// On laisse startWebSocketConnection se lancer malgré la WebSocket ouverte
|
||||||
startWebSocketConnection(token, 42);
|
startWebSocketConnection(token, 42);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chatManager = new ChatManager(username, token); // Initialiser ChatManager
|
||||||
|
chatManager.joinRoom('tournament'); // Utilisez ChatManager pour rejoindre la room
|
||||||
|
console.log("Starting WebSocket connection for tournament...");
|
||||||
|
startWebSocketConnection(token, 42); // Le "42" pourrait être un identifiant pour le mode tournoi
|
||||||
}
|
}
|
||||||
|
|
||||||
function startWebSocketConnection(token, players) {
|
function startWebSocketConnection(token, players) {
|
||||||
socket = new WebSocket(`wss://${window.location.host}/ws/game/`);
|
// Si le socket existe déjà et est ouvert, le fermer
|
||||||
|
/*if (socket && socket.readyState === WebSocket.OPEN)
|
||||||
|
{
|
||||||
|
console.warn('WebSocket connection already open. Closing and recreating a new one.');
|
||||||
|
socket.close(); // Fermer le socket ouvert
|
||||||
|
}*/
|
||||||
|
socket = new WebSocket(`ws://${window.location.host}/ws/game/`);
|
||||||
|
|
||||||
socket.onopen = function (event) {
|
socket.onopen = function (event) {
|
||||||
console.log('WebSocket connection established');
|
console.log('WebSocket connection established');
|
||||||
@ -371,7 +482,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
console.log("Sending tokens for a local game");
|
console.log("Sending tokens for a local game");
|
||||||
socket.send(JSON.stringify({ type: 'authenticate2', token_1: token, token_2: token2 }));
|
socket.send(JSON.stringify({ type: 'authenticate2', token_1: token, token_2: token2 }));
|
||||||
} else {
|
} else {
|
||||||
console.log("Sending token for a tournament game")
|
console.log("Sending token for a tournament game");
|
||||||
socket.send(JSON.stringify({ type: 'authenticate3', token: token }));
|
socket.send(JSON.stringify({ type: 'authenticate3', token: token }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -388,8 +499,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.addEventListener('keydown', handleKeyDown);
|
document.addEventListener('keydown', handleKeyDown);
|
||||||
} else if (data.type === 'game_state_update') {
|
} else if (data.type === 'game_state_update') {
|
||||||
updateGameState(data.game_state);
|
updateGameState(data.game_state);
|
||||||
} else if (data.type === 'game_text_update') {
|
|
||||||
updateGameText(data.game_text);
|
|
||||||
} else if (data.type === 'player_disconnected') {
|
} else if (data.type === 'player_disconnected') {
|
||||||
console.log('Player disconnected:', data.player);
|
console.log('Player disconnected:', data.player);
|
||||||
} else if (data.type === 'game_ended') {
|
} else if (data.type === 'game_ended') {
|
||||||
@ -416,11 +525,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.getElementById('tournament-bracket').innerHTML = data.html;
|
document.getElementById('tournament-bracket').innerHTML = data.html;
|
||||||
} else if (data.type === 'tournament_end') {
|
} else if (data.type === 'tournament_end') {
|
||||||
console.log('Tournament ended, the winner is:', data.winner);
|
console.log('Tournament ended, the winner is:', data.winner);
|
||||||
|
// Nouveau cas pour gérer les prochains matchs du tournoi
|
||||||
|
} else if (data.type === 'tournament_match') {
|
||||||
|
console.log('Prochain match du tournoi:', data.message);
|
||||||
|
// Transmettre le message au chat via WebSocket du chat
|
||||||
|
if (chatManager.chatSocket && chatManager.chatSocket.readyState === WebSocket.OPEN) {
|
||||||
|
chatManager.chatSocket.send(JSON.stringify({
|
||||||
|
type: 'chat_message',
|
||||||
|
message: data.message,
|
||||||
|
username: 'Server', // Ou le nom d'utilisateur si pertinent
|
||||||
|
room: 'tournament' // Ou la room appropriée
|
||||||
|
}));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Message from server:', data.type, data.message);
|
console.log('Message from server:', data.type, data.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Gestion des fermetures de connexion
|
||||||
socket.onclose = function (event) {
|
socket.onclose = function (event) {
|
||||||
console.log('WebSocket connection closed');
|
console.log('WebSocket connection closed');
|
||||||
};
|
};
|
||||||
@ -430,15 +552,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gestion des événements de touche
|
||||||
function handleKeyDown(event) {
|
function handleKeyDown(event) {
|
||||||
|
console.log("Key pressed:", event.key);
|
||||||
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'w' || event.key === 's') {
|
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'w' || event.key === 's') {
|
||||||
sendKeyPress(event.key.toLowerCase());
|
sendKeyPress(event.key.toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendKeyPress(key) {
|
function sendKeyPress(key) {
|
||||||
|
console.log("Sending key press:", key);
|
||||||
if (socket.readyState === WebSocket.OPEN) {
|
if (socket.readyState === WebSocket.OPEN) {
|
||||||
socket.send(JSON.stringify({ type: 'key_press', key }));
|
socket.send(JSON.stringify({ type: 'key_press', key }));
|
||||||
|
} else {
|
||||||
|
console.warn("WebSocket is not open. Key press not sent.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +575,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
checkForWinner();
|
checkForWinner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fonction pour rendre l'état du jeu à l'écran
|
||||||
function renderGame() {
|
function renderGame() {
|
||||||
|
console.log("Rendering game state...");
|
||||||
document.getElementById('player1-name').textContent = `${gameState.player1_name}`;
|
document.getElementById('player1-name').textContent = `${gameState.player1_name}`;
|
||||||
document.getElementById('player2-name').textContent = `${gameState.player2_name}`;
|
document.getElementById('player2-name').textContent = `${gameState.player2_name}`;
|
||||||
|
|
||||||
@ -464,10 +593,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.getElementById('game-text').textContent = gameState.game_text;
|
document.getElementById('game-text').textContent = gameState.game_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateGameText(gameText) {
|
|
||||||
document.getElementById('game-text').textContent = gameText;
|
|
||||||
}
|
|
||||||
|
|
||||||
const starsContainer = document.getElementById('stars');
|
const starsContainer = document.getElementById('stars');
|
||||||
for (let i = 0; i < 500; i++) {
|
for (let i = 0; i < 500; i++) {
|
||||||
const star = document.createElement('div');
|
const star = document.createElement('div');
|
||||||
@ -521,4 +646,493 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendStatsCommand(targetUser) {
|
||||||
|
console.log(`Detected stats command for user: ${targetUser}`);
|
||||||
|
|
||||||
|
// Appelle fetchPlayers et utilise .then() pour traiter les résultats
|
||||||
|
fetchPlayers().then((players) => {
|
||||||
|
if (!players) {
|
||||||
|
console.log('No players found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Players received in sendStatsCommand:', players); // Affiche les joueurs récupérés
|
||||||
|
|
||||||
|
// Filtrer et récupérer les informations du joueur spécifique
|
||||||
|
const playerStats = filterPlayers(targetUser, players); // Passer le tableau players en paramètre
|
||||||
|
if (playerStats) {
|
||||||
|
// Si les stats sont trouvées, afficher la popup avec les données
|
||||||
|
displayPlayerStats(playerStats);
|
||||||
|
} else {
|
||||||
|
console.log(`Player with username ${targetUser} not found.`);
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('Error fetching players:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modification de filterPlayers pour chercher dans les données reçues (JSON)
|
||||||
|
function filterPlayers(targetUser, players) {
|
||||||
|
const searchValue = targetUser.toLowerCase(); // Utiliser le nom d'utilisateur comme valeur de recherche
|
||||||
|
|
||||||
|
for (let i = 0; i < players.length; i++) {
|
||||||
|
const player = players[i];
|
||||||
|
if (player.name && player.name.toLowerCase() === searchValue) {
|
||||||
|
// Récupérer les statistiques du joueur à partir des données reçues
|
||||||
|
const playerStats = {
|
||||||
|
username: player.name,
|
||||||
|
total_matches: player.total_match,
|
||||||
|
total_wins: player.total_win,
|
||||||
|
win_percentage: player.p_win,
|
||||||
|
best_score: player.best_score || 'N/A' // Ajoute une gestion de cas si best_score n'existe pas
|
||||||
|
};
|
||||||
|
return playerStats; // Retourne les stats du joueur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // Retourne null si le joueur n'est pas trouvé
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function displayPlayerStats(stats) {
|
||||||
|
console.log('Displaying player stats:', stats); // Vérifie que la fonction est bien appelée
|
||||||
|
|
||||||
|
// Créer ou récupérer l'élément popup
|
||||||
|
let statsPopup = document.getElementById('player-stats-popup');
|
||||||
|
|
||||||
|
if (!statsPopup) {
|
||||||
|
console.log('Creating stats popup element'); // Vérifie si l'élément est bien créé
|
||||||
|
statsPopup = document.createElement('div');
|
||||||
|
statsPopup.id = 'player-stats-popup';
|
||||||
|
statsPopup.classList.add('player-stats-popup');
|
||||||
|
document.body.appendChild(statsPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre à jour le contenu de la popup avec les statistiques
|
||||||
|
statsPopup.innerHTML = `
|
||||||
|
<h3>Player Stats</h3>
|
||||||
|
<p><strong>Username:</strong> ${stats.username}</p>
|
||||||
|
<p><strong>Total Matches:</strong> ${stats.total_matches}</p>
|
||||||
|
<p><strong>Total Wins:</strong> ${stats.total_wins}</p>
|
||||||
|
<p><strong>Win Percentage:</strong> ${stats.win_percentage}%</p>
|
||||||
|
<p><strong>Best Score:</strong> ${stats.best_score}</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Afficher la popup avec une animation
|
||||||
|
statsPopup.classList.add('show');
|
||||||
|
statsPopup.classList.remove('hide');
|
||||||
|
|
||||||
|
// Masquer la popup après 5 secondes
|
||||||
|
setTimeout(() => {
|
||||||
|
statsPopup.classList.remove('show');
|
||||||
|
statsPopup.classList.add('hide');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////CHAT////////////////////////////////////
|
||||||
|
class ChatManager {
|
||||||
|
constructor(username, token) {
|
||||||
|
this.username = username;
|
||||||
|
this.token = token;
|
||||||
|
this.roomSockets = {}; // Stockage des WebSockets par room
|
||||||
|
this.blockedUsers = []; // Liste des utilisateurs bloqués
|
||||||
|
this.activeRoom = null; // La room actuellement active
|
||||||
|
this.chatSocket = null; // Le WebSocket de chat actif
|
||||||
|
|
||||||
|
console.log(`ChatManager initialized for user: ${username}`);
|
||||||
|
this.initializeEventListeners(); // Initialiser les gestionnaires d'événements
|
||||||
|
}
|
||||||
|
initializeEventListeners() {
|
||||||
|
const quitButton = document.getElementById('quit-room-btn');
|
||||||
|
if (quitButton) {
|
||||||
|
quitButton.addEventListener('click', () => {
|
||||||
|
if (this.activeRoom) {
|
||||||
|
this.leaveRoom(this.activeRoom);
|
||||||
|
console.log(`User ${this.username} has left the room ${this.activeRoom}`);
|
||||||
|
} else {
|
||||||
|
console.warn('No active room to leave.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startChatWebSocket(roomName) {
|
||||||
|
if (!this.username || this.username.trim() === '') {
|
||||||
|
console.error("Username is not defined or empty. WebSocket connection aborted.");
|
||||||
|
alert("Username is required to join the chat. Please log in.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.roomSockets[roomName] && this.roomSockets[roomName].readyState === WebSocket.OPEN) {
|
||||||
|
console.warn(`WebSocket for room ${roomName} already open.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Initializing chat WebSocket...");
|
||||||
|
console.log(`Initializing chat WebSocket for room: ${roomName} with username: ${this.username}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.chatSocket = new WebSocket(`ws://${window.location.host}/ws/chat/${roomName}/`);
|
||||||
|
this.roomSockets[roomName] = this.chatSocket; // Stockage du WebSocket
|
||||||
|
console.log(`startChatWebSocket: ${roomName} with username: ${this.username} and token: ${this.token}`);
|
||||||
|
|
||||||
|
const chatInputInstance = new ChatInput(roomName, this.username, this.chatSocket, this); // On passe l'instance du manager
|
||||||
|
|
||||||
|
// Gestion de l'ouverture du WebSocket
|
||||||
|
this.chatSocket.onopen = () => {
|
||||||
|
console.log(`WebSocket ouvert pour l'utilisateur ${this.username} dans la room ${roomName}`);
|
||||||
|
|
||||||
|
this.chatSocket.send(JSON.stringify({
|
||||||
|
'type': 'authenticate',
|
||||||
|
'username': this.username,
|
||||||
|
'token': this.token,
|
||||||
|
'room': roomName,
|
||||||
|
}));
|
||||||
|
console.log(`Authentication message sent for room: ${roomName} with username: ${this.username}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gestion des messages WebSocket
|
||||||
|
this.chatSocket.onmessage = (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
console.log(`Message received from server in room ${roomName}:`, data);
|
||||||
|
const receivedUsername = data.username || this.username;
|
||||||
|
|
||||||
|
// Assurez-vous que le chat log est bien trouvé pour la room active
|
||||||
|
let chatLog = document.getElementById(`chat-log-${roomName}`);
|
||||||
|
if (!chatLog) {
|
||||||
|
console.error(`Chat log element for room ${roomName} not found.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (data.type) {
|
||||||
|
case 'authenticated':
|
||||||
|
console.log(`User authenticated successfully in room: ${roomName}`);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'chat_message':
|
||||||
|
const message = data.message;
|
||||||
|
const receivedUsername = data.username;
|
||||||
|
const roomName = data.room;
|
||||||
|
|
||||||
|
// Si l'utilisateur n'est pas bloqué, afficher le message
|
||||||
|
if (!this.blockedUsers.includes(receivedUsername)) {
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
messageElement.textContent = `${receivedUsername}: ${message}`;
|
||||||
|
chatLog.appendChild(messageElement);
|
||||||
|
console.log(`Message displayed in chat log for room: ${roomName}`);
|
||||||
|
} else {
|
||||||
|
console.log(`Message from blocked user ${receivedUsername} was filtered out.`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'block_user':
|
||||||
|
if (data.message) {
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
messageElement.textContent = data.message;
|
||||||
|
chatLog.appendChild(messageElement); // Ajoute le message au chat-log
|
||||||
|
} else {
|
||||||
|
console.error(`Failed to block user: ${data.message}`);
|
||||||
|
alert(`Error: Failed to block user. ${data.message}`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'invite':
|
||||||
|
// Vérifie si l'invitation est destinée à cet utilisateur (invité)
|
||||||
|
if (data.target_user === this.username) {
|
||||||
|
console.log(`Invitation reçue de ${data.inviter}`);
|
||||||
|
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
messageElement.textContent = data.message;
|
||||||
|
chatLog.appendChild(messageElement); // Affiche le message dans le chat-log
|
||||||
|
|
||||||
|
// Demande à l'utilisateur s'il accepte ou refuse l'invitation
|
||||||
|
const inviteResponse = confirm(`${data.inviter} vous a invité dans la room ${data.room}. Accepter? yes/no.`);
|
||||||
|
const response = inviteResponse ? 'yes' : 'no';
|
||||||
|
|
||||||
|
console.log(`Réponse à l'invitation: ${response}`);
|
||||||
|
|
||||||
|
// Envoie la réponse (oui ou non) au serveur
|
||||||
|
this.chatSocket.send(JSON.stringify({
|
||||||
|
'type': 'invite_response',
|
||||||
|
'username': this.username, // Utilisateur invité
|
||||||
|
'response': response,
|
||||||
|
'inviter': data.inviter, // Le nom de l'invitant
|
||||||
|
'room': data.room
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (response === 'yes') {
|
||||||
|
// Si l'invitation est acceptée, lancer QuickMatch pour l'invité
|
||||||
|
console.log(`L'invité ${this.username} va démarrer le QuickMatch...`);
|
||||||
|
// Si l'invitation est acceptée, lancer QuickMatch pour l'invité après un délai
|
||||||
|
console.log("Invitation acceptée, démarrage du QuickMatch pour l'invité après un délai...");
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("Appel de startQuickMatch(invite)...");
|
||||||
|
startQuickMatch(); // Lancer le jeu après 2 secondes
|
||||||
|
console.log("startQuickMatch appelé.");
|
||||||
|
}, 2000); // 2000 millisecondes = 2 secondes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'invite_response':
|
||||||
|
// Vérifie si l'invitation concerne cet utilisateur (l'invitant)
|
||||||
|
if (data.inviter === this.username) {
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
messageElement.textContent = data.message;
|
||||||
|
chatLog.appendChild(messageElement); // Affiche la réponse dans le chat-log
|
||||||
|
console.log(`Réponse à l'invitation: ${data.message}`);
|
||||||
|
|
||||||
|
if (data.response && data.response.toLowerCase() === 'yes') {
|
||||||
|
console.log("Invitation acceptée, démarrage du QuickMatch pour l'invitant...");
|
||||||
|
console.log("Appel de startQuickMatch...(invite response)");
|
||||||
|
startQuickMatch();
|
||||||
|
console.log("startQuickMatch appelé.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'player_stats':
|
||||||
|
console.log('Player stats received:', data);
|
||||||
|
displayPlayerStats(data.stats);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'error':
|
||||||
|
console.error('Error message received:', data.message);
|
||||||
|
alert('Error: ' + data.message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn('Unhandled message type:', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gestion de la fermeture du WebSocket
|
||||||
|
this.chatSocket.onclose = (event) => {
|
||||||
|
if (event.wasClean) {
|
||||||
|
console.log(`Chat WebSocket closed cleanly for room ${roomName}, code=${event.code}, reason=${event.reason}`);
|
||||||
|
} else {
|
||||||
|
console.error(`Chat WebSocket closed unexpectedly for room ${roomName}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gestion des erreurs WebSocket
|
||||||
|
this.chatSocket.onerror = (error) => {
|
||||||
|
console.error(`Chat WebSocket error in room ${roomName}:`, error);
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error initializing chat WebSocket for room ${roomName}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockUser(targetUser) {
|
||||||
|
this.blockedUsers.push(targetUser);
|
||||||
|
console.log(`User ${targetUser} added to blocked list.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
createRoomTab(roomName) {
|
||||||
|
console.log(`createRoomTab: ${roomName} with username: ${username} and token: ${token}`);
|
||||||
|
|
||||||
|
const tabContainer = document.getElementById('room-tabs-container');
|
||||||
|
if (!tabContainer) {
|
||||||
|
console.error('Room tabs container not found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingTab = Array.from(tabContainer.children).find(tab => tab.dataset.room === roomName);
|
||||||
|
if (existingTab) {
|
||||||
|
console.log(`Tab for room ${roomName} already exists.`);
|
||||||
|
// Vous pouvez ajouter une classe pour indiquer que l'onglet est inactif
|
||||||
|
existingTab.classList.remove('active');
|
||||||
|
} else {
|
||||||
|
console.warn(`Tab for room ${roomName} not found in the HTML.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showRoomTab(roomName) {
|
||||||
|
const tabContainer = document.getElementById('room-tabs-container');
|
||||||
|
const tab = Array.from(tabContainer.children).find(tab => tab.dataset.room === roomName);
|
||||||
|
if (tab) {
|
||||||
|
tab.classList.add('active');
|
||||||
|
console.log(`Showing tab for room: ${roomName}`);
|
||||||
|
} else {
|
||||||
|
console.warn(`Tab for room ${roomName} not found.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switchRoom(roomName) {
|
||||||
|
|
||||||
|
if (!roomName) {
|
||||||
|
console.error('Room name is undefined.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Attempting to switch to room: ${roomName}`);
|
||||||
|
if (activeRoom === roomName) {
|
||||||
|
console.log(`Already in room: ${roomName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Switching from room ${activeRoom} to room ${roomName}`);
|
||||||
|
const previousRoom = activeRoom;
|
||||||
|
activeRoom = roomName;
|
||||||
|
|
||||||
|
if (previousRoom && document.getElementById(`chat-log-${previousRoom}`)) {
|
||||||
|
console.log(`Hiding chat log for previous room: ${previousRoom}`);
|
||||||
|
document.getElementById(`chat-log-${previousRoom}`).style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatLog = document.getElementById(`chat-log-${roomName}`);
|
||||||
|
if (chatLog) {
|
||||||
|
chatLog.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
console.warn(`No chat log found for room: ${roomName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre à jour l'affichage des inputs
|
||||||
|
document.querySelectorAll('.chat-input').forEach(input => {
|
||||||
|
input.style.display = 'none';
|
||||||
|
});
|
||||||
|
document.getElementById(`chat-input-${roomName}`).style.display = 'block';
|
||||||
|
|
||||||
|
// Mettre à jour l'onglet actif
|
||||||
|
const tabs = document.querySelectorAll('.room-tab');
|
||||||
|
tabs.forEach(t => t.classList.remove('active'));
|
||||||
|
const activeTab = Array.from(tabs).find(tab => tab.dataset.room === roomName);
|
||||||
|
if (activeTab) {
|
||||||
|
activeTab.classList.add('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
joinRoom(roomName) {
|
||||||
|
console.log(`Joining room: ${roomName} with username: ${chatManager.username} and token: ${chatManager.token}`);
|
||||||
|
if (activeRoom === roomName) {
|
||||||
|
console.log(`Already in room: ${roomName}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si la room n'a pas de WebSocket actif, on le crée
|
||||||
|
if (!chatManager.roomSockets[roomName]) {
|
||||||
|
console.log(`Joining new room: ${roomName}`);
|
||||||
|
this.createRoomTab(roomName);
|
||||||
|
this.showRoomTab(roomName);
|
||||||
|
this.startChatWebSocket(roomName); // Utilisation du ChatManager pour démarrer le WebSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
this.switchRoom(roomName);
|
||||||
|
// Activer l'affichage du conteneur de chat
|
||||||
|
document.getElementById('chat-container').style.display = 'flex';
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveRoom(roomName) {
|
||||||
|
if (this.roomSockets[roomName]) {
|
||||||
|
console.log(`Leaving room: ${roomName}`);
|
||||||
|
this.roomSockets[roomName].close();
|
||||||
|
delete this.roomSockets[roomName];
|
||||||
|
if (this.activeRoom === roomName) {
|
||||||
|
this.activeRoom = null;
|
||||||
|
this.chatSocket = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn(`No active WebSocket found for room: ${roomName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatInput {
|
||||||
|
constructor(roomName, username, chatSocket, chatManager) {
|
||||||
|
this.roomName = roomName;
|
||||||
|
this.username = username;
|
||||||
|
this.chatSocket = chatSocket;
|
||||||
|
this.chatManager = chatManager;
|
||||||
|
this.messageInput = document.querySelector(`#chat-input-${roomName} input`);
|
||||||
|
this.chatButton = document.querySelector(`#chat-input-${roomName} button`);
|
||||||
|
|
||||||
|
console.log(`ChatInput initialized for room: ${roomName}, username: ${username}`);
|
||||||
|
this.initEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
initEventListeners() {
|
||||||
|
this.messageInput.addEventListener('keypress', (event) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
console.log("Enter key pressed, attempting to send message...");
|
||||||
|
this.sendMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.chatButton.addEventListener('click', () => {
|
||||||
|
console.log("Send button clicked, attempting to send message...");
|
||||||
|
this.sendMessage();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage() {
|
||||||
|
const message = this.messageInput.value.trim();
|
||||||
|
console.log(`Attempting to send message: ${message}`);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
if (message.startsWith('/b ')) {
|
||||||
|
const targetUser = message.slice(3).trim();
|
||||||
|
console.log(`Detected block command for user: ${targetUser}`);
|
||||||
|
this.sendBlockCommand(targetUser);
|
||||||
|
} else if (message.startsWith('/i ')) {
|
||||||
|
const targetUser = message.slice(3).trim();
|
||||||
|
console.log(`Detected invite command for user: ${targetUser}`);
|
||||||
|
this.sendInviteCommand(targetUser);
|
||||||
|
} else if (message.startsWith('/s ')) {
|
||||||
|
const targetUser = message.slice(3).trim();
|
||||||
|
console.log(`Detected stats command for user: ${targetUser}`);
|
||||||
|
sendStatsCommand(targetUser);
|
||||||
|
} else {
|
||||||
|
console.log(`Sending chat message to WebSocket...`);
|
||||||
|
this.chatSocket.send(JSON.stringify({
|
||||||
|
'type': 'chat_message',
|
||||||
|
'username': this.username,
|
||||||
|
'message': message,
|
||||||
|
'room': this.roomName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.messageInput.value = '';
|
||||||
|
console.log("Message input cleared.");
|
||||||
|
} else {
|
||||||
|
console.warn('Cannot send an empty message.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendBlockCommand(targetUser) {
|
||||||
|
this.chatManager.blockUser(targetUser); // Met à jour la liste des utilisateurs bloqués via ChatManager
|
||||||
|
console.log(`Sending block command to WebSocket for user: ${targetUser}`);
|
||||||
|
this.chatSocket.send(JSON.stringify({
|
||||||
|
'type': 'block_user',
|
||||||
|
'username': this.username,
|
||||||
|
'target_user': targetUser,
|
||||||
|
'room': this.roomName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
sendInviteCommand(targetUser) {
|
||||||
|
if (!targetUser) {
|
||||||
|
console.error("Target user is not defined. Cannot send invite.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.username) {
|
||||||
|
console.error("Username is not defined. Cannot send invite.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.roomName) {
|
||||||
|
console.error("Room name is not defined. Cannot send invite.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Sending invite command to WebSocket for user: ${targetUser}`);
|
||||||
|
|
||||||
|
this.chatSocket.send(JSON.stringify({
|
||||||
|
'type': 'invite',
|
||||||
|
'username': this.username, // Utilisateur qui envoie l'invitation
|
||||||
|
'target_user': targetUser, // Utilisateur qui reçoit l'invitation
|
||||||
|
'room': this.roomName // Room où l'invitation est faite
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
@ -200,9 +200,125 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.0/dist/chartjs-adapter-moment.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.0/dist/chartjs-adapter-moment.min.js"></script>
|
||||||
|
|
||||||
<script src="{% static 'game.js' %}"></script>
|
|
||||||
<script src="{% static 'burger.js' %}"></script>
|
<script src="{% static 'burger.js' %}"></script>
|
||||||
|
<script src="{% static 'game.js' %}"></script>
|
||||||
<script src="{% static 'language.js' %}"></script>
|
<script src="{% static 'language.js' %}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
<div id="player-stats" class="player-stats-popup" style="display: none;">
|
||||||
|
<h3>Player Statistics</h3>
|
||||||
|
<p id="stats-username"></p>
|
||||||
|
<p id="stats-total-matches"></p>
|
||||||
|
<p id="stats-total-wins"></p>
|
||||||
|
<p id="stats-win-percentage"></p>
|
||||||
|
<p id="stats-best-score"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="chat-controls">
|
||||||
|
<button id="show-chat">Afficher le Chat</button>
|
||||||
|
<button id="hide-chat">Masquer le Chat</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="chat-container">
|
||||||
|
<!-- Conteneur des journaux de chat -->
|
||||||
|
<div id="chat-log-container">
|
||||||
|
<div id="chat-log-main_room" class="chat-log" style="display:block;"></div>
|
||||||
|
<div id="chat-log-tournament" class="chat-log" style="display:none;"></div>
|
||||||
|
<div id="chat-log-quick_match" class="chat-log" style="display:none;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Entrées de texte et boutons d'envoi pour chaque room -->
|
||||||
|
<div id="chat-input-container">
|
||||||
|
<div id="chat-input-main_room" class="chat-input active">
|
||||||
|
<input type="text" placeholder="Tapez votre message...">
|
||||||
|
<button id="chat-button-main_room" class="chat-button">➤</button>
|
||||||
|
</div>
|
||||||
|
<div id="chat-input-tournament" class="chat-input">
|
||||||
|
<input type="text" placeholder="Tapez votre message...">
|
||||||
|
<button id="chat-button-tournament" class="chat-button">➤</button>
|
||||||
|
</div>
|
||||||
|
<div id="chat-input-quick_match" class="chat-input">
|
||||||
|
<input type="text" placeholder="Tapez votre message...">
|
||||||
|
<button id="chat-button-quick_match" class="chat-button">➤</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Conteneur des onglets de room -->
|
||||||
|
<div id="room-tabs-container">
|
||||||
|
<div class="room-tab active" data-room="main_room">Main Room</div>
|
||||||
|
<div class="room-tab" data-room="tournament">Tournament</div>
|
||||||
|
<div class="room-tab" data-room="quick_match">Quick Match</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const chatContainer = document.getElementById('chat-container');
|
||||||
|
const showChatButton = document.getElementById('show-chat');
|
||||||
|
const hideChatButton = document.getElementById('hide-chat');
|
||||||
|
|
||||||
|
showChatButton.addEventListener('click', function() {
|
||||||
|
chatContainer.style.display = 'flex'; // Afficher le conteneur de chat
|
||||||
|
});
|
||||||
|
|
||||||
|
hideChatButton.addEventListener('click', function() {
|
||||||
|
chatContainer.style.display = 'none'; // Masquer le conteneur de chat
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabs = document.querySelectorAll('.room-tab');
|
||||||
|
const chatLogs = document.querySelectorAll('.chat-log');
|
||||||
|
const chatInputs = document.querySelectorAll('.chat-input');
|
||||||
|
const chatButtons = document.querySelectorAll('.chat-button');
|
||||||
|
|
||||||
|
tabs.forEach(tab => {
|
||||||
|
tab.addEventListener('click', function() {
|
||||||
|
const roomId = this.dataset.room;
|
||||||
|
|
||||||
|
console.log(`Switching to room: ${roomId}`);
|
||||||
|
|
||||||
|
// Afficher le journal de chat correspondant
|
||||||
|
chatLogs.forEach(log => {
|
||||||
|
if (log.id === `chat-log-${roomId}`) {
|
||||||
|
log.style.display = 'block';
|
||||||
|
console.log(`Displaying chat log for: ${roomId}`);
|
||||||
|
} else {
|
||||||
|
log.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Afficher l'entrée de texte correspondante
|
||||||
|
chatInputs.forEach(input => {
|
||||||
|
if (input.id === `chat-input-${roomId}`) {
|
||||||
|
input.classList.add('active');
|
||||||
|
input.style.display = 'flex';
|
||||||
|
console.log(`Displaying chat input for: ${roomId}`);
|
||||||
|
} else {
|
||||||
|
input.classList.remove('active');
|
||||||
|
input.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Afficher le bouton correspondant
|
||||||
|
chatButtons.forEach(button => {
|
||||||
|
if (button.id === `chat-button-${roomId}`) {
|
||||||
|
button.style.display = 'flex';
|
||||||
|
console.log(`Displaying chat button for: ${roomId}`);
|
||||||
|
} else {
|
||||||
|
button.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mettre à jour l'onglet actif
|
||||||
|
tabs.forEach(t => t.classList.remove('active'));
|
||||||
|
this.classList.add('active');
|
||||||
|
console.log(`Tab for ${roomId} is now active`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -470,3 +470,235 @@ canvas {
|
|||||||
color: #00ffff;
|
color: #00ffff;
|
||||||
box-shadow: 0 0 20px #00ffff;
|
box-shadow: 0 0 20px #00ffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************CHAT*************************************/
|
||||||
|
@keyframes borderGlow {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 30px #00ffff, inset 0 0 20px #00ffff;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 60px #0099ff, inset 0 0 40px #0099ff;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 30px #00ffff, inset 0 0 20px #00ffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-container {
|
||||||
|
display: none; /* Masquer par défaut */
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
width: 300px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7); /* Couleur de fond semi-transparente par défaut */
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 0 0 30px #00ffff, inset 0 0 20px #00ffff;
|
||||||
|
z-index: 1000;
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex-direction: column;
|
||||||
|
animation: borderGlow 3s infinite; /* Ajouter l'animation */
|
||||||
|
transition: background-color 0.3s, transform 0.3s; /* Ajouter des transitions */
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-container:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 1); /* Couleur de fond opaque au survol */
|
||||||
|
transform: scale(1.05); /* Agrandir légèrement au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-log {
|
||||||
|
max-height: 150px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: transparent;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
position: relative; /* Assurez-vous que le conteneur parent est positionné */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input.active {
|
||||||
|
display: flex; /* Afficher uniquement l'élément actif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input input[type="text"] {
|
||||||
|
flex: 1;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 28px;
|
||||||
|
width: 250px; /* Réduire la largeur */
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-button {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px; /* Réduire la taille du bouton */
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(45deg, #00ffff, #0099ff);
|
||||||
|
color: #000033;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute; /* Positionner le bouton de manière absolue */
|
||||||
|
right: 10px; /* Ajuster la position à droite */
|
||||||
|
top: 10%; /* Centrer verticalement */
|
||||||
|
transform: translateY(-50%); /* Centrer verticalement */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||||
|
transition: background 0.3s, transform 0.3s;
|
||||||
|
animation: buttonGlow 3s infinite; /* Ajouter l'animation */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-button:hover {
|
||||||
|
background: linear-gradient(45deg, #0099ff, #00ffff);
|
||||||
|
transform: translateY(-50%) scale(1.1); /* Agrandir légèrement au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-button:active {
|
||||||
|
transform: translateY(-50%) scale(0.95); /* Réduire légèrement à l'activation */
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes buttonGlow {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 20px #0099ff, inset 0 0 10px #0099ff;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#room-tabs-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-tab {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
margin-right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #00ffff;
|
||||||
|
background-color: #000033;
|
||||||
|
color: #00ffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
opacity: 0.1;
|
||||||
|
transition: background 0.3s, transform 0.3s; /* Ajouter des transitions */
|
||||||
|
animation: tabGlow 3s infinite; /* Ajouter l'animation */
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-tab:hover {
|
||||||
|
background-color: #00ffff;
|
||||||
|
color: #000033;
|
||||||
|
transform: scale(1.1); /* Agrandir légèrement au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-tab:active {
|
||||||
|
transform: scale(0.95); /* Réduire légèrement à l'activation */
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-tab.active {
|
||||||
|
background-color: #00ffff;
|
||||||
|
color: #000033;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tabGlow {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 20px #0099ff, inset 0 0 10px #0099ff;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-controls {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 320px; /* Correspondre à la position à côté du conteneur de chat */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px; /* Espacement entre les boutons */
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-controls button {
|
||||||
|
width: 100px; /* Correspondre à la taille des boutons */
|
||||||
|
height: 30px; /* Correspondre à la taille des boutons */
|
||||||
|
font-size: 12px; /* Correspondre à la taille de la police */
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #00ffff;
|
||||||
|
color: #000033;
|
||||||
|
border: none;
|
||||||
|
transition: background-color 0.3s, transform 0.3s;
|
||||||
|
animation: buttonGlow 3s infinite; /* Ajouter l'animation */
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-controls button:hover {
|
||||||
|
background-color: #0099ff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
#chat-controls button:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes buttonGlow {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 20px #0099ff, inset 0 0 10px #0099ff;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 10px #00ffff, inset 0 0 5px #00ffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-stats-popup {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 320px; /* Adjust to appear above the chat */
|
||||||
|
width: 300px;
|
||||||
|
background-color: rgba(0, 0, 40, 0.9);
|
||||||
|
color: #00ffff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 0 20px #00ffff, inset 0 0 10px #00ffff;
|
||||||
|
z-index: 2000;
|
||||||
|
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-stats-popup.show {
|
||||||
|
display: block;
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-stats-popup.hide {
|
||||||
|
transform: translateY(20px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|||||||