versionpostpull

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

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