diff --git a/.env b/.env index 66aac01..28e29d9 100644 --- a/.env +++ b/.env @@ -13,6 +13,7 @@ DB_HOST=db DB_PORT=5432 PWD_PATH=${PWD} PROJECT_PATH=${PWD_PATH}/pong +DJANGO_LOGS=${PWD_PATH}/logs # ElasticSearch settings STACK_VERSION=8.14.3 diff --git a/config/logstash.conf b/config/logstash.conf index 602a7df..329a522 100644 --- a/config/logstash.conf +++ b/config/logstash.conf @@ -1,13 +1,17 @@ input { file { - path => "/transcendence/django.log" # Adjust this path to where the log file is stored - start_position => "beginning" + path => "/usr/share/logstash/logs/django.log" + start_position => "beginning" sincedb_path => "/dev/null" codec => "json" } } filter { + json { + source => "message" + target => "json_message" + } } output { @@ -20,5 +24,5 @@ output { ssl_verification_mode => "full" index => "django-logs-%{+YYYY.MM.dd}" } - stdout { codec => rubydebug } # Optional: For debugging purposes -} + stdout { codec => rubydebug } + } diff --git a/docker-compose.yml b/docker-compose.yml index 86419bb..e4c2828 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,6 +74,7 @@ services: venv/bin/daphne -b 0.0.0.0 -p 8080 pong.asgi:application" volumes: - pong:/transcendence/pong + - pong_django_logs:/transcendence/logs ports: - 8080:8080 networks: @@ -200,6 +201,7 @@ services: - certs:/usr/share/logstash/certs - pong_logstash_data01:/usr/share/logstash/data - ./config/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro + - pong_django_logs:/usr/share/logstash/logs ports: - "5044:5044/udp" command: logstash -f /usr/share/logstash/pipeline/logstash.conf @@ -217,6 +219,12 @@ volumes: type: none device: ${PROJECT_PATH} o: bind + pong_django_logs: + driver: local + driver_opts: + type: none + device: ${DJANGO_LOGS} + o: bind pong_pg_data: driver: local pong_es_data_01: diff --git a/logs/django.log b/logs/django.log new file mode 100644 index 0000000..e69de29 diff --git a/makefile b/makefile index 36ad556..81d3320 100644 --- a/makefile +++ b/makefile @@ -2,9 +2,7 @@ COMPOSE_FILE=docker-compose.yml COMPOSE=docker compose -f $(COMPOSE_FILE) CONTAINER=$(c) -.PHONY: up build start stop down destroy logs ps db-shell help - -up: +up: down $(COMPOSE) build $(COMPOSE) up $(CONTAINER) || true @@ -48,3 +46,5 @@ help: @echo " make ps # List containers" @echo " make help # Show this help" +.PHONY: up build start stop down destroy logs ps db-shell help + diff --git a/pong/game/consumers.py b/pong/game/consumers.py index b473ece..e3d68a1 100644 --- a/pong/game/consumers.py +++ b/pong/game/consumers.py @@ -16,6 +16,8 @@ class GameConsumer(AsyncWebsocketConsumer): 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'] == 'key_press': if self.game: await self.game.handle_key_press(self, data['key']) @@ -45,6 +47,33 @@ class GameConsumer(AsyncWebsocketConsumer): 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") + + @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 disconnect(self, close_code): if self.game: await self.game.end_game(disconnected_player=self) diff --git a/pong/game/game.py b/pong/game/game.py index 7ff81f3..31048af 100644 --- a/pong/game/game.py +++ b/pong/game/game.py @@ -6,23 +6,36 @@ import random from datetime import datetime from .utils import endfortheouche - class Game: - def __init__(self, game_id, player1, player2): + def __init__(self, game_id, player1, player2, localgame): self.game_id = game_id self.player1 = player1 self.player2 = player2 - self.botgame = player2 is None - self.game_state = { - 'player1_name': player1.user.username, - 'player2_name': player2.user.username if player2 else 'BOT', - 'player1_position': 150, - 'player2_position': 150, - 'ball_position': {'x': 390, 'y': 190}, - 'ball_velocity': {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])}, - 'player1_score': 0, - 'player2_score': 0 - } + self.localgame = localgame + if self.localgame: + self.botgame = False + self.game_state = { + 'player1_name': player1.user.username, + 'player2_name': player1.user2.username, + 'player1_position': 150, + 'player2_position': 150, + 'ball_position': {'x': 390, 'y': 190}, + 'ball_velocity': {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])}, + 'player1_score': 0, + 'player2_score': 0 + } + else: + self.botgame = player2 is None + self.game_state = { + 'player1_name': player1.user.username, + 'player2_name': player2.user.username if player2 else 'BOT', + 'player1_position': 150, + 'player2_position': 150, + 'ball_position': {'x': 390, 'y': 190}, + 'ball_velocity': {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])}, + 'player1_score': 0, + 'player2_score': 0 + } self.speed = 1 self.game_loop_task = None self.ended = False @@ -31,21 +44,18 @@ class Game: self.bt1 = 0 self.bt2 = 0 self.start_time = None - - async def start_game(self): print(f"- Game #{self.game_id} STARTED") self.game_loop_task = asyncio.create_task(self.game_loop()) - print(" begin MATCH at : ") self.start_time = datetime.now() - print(f" begin MATCH : {self.start_time} ") + print(f" Begin MATCH at: {self.start_time}") async def game_loop(self): + print(" In the game loop..") while not self.ended: if self.botgame: - await self.update_bot_position() - + await self.update_bot_position() await self.handle_pad_movement() await self.update_game_state() await self.send_game_state() @@ -60,7 +70,6 @@ class Game: elif self.game_state['player2_position'] + 80 > target_y: self.game_state['player2_position'] = max(self.game_state['player2_position'] - (5 * self.speed), 0) - async def update_game_state(self): if self.ended: return @@ -84,18 +93,19 @@ class Game: self.bt2 += 1 self.update_ball_velocity() # Check for scoring - print(f"########### score user 1 {self.game_state['player1_score']} ###########") - print(f"§§§§§§§§§§§ score user 2 {self.game_state['player2_score']} §§§§§§§§§§§") + #print(f"########### score user 1 {self.game_state['player1_score']} ###########") + #print(f"§§§§§§§§§§§ score user 2 {self.game_state['player2_score']} §§§§§§§§§§§") if self.game_state['ball_position']['x'] <= 10: self.game_state['player2_score'] += 1 - if self.game_state['player2_score'] >= 2: + if self.game_state['player2_score'] > 2: print("Here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") await self.end_game() self.reset_ball() elif self.game_state['ball_position']['x'] >= 790: self.game_state['player1_score'] += 1 - if self.game_state['player1_score'] >= 2: + if self.game_state['player1_score'] > 2: + print("Here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") await self.end_game() self.reset_ball() @@ -128,30 +138,33 @@ class Game: }) await self.player1.send(message) if not self.botgame: - await self.player2.send(message) + if not self.localgame: + await self.player2.send(message) async def handle_key_press(self, player, key): if self.ended: return - if player == self.player1: - print(f"Key press: {key}") - if key == 'arrowup': - self.p1_mov = -1 - #self.game_state['player1_position'] = max(self.game_state['player1_position'] - 25, 0) - elif key == 'arrowdown': - self.p1_mov = 1 - #self.game_state['player1_position'] = min(self.game_state['player1_position'] + 25, 300) - elif not self.botgame and player == self.player2: + if self.localgame: + if key == 'arrowup': + self.p2_mov = -1 + elif key == 'arrowdown': + self.p2_mov = 1 + elif key == 'w': + self.p1_mov = -1 + elif key == 's': + self.p1_mov = 1 + elif player == self.player1: + if key == 'arrowup': + self.p1_mov = -1 + elif key == 'arrowdown': + self.p1_mov = 1 + elif player == self.player2: if key == 'arrowup': self.p2_mov = -1 - #self.game_state['player2_position'] = max(self.game_state['player2_position'] - 25, 0) elif key == 'arrowdown': self.p2_mov = 1 - #self.game_state['player2_position'] = min(self.game_state['player2_position'] + 25, 300) async def handle_pad_movement(self): - #print(f"P1 mov: {self.p1_mov}") - #print(f"P2 mov: {self.p2_mov}") if self.ended: return if self.p1_mov == -1: @@ -192,9 +205,9 @@ class Game: }) await self.player1.send(end_message) if not self.botgame: - await self.player2.send(end_message) + if not self.localgame: + await self.player2.send(end_message) print("save data") await endfortheouche(self.game_state['player1_name'], self.game_state['player2_name'], self.game_state['player1_score'], self.game_state['player2_score'], self.bt1, self.bt2, duration, False, None) - diff --git a/pong/game/matchmaking.py b/pong/game/matchmaking.py index 7becf72..4939c87 100644 --- a/pong/game/matchmaking.py +++ b/pong/game/matchmaking.py @@ -35,7 +35,7 @@ class MatchMaker: player1 = self.waiting_players.pop(0) player2 = self.waiting_players.pop(0) print(f"*** MATCH FOUND: {player1.user.username} vs {player2.user.username}") - await self.create_game(player1, player2) + await self.create_game(player1, player2, False) else: await asyncio.sleep(1) self.timer += 1 @@ -49,26 +49,30 @@ class MatchMaker: if not self.waiting_players: break - async def create_game(self, player1, player2): + async def create_game(self, player1, player2, localgame): game_id = len(self.active_games) + 1 - print(f"- Creating game: #{game_id}") - new_game = Game(game_id, player1, player2) + if localgame: + print(f"- Creating LOCAL game: #{game_id}") + else: + print(f"- Creating MATCH game: #{game_id}") + new_game = Game(game_id, player1, player2, localgame) self.active_games[game_id] = new_game await player1.set_game(new_game) - await player2.set_game(new_game) - await self.notify_players(player1, player2, game_id) + if not localgame: + await player2.set_game(new_game) + await self.notify_players(player1, player2, game_id, localgame) asyncio.create_task(new_game.start_game()) async def create_bot_game(self, player1): game_id = len(self.active_games) + 1 print(f"- Creating BOT game: #{game_id}") - new_game = Game(game_id, player1, None) + new_game = Game(game_id, player1, None, False) self.active_games[game_id] = new_game await player1.set_game(new_game) - await self.notify_players(player1, None, game_id) + await self.notify_players(player1, None, game_id, False) asyncio.create_task(new_game.start_game()) - async def notify_players(self, player1, player2, game_id): + async def notify_players(self, player1, player2, game_id, localgame): if player2: await player1.send(json.dumps({ 'type': 'game_start', @@ -83,12 +87,20 @@ class MatchMaker: 'player2': player2.user.username })) else: - await player1.send(json.dumps({ - 'type': 'game_start', - 'game_id': game_id, - 'player1': player1.user.username, - 'player2': 'BOT' - })) + if localgame: + await player1.send(json.dumps({ + 'type': 'game_start', + 'game_id': game_id, + 'player1': player1.user.username, + 'player2': player1.user2.username + })) + else: + await player1.send(json.dumps({ + 'type': 'game_start', + 'game_id': game_id, + 'player1': player1.user.username, + 'player2': 'BOT' + })) async def handle_key_press(self, player, key): for game in self.active_games.values(): diff --git a/pong/game/views.py b/pong/game/views.py index e810b78..b63e7b4 100644 --- a/pong/game/views.py +++ b/pong/game/views.py @@ -18,6 +18,16 @@ from rest_framework import viewsets import json import uuid +@csrf_exempt +def check_user_exists(request): + if request.method == 'POST': + data = json.loads(request.body) + username = data.get('username') + if User.objects.filter(username=username).exists(): + return JsonResponse({'exists': True}) + return JsonResponse({'exists': False}) + return JsonResponse({'error': 'Invalid request method'}, status=400) + @csrf_exempt def register_user(request): if request.method == 'POST': @@ -31,16 +41,6 @@ def register_user(request): return JsonResponse({'registered': False, 'error': 'User already exists'}) return JsonResponse({'error': 'Invalid request method'}, status=400) -@csrf_exempt -def check_user_exists(request): - if request.method == 'POST': - data = json.loads(request.body) - username = data.get('username') - if User.objects.filter(username=username).exists(): - return JsonResponse({'exists': True}) - return JsonResponse({'exists': False}) - return JsonResponse({'error': 'Invalid request method'}, status=400) - @csrf_exempt def authenticate_user(request): if request.method == 'POST': @@ -86,8 +86,8 @@ def tournoi_list(request): from django.http import JsonResponse -def match_list_json(request): - matches = Match.objects.all() +async def match_list_json(request): + matches = await Match.objects.all() data = { 'matches': list(matches.values( 'id', 'player1__name', 'player2__name', 'score_player1', 'score_player2', @@ -97,9 +97,9 @@ def match_list_json(request): } return JsonResponse(data) -def player_list_json(request): +async def player_list_json(request): # Récupère tous les joueurs - players = Player.objects.all() + players = await Player.objects.all() # Crée un dictionnaire avec les informations des joueurs data = { @@ -114,9 +114,9 @@ def player_list_json(request): # Renvoie les données en JSON return JsonResponse(data) -def tournoi_list_json(request): +async def tournoi_list_json(request): # Récupère tous les joueurs - tournois = Tournoi.objects.all() + tournois = await Tournoi.objects.all() # Crée un dictionnaire avec les informations des joueurs data = { diff --git a/pong/settings.py b/pong/settings.py index 6c171ec..1f8d1ce 100644 --- a/pong/settings.py +++ b/pong/settings.py @@ -153,7 +153,7 @@ LOGGING = { 'file': { 'level': 'INFO', # Minimum log level to be handled (INFO and above) 'class': 'logging.FileHandler', - 'filename': os.path.join(BASE_DIR, 'django.log'), # The file where logs will be saved + 'filename': os.path.join(BASE_DIR, 'logs/django.log'), # The file where logs will be saved 'formatter': 'json', # Uses the JSON formatter defined above }, 'console': { diff --git a/pong/static/game.js b/pong/static/game.js index 0698013..1a65cdf 100644 --- a/pong/static/game.js +++ b/pong/static/game.js @@ -1,29 +1,54 @@ document.addEventListener('DOMContentLoaded', () => { - console.log('DOMContentLoaded event fired'); - const checkNicknameButton = document.getElementById('check-nickname'); - const registerButton = document.getElementById('register'); - const loginButton = document.getElementById('login'); + const formBlock = document.getElementById('block-form'); + const authForm = document.getElementById('auth-form'); - const gameContainer = document.getElementById('game1'); const nicknameInput = document.getElementById('nickname'); + const checkNicknameButton = document.getElementById('check-nickname'); + + const registerForm = document.getElementById('register-form'); const passwordInput = document.getElementById('password'); const confirmPasswordInput = document.getElementById('confirm-password'); - const loginPasswordInput = document.getElementById('login-password'); + const registerButton = document.getElementById('register'); + const loginForm = document.getElementById('login-form'); - const registerForm = document.getElementById('register-form'); - const formBlock = document.getElementById('block-form'); + const loginPasswordInput = document.getElementById('login-password'); + const loginButton = document.getElementById('login'); + + const authForm2 = document.getElementById('auth-form2'); + const nicknameInput2 = document.getElementById('nickname2'); + const checkNicknameButton2 = document.getElementById('check-nickname2'); + + const registerForm2 = document.getElementById('register-form2'); + const passwordInput2 = document.getElementById('password2'); + const confirmPasswordInput2 = document.getElementById('confirm-password2'); + const registerButton2 = document.getElementById('register2'); + + const loginForm2 = document.getElementById('login-form2'); + const loginPasswordInput2 = document.getElementById('login-password2'); + const loginButton2 = document.getElementById('login2'); + + const gameContainer = document.getElementById('game1'); + const menuButton = document.querySelector('.burger-menu'); + const dropdownMenu = document.getElementById('dropdown-menu'); + const playerList = document.getElementById('player-list'); const matchList = document.getElementById('match-list'); const tournoiList = document.getElementById('tournoi-list'); - const dropdownMenu = document.getElementById('dropdown-menu'); + const blockchainList = document.getElementById('blockchain-list'); const pongElements = document.getElementById('pong-elements'); const logo = document.querySelector('.logo'); + const localGameButton = document.getElementById('local-game'); const quickMatchButton = document.getElementById('quick-match'); const tournamentButton = document.getElementById('tournament'); + /* const modal = document.getElementById("myModal"); + const btn = document.getElementById("myBtn"); + const span = document.getElementsByClassName("close")[0]; + const jsonContent = document.getElementById("jsonContent"); */ + let socket; let token; let gameState; @@ -41,11 +66,15 @@ document.addEventListener('DOMContentLoaded', () => { registerButton.addEventListener('click', handleRegister); loginButton.addEventListener('click', handleLogin); + checkNicknameButton2.addEventListener('click', handleCheckNickname2); + registerButton2.addEventListener('click', handleRegister2); + loginButton2.addEventListener('click', handleLogin2); + + localGameButton.addEventListener('click', startLocalGame); quickMatchButton.addEventListener('click', startQuickMatch); tournamentButton.addEventListener('click', startTournament); - async function handleCheckNickname() { const nickname = nicknameInput.value.trim(); if (nickname) { @@ -109,13 +138,7 @@ document.addEventListener('DOMContentLoaded', () => { const result = await registerUser(nickname, password); if (result) { registerForm.style.display = 'none'; - //gameContainer.style.display = 'flex'; - //formBlock.style.display = 'none'; - //logo.style.display = 'none'; - pongElements.style.display = 'none'; - console.log("new button must appear !"); - document.getElementById("post-form-buttons").style.display = 'inline-block'; - //startWebSocketConnection(token); + document.getElementById("post-form-buttons").style.display = 'block'; } else { alert('Registration failed. Please try again.'); } @@ -149,13 +172,7 @@ document.addEventListener('DOMContentLoaded', () => { const result = await authenticateUser(nickname, password); if (result) { loginForm.style.display = 'none'; - //gameContainer.style.display = 'flex'; - //formBlock.style.display = 'none'; - //logo.style.display = 'none'; - //pongElements.style.display = 'none'; - console.log("new button must appear !"); - document.getElementById("post-form-buttons").style.display = 'inline-block'; - //startWebSocketConnection(token); + document.getElementById("post-form-buttons").style.display = 'block'; } else { alert('Authentication failed. Please try again.'); } @@ -164,18 +181,6 @@ document.addEventListener('DOMContentLoaded', () => { } } - function startQuickMatch() { - gameContainer.style.display = 'flex'; - logo.style.display = 'none'; - menuButton.style.display = 'none'; - formBlock.style.display = 'none'; - startWebSocketConnection(token); - } - - function startTournament() { - console.log("For now, do nothing, hurry up and work Senor chaku !!!!") - } - async function authenticateUser(username, password) { const response = await fetch('/authenticate_user/', { method: 'POST', @@ -191,12 +196,176 @@ document.addEventListener('DOMContentLoaded', () => { return data.authenticated; } - function startWebSocketConnection(token) { + // functions to handle the second player + + async function handleCheckNickname2() { + const nickname2 = nicknameInput2.value.trim(); + if (nickname2) { + try { + const exists = await checkUserExists2(nickname2); + if (exists) { + authForm2.style.display = 'none'; + loginForm2.style.display = 'block'; + // Auto-focus and key handling for LOGIN-FORM2 + loginPasswordInput2.focus(); + loginPasswordInput2.addEventListener('keypress', function (event) { + if (event.key === 'Enter') { + event.preventDefault(); + loginButton2.click(); + } + }); + } else { + authForm2.style.display = 'none'; + registerForm2.style.display = 'block'; + // Auto-focus and key handling for REGISTER-FORM2 + passwordInput2.focus(); + passwordInput2.addEventListener('keypress', function (event) { + if (event.key === 'Enter') { + confirmPasswordInput2.focus(); + confirmPasswordInput2.addEventListener('keypress', function (event) { + if (event.key === 'Enter') { + event.preventDefault(); + registerButton2.click(); + } + }); + } + }); + } + } catch (error) { + console.error('Error checking user existence:', error); + } + } else { + alert('Please enter a nickname.'); + } + } + + async function checkUserExists2(username) { + const response = await fetch('/check_user_exists/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ username }) + }); + const data = await response.json(); + return data.exists; + } + + async function handleRegister2() { + const nickname2 = nicknameInput2.value.trim(); + const password2 = passwordInput2.value.trim(); + const confirmPassword2 = confirmPasswordInput2.value.trim(); + + if (password2 === confirmPassword2) { + try { + const result = await registerUser2(nickname2, password2); + if (result) { + registerForm2.style.display = 'none'; + startLocalGame2(); + } else { + alert('Registration failed. Please try again.'); + } + } catch (error) { + console.error('Error registering user:', error); + } + } else { + alert('Passwords do not match.'); + } + } + + async function registerUser2(username, password) { + const response = await fetch('/register_user/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ username, password }) + }); + const data = await response.json(); + if (data.registered) { + token2 = data.token; + } + return data.registered; + } + + async function handleLogin2() { + const nickname2 = nicknameInput2.value.trim(); + const password2 = loginPasswordInput2.value.trim(); + try { + const result = await authenticateUser2(nickname2, password2); + if (result) { + loginForm2.style.display = 'none'; + startLocalGame2(); + } else { + alert('Authentication failed. Please try again.'); + } + } catch (error) { + console.error('Error authenticating user:', error); + } + } + + async function authenticateUser2(username, password) { + const response = await fetch('/authenticate_user/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ username, password }) + }); + const data = await response.json(); + if (data.authenticated) { + token2 = data.token; + } + return data.authenticated; + } + + function startLocalGame() { + console.log("starting a Local Game.."); + document.getElementById("post-form-buttons").style.display = 'none'; + authForm2.style.display = 'block'; + nicknameInput2.focus(); + nicknameInput2.addEventListener('keypress', function (event) { + if (event.key === 'Enter') { + event.preventDefault(); + checkNicknameButton2.click(); + } + }); + } + + function startLocalGame2() { + gameContainer.style.display = 'flex'; + logo.style.display = 'none'; + pongElements.style.display = 'none'; + //menuButton.style.display = 'none'; + formBlock.style.display = 'none'; + startWebSocketConnection(token, 2); + } + + function startQuickMatch() { + gameContainer.style.display = 'flex'; + logo.style.display = 'none'; + pongElements.style.display = 'none'; + //menuButton.style.display = 'none'; + formBlock.style.display = 'none'; + startWebSocketConnection(token, 1); + } + + function startTournament() { + console.log("For now, do nothing, hurry up and work Senor chaku !!!!") + } + + function startWebSocketConnection(token, players) { socket = new WebSocket(`ws://${window.location.host}/ws/game/`); socket.onopen = function (event) { console.log('WebSocket connection established'); - socket.send(JSON.stringify({ type: 'authenticate', token: token })); + if (players === 1) { + console.log("Sending token for 1 player game"); + socket.send(JSON.stringify({ type: 'authenticate', token: token })); + } else { + console.log("Sending tokens for 2 player game"); + socket.send(JSON.stringify({ type: 'authenticate2', token_1: token, token_2: token2 })); + } }; socket.onmessage = function (event) { @@ -239,15 +408,15 @@ document.addEventListener('DOMContentLoaded', () => { } function handleKeyDown(event) { - if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { - console.log('Key press: ', event.key); + if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'w' || event.key === 's') { + //console.log('Key press: ', event.key); sendKeyPress(event.key.toLowerCase()); } } function sendKeyPress(key) { if (socket.readyState === WebSocket.OPEN) { - console.log('Key sent: ', key); + //console.log('Key sent: ', key); socket.send(JSON.stringify({ type: 'key_press', key })); } } @@ -275,25 +444,35 @@ document.addEventListener('DOMContentLoaded', () => { player2Score.textContent = gameState.player2_score; } + + ////////////////////////////// BEG BURGER BUTTON //////////////////////////////// + menuButton.addEventListener('click', toggleMenu); function toggleMenu() { console.log('Menu toggled'); if (dropdownMenu.style.display === "block") { dropdownMenu.style.display = "none"; + hideAllTables(); } else { dropdownMenu.style.display = "block"; } } + function hideAllTables(){ + if (playerList) playerList.style.display = 'none'; + if (matchList) matchList.style.display = 'none'; + if (tournoiList) tournoiList.style.display = 'none'; + if (blockchainList) blockchainList.style.display = 'none'; + } + const links = document.querySelectorAll('#dropdown-menu a'); - //console.log(links); links.forEach(link => { link.addEventListener('click', (event) => { event.preventDefault(); // Empêche le comportement par défaut du lien const tableId = link.getAttribute('data-table'); - console.log("Here !!!!!!!!!!!! NNNNNNNN"); + //console.log("Here !!!!!!!!!!!! NNNNNNNN"); showTable(tableId); }); }); @@ -301,28 +480,36 @@ document.addEventListener('DOMContentLoaded', () => { function showTable(tableId) { // Masquer tous les tableaux console.log('Entering showTable', tableId); - if (playerList) playerList.style.display = 'none'; - if (matchList) matchList.style.display = 'none'; - if (tournoiList) tournoiList.style.display = 'none'; + hideAllTables(); // Afficher le tableau sélectionné if (tableId === 'player-list') { - console.log('Showing player list'); + console.log('Showing player list 2'); //if (playerList) { playerList.style.display = 'block'; fetchPlayers(); //} } else if (tableId === 'match-list') { - console.log('Showing match list'); + console.log('Showing match list 2'); //if (matchList) matchList.style.display = 'block'; fetchMatches(); } else if (tableId === 'tournoi-list') { - console.log('Showing tournoi list'); + console.log('Showing tournoi list 2'); //if (tournoiList) tournoiList.style.display = 'block'; fetchTournois(); + } else if (tableId === 'blockchain-list') { + console.log('Opening external page in a new tab'); + window.open('https://sepolia.etherscan.io/address/0x078d04eb6fb97cd863361fc86000647dc876441b', '_blank'); + /* fetch('/web3/') + .then(response => response.json()) + .then(data => { + console.log('ok here !!'); + jsonContent.textContent = JSON.stringify(data, null, 2); + }); */ } + // Masquer le menu après la sélection if (dropdownMenu) { dropdownMenu.style.display = 'none'; @@ -403,7 +590,6 @@ document.addEventListener('DOMContentLoaded', () => { console.log('No players to display'); } - players.forEach(player => { const row = document.createElement('tr'); row.innerHTML = ` @@ -447,4 +633,166 @@ document.addEventListener('DOMContentLoaded', () => { }); } + ////////////////////////////// END BURGER BUTTON //////////////////////////////// + + + ////////////////////////////// BEG STARS //////////////////////////////// + + const starsContainer = document.getElementById('stars'); + for (let i = 0; i < 500; i++) { + const star = document.createElement('div'); + star.className = 'star'; + star.style.width = `${Math.random() * 3}px`; + star.style.height = star.style.width; + star.style.left = `${Math.random() * 100}%`; + star.style.top = `${Math.random() * 100}%`; + star.style.animationDuration = `${Math.random() * 2 + 1}s`; + starsContainer.appendChild(star); + } + + ////////////////////////////// END STARS //////////////////////////////// + + + /* btn.onclick = function() { + fetch('/web3/') + .then(response => response.json()) + .then(data => { + console.log('ok here !!'); + jsonContent.textContent = JSON.stringify(data, null, 2); + modal.style.display = "block"; + }); + } + + span.onclick = function() { + modal.style.display = "none"; + } + + window.onclick = function(event) { + if (event.target == modal) { + modal.style.display = "none"; + } + } */ + + ////////////////////////////// BEG LANGAGE //////////////////////////////// + const translations = { + fr: { + welcome: "BIENVENUE DANS LE PONG 42", + labelNickname: "Entrez votre surnom:", + labelPassword: "Entrez votre mot de passe:", + labelConfirmPassword: "Confirmez votre mot de passe:", + labelLoginPassword: "Entrez votre mot de passe:" + }, + en: { + welcome: "WELCOME TO PONG 42", + labelNickname: "Enter your nickname:", + labelPassword: "Enter your password:", + labelConfirmPassword: "Confirm your password:", + labelLoginPassword: "Enter your password:" + }, + it: { + welcome: "BENVENUTO A PONG 42", + labelNickname: "Inserisci il tuo soprannome:", + labelPassword: "Inserisci la tua password:", + labelConfirmPassword: "Conferma la tua password:", + labelLoginPassword: "Inserisci la tua password:" + }, + es: { + welcome: "BIENVENIDO A PONG 42", + labelNickname: "Introduce tu apodo:", + labelPassword: "Introduce tu contraseña:", + labelConfirmPassword: "Confirma tu contraseña:", + labelLoginPassword: "Introduce tu contraseña:" + }, + de: { + welcome: "WILLKOMMEN BEI PONG 42", + labelNickname: "Geben Sie Ihren Spitznamen ein:", + labelPassword: "Geben Sie Ihr Passwort ein:", + labelConfirmPassword: "Bestätigen Sie Ihr Passwort:", + labelLoginPassword: "Geben Sie Ihr Passwort ein:" + } + }; + + function setCookie(name, value, days) { + const d = new Date(); + d.setTime(d.getTime() + (days*24*60*60*1000)); + const expires = "expires=" + d.toUTCString(); + document.cookie = name + "=" + value + ";" + expires + ";path=/"; + } + + function getCookie(name) { + const cname = name + "="; + const decodedCookie = decodeURIComponent(document.cookie); + const ca = decodedCookie.split(';'); + for(let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) === ' ') { + c = c.substring(1); + } + if (c.indexOf(cname) === 0) { + return c.substring(cname.length, c.length); + } + } + return ""; + } + + function changeLanguage(lang) { + setCookie('preferredLanguage', lang, 365); // Store the language preference for 1 year + document.getElementById('welcome').innerText = translations[lang].welcome; + document.getElementById('label-nickname').innerText = translations[lang].labelNickname; + document.getElementById('label-password').innerText = translations[lang].labelPassword; + document.getElementById('label-confirm-password').innerText = translations[lang].labelConfirmPassword; + document.getElementById('label-login-password').innerText = translations[lang].labelLoginPassword; + } + + // Function to set the language based on the cookie + function setLanguageFromCookie() { + const preferredLanguage = getCookie('preferredLanguage'); + if (preferredLanguage && translations[preferredLanguage]) { + changeLanguage(preferredLanguage); + } else { + changeLanguage('fr'); // Default to French if no cookie is found + } + } + + document.getElementById('lang-fr').addEventListener('click', () => changeLanguage('fr')); + document.getElementById('lang-en').addEventListener('click', () => changeLanguage('en')); + document.getElementById('lang-it').addEventListener('click', () => changeLanguage('it')); + document.getElementById('lang-es').addEventListener('click', () => changeLanguage('es')); + document.getElementById('lang-de').addEventListener('click', () => changeLanguage('de')); + + // Set the language when the page loads + window.onload = setLanguageFromCookie; + + ////////////////////////////// END LANGAGE //////////////////////////////// + + + + ////////////////////////////// BEG SETTING //////////////////////////////// + + document.getElementById('settings-btn').addEventListener('click', function() { + document.getElementById('settings-menu').style.display = 'block'; + }); + + document.getElementById('close-settings').addEventListener('click', function() { + document.getElementById('settings-menu').style.display = 'none'; + }); + + // Change the color of the text + document.getElementById('color-picker').addEventListener('input', function() { + document.body.style.color = this.value; + document.querySelectorAll('button').forEach(function(button) { + button.style.backgroundColor = this.value; // Change la couleur de fond des boutons + }, this); + }); + + document.getElementById('font-selector').addEventListener('change', function() { + document.body.style.fontFamily = this.value; + }); + + document.getElementById('font-size-slider').addEventListener('input', function() { + document.body.style.fontSize = this.value + 'px'; + }); + + ////////////////////////////// END SETTING //////////////////////////////// + }); diff --git a/pong/static/index.html b/pong/static/index.html index 48d0691..189fca0 100644 --- a/pong/static/index.html +++ b/pong/static/index.html @@ -6,7 +6,7 @@