versionpostpull

This commit is contained in:
Ladebeze66 2024-09-17 20:26:15 +02:00
commit f2878b3a5e
30 changed files with 5059 additions and 460 deletions

View File

@ -1,3 +1,4 @@
services:
nginx:
image: nginx:latest
@ -22,7 +23,7 @@ services:
restart: always
command: /bin/sh -c "sleep 5 &&
venv/bin/python manage.py makemigrations --noinput &&
venv/bin/python manage.py migrate --noinput &&
venv/bin/python manage.py migrate --noinput &&
venv/bin/python manage.py collectstatic --noinput &&
venv/bin/daphne -b 0.0.0.0 -p 8080 pong.asgi:application"
volumes:

View File

@ -6,7 +6,7 @@ DJANGO_ALLOWED_HOSTS=['*']
# PostgreSQL settings
POSTGRES_DB=players_db
POSTGRES_USER=42student
POSTGRES_PASSWORD=postgre_pass
POSTGRES_PASSWORD=
# Django settings
DB_HOST=db
@ -20,11 +20,11 @@ CLUSTER_NAME=docker-cluster
LICENSE=basic
ELASTIC_USERNAME=elastic
ELASTIC_PASSWORD=elastic_pass
ELASTIC_PASSWORD=
# Kibana settings
KIBANA_PORT=5601
KIBANA_USERNAME=kibana_system
KIBANA_PASSWORD=kibana_pass
KIBANA_PASSWORD=
ENCRYPTION_KEY=c34d38b3a14956121ff2170e5030b471551370178f43e5626eec58b04a30fae2

View 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

View 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

View 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.

View 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

View 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

View 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

View 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:

File diff suppressed because it is too large Load Diff

1826
logs/django.log Normal file

File diff suppressed because it is too large Load Diff

0
logs/django_errors.log Normal file
View File

View File

@ -81,3 +81,4 @@ help:
.PHONY: up build start stop down destroy logs ps db-shell help

View File

@ -28,3 +28,4 @@ application = ProtocolTypeRouter({
)
),
})

View File

@ -1,106 +1,418 @@
# /pong/game/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
from channels.db import database_sync_to_async
from .matchmaking import match_maker
from .tournament import tournament_match_maker
from .models import Player
import asyncio
import logging
logger = logging.getLogger(__name__)
class GameConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
self.game = None
print("User connected")
async def connect(self):
await self.accept()
self.game = None
print("User connected")
async def receive(self, text_data):
data = json.loads(text_data)
if data['type'] == 'authenticate':
await self.authenticate(data['token'])
elif data['type'] == 'authenticate2':
await self.authenticate2(data['token_1'], data['token_2'])
elif data['type'] == 'authenticate3':
await self.authenticate3(data['token'])
elif data['type'] == 'key_press':
if self.game:
await self.game.handle_key_press(self, data['key'])
elif data['type'] == 'start_tournament':
print(f"Start TOURNAMENT received by {self.user}")
# Run the tournament in the background
asyncio.create_task(tournament_match_maker.start_tournament())
async def receive(self, text_data):
data = json.loads(text_data)
if data['type'] == 'authenticate':
await self.authenticate(data['token'])
elif data['type'] == 'authenticate2':
await self.authenticate2(data['token_1'], data['token_2'])
elif data['type'] == 'authenticate3':
await self.authenticate3(data['token'])
elif data['type'] == 'key_press':
if self.game:
await self.game.handle_key_press(self, data['key'])
elif data['type'] == 'start_tournament':
print(f"Start TOURNAMENT received by {self.user}")
# Run the tournament in the background
asyncio.create_task(tournament_match_maker.start_tournament())
async def authenticate(self, token):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user} authenticated")
await self.join_waiting_room()
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
async def authenticate(self, token):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user} authenticated")
await self.join_waiting_room()
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
@database_sync_to_async
def get_user_from_token(self, token):
try:
user = User.objects.filter(auth_token=token).first()
return user
except User.DoesNotExist:
return None
@database_sync_to_async
def get_user_from_token(self, token):
try:
user = User.objects.filter(auth_token=token).first()
return user
except User.DoesNotExist:
return None
async def join_waiting_room(self):
await self.send(text_data=json.dumps({'type': 'waiting_room'}))
await match_maker.add_player(self)
async def join_waiting_room(self):
await self.send(text_data=json.dumps({'type': 'waiting_room'}))
await match_maker.add_player(self)
async def authenticate2(self, token, token2):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user} authenticated")
user2 = await self.get_user_from_token2(token2)
if user2:
self.user2 = user2
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user2} authenticated")
await match_maker.create_game(self, None, True)
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
async def authenticate2(self, token, token2):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user} authenticated")
user2 = await self.get_user_from_token2(token2)
if user2:
self.user2 = user2
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user2} authenticated")
await match_maker.create_game(self, None, True)
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Authentication failed")
@database_sync_to_async
def get_user_from_token2(self, token):
try:
user2 = User.objects.filter(auth_token=token).first()
return user2
except User.DoesNotExist:
return None
@database_sync_to_async
def get_user_from_token2(self, token):
try:
user2 = User.objects.filter(auth_token=token).first()
return user2
except User.DoesNotExist:
return None
async def authenticate3(self, token):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user.username} authenticated for tournament")
await self.join_tournament_waiting_room()
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Tournament authentication failed")
async def authenticate3(self, token):
user = await self.get_user_from_token(token)
if user:
self.user = user
await self.send(text_data=json.dumps({'type': 'authenticated'}))
print(f"User {self.user.username} authenticated for tournament")
await self.join_tournament_waiting_room()
else:
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
print("Tournament authentication failed")
async def join_tournament_waiting_room(self):
await tournament_match_maker.add_player(self)
async def join_tournament_waiting_room(self):
await tournament_match_maker.add_player(self)
async def disconnect(self, close_code):
if self.game:
await self.game.end_game(disconnected_player=self)
await match_maker.remove_player(self)
await tournament_match_maker.remove_player(self)
print(f"User {self.user.username if hasattr(self, 'user') else 'Unknown'} disconnected")
async def disconnect(self, close_code):
if self.game:
await self.game.end_game(disconnected_player=self)
await match_maker.remove_player(self)
await tournament_match_maker.remove_player(self)
print(f"User {self.user.username if hasattr(self, 'user') else 'Unknown'} disconnected")
async def set_game(self, game):
print(f"({self.user}) Game set to: {game}")
self.game = game
async def set_game(self, game):
print(f"({self.user}) Game set to: {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

View File

@ -9,7 +9,6 @@ from asgiref.sync import sync_to_async
from .models import Tournoi
class Game:
def __init__(self, game_id, player1, player2, localgame):
self.game_id = game_id
self.player1 = player1
@ -51,7 +50,6 @@ class Game:
self.bt1 = 0
self.bt2 = 0
self.start_time = datetime.now()
self.future_ball_position = {'x': 390, 'y': 190}
async def start_game(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):
print(" In the game loop..")
x = 59
x = 0
while not self.ended:
if self.botgame:
x += 1
if x == 60:
# Random BOT difficulty..
steps = 60#random.randint(10, 60)
self.future_ball_position = await self.predict_ball_trajectory(steps)
await self.update_bot_position()
x = 0
if self.botgame:
await self.update_bot_position()
await self.handle_pad_movement()
await self.update_game_state()
await self.send_game_state()
await asyncio.sleep(1/60) # Around 60 FPS
async def update_bot_position(self):
#future_ball_position = self.predict_ball_trajectory()
target_y = self.future_ball_position['y']
future_ball_position = self.predict_ball_trajectory()
target_y = future_ball_position['y']
player2_position = self.game_state['player2_position']
# Adjusts bot position based on expected ball position
if player2_position < target_y < player2_position + 80:
pass #bot already placed
elif player2_position < target_y:
self.p2_mov = 1
#self.game_state['player2_position'] = min(player2_position + (50 * self.speed), 300)
#self.p2_mov = 1
self.game_state['player2_position'] = min(player2_position + (50 * self.speed), 300)
elif player2_position + 80 > target_y:
self.p2_mov = -1
#self.game_state['player2_position'] = max(player2_position - (50 * self.speed), 0)
#self.p2_mov = -1
self.game_state['player2_position'] = max(player2_position - (50 * self.speed), 0)
async def predict_ball_trajectory(self, steps=60):
def predict_ball_trajectory(self, steps=60):
future_x = self.game_state['ball_position']['x']
future_y = self.game_state['ball_position']['y']
velocity_x = self.game_state['ball_velocity']['x']
velocity_y = self.game_state['ball_velocity']['y']
for _ in range(steps):
future_x += velocity_x
if future_x <= 10:
@ -105,9 +102,11 @@ class Game:
future_x = 790
else:
future_y += velocity_y
# Dealing with bounces off walls
if future_y <= 10 or future_y >= 390:
velocity_y = -velocity_y # Reverse the direction of vertical movement
# Dealing with bounces off walls
if future_y <= 10 or future_y >= 390:
velocity_y = -velocity_y # Reverse the direction of vertical movement
return {'x': future_x, 'y': future_y}
async def update_game_state(self):

View File

@ -1,8 +1,15 @@
# /pong/game/routing.py
from django.urls import re_path
from . import consumers
import logging
logger = logging.getLogger(__name__)
logger.debug("Configuring WebSocket routing patterns")
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")

View File

@ -10,6 +10,13 @@ from .models import Tournoi
from .utils import create_tournament, update_tournament, getlen
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 = [
"Champion's Clash", "Ultimate Showdown", "Battle Royale",
"Victory's Cup", "Legends Tournament", "Elite Series", "Clash of 42",
@ -82,13 +89,13 @@ class TournamentMatchMaker:
# Tournament start method
async def start_tournament(self):
if len(self.waiting_players) < 3:
if len(self.waiting_players) < 2:
return False
random.shuffle(self.waiting_players)
'''if (len(self.waiting_players) % 2) != 0:
print("Adding a BYE to the tournament..")
await self.add_player(None)'''
if len(self.waiting_players) % 2 == 0:
await self.add_player(None)
self.tournament_state = "in_progress"
random.shuffle(self.waiting_players)
self.current_round = 0
len_tournament = await sync_to_async(getlen)()
self.final_name = self.name + " #" + str(len_tournament + 1)
@ -97,7 +104,7 @@ class TournamentMatchMaker:
return True
async def advance_tournament(self):
players = self.waiting_players
players = self.waiting_players
while len(players) > 1:
self.current_round += 1
print(f"Starting round {self.current_round} with {len(players)} players")
@ -171,12 +178,16 @@ class TournamentMatchMaker:
print(f"Starting TOURNAMENT round #{self.current_round}")
for match in self.rounds[-1]:
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)
asyncio.create_task(match.start_game())
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)
#asyncio.create_task(match.start_game())
match.game_state['player1_score'] = 3
match.game_state['player2_score'] = 0
await match.end_game()
@ -215,7 +226,6 @@ class TournamentMatchMaker:
self.rounds = []
self.current_round = 0
self.games = 0
self.tournament_state = "waiting"
async def handle_match_end(self, match):
await self.update_brackets()

View File

@ -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_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)
print("and ADRIANO is the PEST")
update_player_statistics(p1)
print("UPDATE PLAYER 1")

View File

@ -95,22 +95,15 @@ def player_list_json(request):
}
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):
tournois = Tournoi.objects.select_related('winner').all() # Charge les données du gagnant
tournois_data = [get_tournoi_data(tournoi) for tournoi in tournois]
return JsonResponse({"tournois": tournois_data})
tournois = Tournoi.objects.all()
data = {
'tournois': list(tournois.values(
'id', 'name', 'nbr_player', 'date', 'winner'
))
}
return JsonResponse(data)
from web3 import Web3

View File

@ -58,19 +58,19 @@ MIDDLEWARE = [
ROOT_URLCONF = 'pong.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'pong', 'static')], # Ensure templates are found
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'pong', 'static')], # Ensure templates are found
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
ASGI_APPLICATION = 'pong.asgi.application'
@ -94,18 +94,18 @@ DATABASES = {
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
@ -121,10 +121,6 @@ USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'pong/static')]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
@ -136,10 +132,11 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Channels
# Define the channel layers for WebSockets
# Define the channel layers for WebSockets
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
},
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
},
}
LOGGING = {

View File

@ -75,18 +75,31 @@ document.addEventListener('DOMContentLoaded', () => {
.catch(error => console.error('Error fetching match data:', error));
}
function fetchPlayers(){
function fetchPlayers() {
console.log('Fetching players...');
fetch('/api/player_list/')
.then(response => response.json())
// Retourner la promesse pour permettre l'utilisation de .then() plus tard
return fetch('/api/player_list/')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
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(){
console.log('Fetching tournois...');
fetch('/api/tournoi_list/')
@ -103,11 +116,10 @@ document.addEventListener('DOMContentLoaded', () => {
console.log('Displaying matches:');
const matchListBody = document.querySelector('#match-list tbody');
matchListBody.innerHTML = '';
const row = document.createElement('tr');
if (matches.length != 0) {
matches.forEach(match => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${match.id}</td>
<td>${match.player1__name}</td>
@ -125,7 +137,6 @@ document.addEventListener('DOMContentLoaded', () => {
matchListBody.appendChild(row);
});
} else {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="12">No matches found.</td>
`;
@ -137,11 +148,10 @@ document.addEventListener('DOMContentLoaded', () => {
console.log('Displaying players:');
const playersListBody = document.querySelector('#player-list tbody');
playersListBody.innerHTML = '';
const row = document.createElement('tr');
if (players.length != 0) {
players.forEach(player => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${player.id}</td>
<td>${player.name}</td>
@ -160,9 +170,8 @@ document.addEventListener('DOMContentLoaded', () => {
playersListBody.appendChild(row);
});
} else {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="12">No player found.</td>
<td colspan="12">No matches found.</td>
`
playersListBody.appendChild(row);
}
@ -172,25 +181,22 @@ document.addEventListener('DOMContentLoaded', () => {
console.log('Displaying tournois:');
const tournoisListBody = document.querySelector('#tournoi-list tbody');
tournoisListBody.innerHTML = '';
const row = document.createElement('tr');
if (tournois.length != 0) {
tournois.forEach(tournoi => {
console.log('Winner:', tournoi.winner); //debug !!!!!!!!!!!!!!!!!
console.log('Winner:', tournoi.winner__name); //debug !!!!!!!!!!!!!!!!!
const row = document.createElement('tr');
row.innerHTML = `
<td>${tournoi.id}</td>
<td>${tournoi.name}</td>
<td>${tournoi.nbr_player}</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);
});
} else {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="12">No tournoi found.</td>
<td colspan="12">No matches found.</td>
`
tournoisListBody.appendChild(row);
}

0
pong/static/flags/de.svg Executable file → Normal file
View 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
View File

Before

Width:  |  Height:  |  Size: 415 KiB

After

Width:  |  Height:  |  Size: 415 KiB

0
pong/static/flags/fr.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 946 B

After

Width:  |  Height:  |  Size: 946 B

0
pong/static/flags/it.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 959 B

After

Width:  |  Height:  |  Size: 959 B

0
pong/static/flags/us.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because it is too large Load Diff

View File

@ -200,9 +200,125 @@
<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="{% static 'game.js' %}"></script>
<script src="{% static 'burger.js' %}"></script>
<script src="{% static 'game.js' %}"></script>
<script src="{% static 'language.js' %}"></script>
</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>

View File

@ -469,4 +469,236 @@ canvas {
background-color: #000033;
color: #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;
}