mirror of
https://github.com/AudebertAdrien/ft_transcendence.git
synced 2026-02-04 11:40:25 +01:00
Merge branch 'chaku' of github.com:AudebertAdrien/ft_transcendence into trash2
This commit is contained in:
commit
86074d359c
1
.env
1
.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
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ __pycache__/
|
||||
data/
|
||||
.env
|
||||
makefile
|
||||
logs/django.log
|
||||
|
||||
@ -1,21 +1,28 @@
|
||||
input {
|
||||
udp {
|
||||
host => "0.0.0.0"
|
||||
port => 5044
|
||||
file {
|
||||
path => "/usr/share/logstash/logs/django.log"
|
||||
start_position => "beginning"
|
||||
sincedb_path => "/dev/null"
|
||||
codec => "json"
|
||||
}
|
||||
}
|
||||
|
||||
filter {}
|
||||
filter {
|
||||
json {
|
||||
source => "message"
|
||||
target => "json_message"
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
elasticsearch {
|
||||
index => "logstash-%{+YYYY.MM.dd}"
|
||||
hosts => ["https://es01:9200"]
|
||||
user => "elastic"
|
||||
password => elastic_pass
|
||||
ssl_enabled => true
|
||||
password => "${ELASTIC_PASSWORD}"
|
||||
ssl_enabled => true
|
||||
ssl_certificate_authorities => "/usr/share/logstash/certs/ca/ca.crt"
|
||||
ssl_verification_mode => "full"
|
||||
index => "django-logs-%{+YYYY.MM.dd}"
|
||||
}
|
||||
stdout { codec => rubydebug }
|
||||
}
|
||||
#stdout {}
|
||||
}
|
||||
|
||||
@ -58,8 +58,6 @@ services:
|
||||
timeout: 5s
|
||||
retries: 120
|
||||
|
||||
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
@ -74,6 +72,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 +199,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 +217,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:
|
||||
|
||||
8
makefile
8
makefile
@ -4,7 +4,7 @@ CONTAINER=$(c)
|
||||
|
||||
up: down
|
||||
$(COMPOSE) build
|
||||
$(COMPOSE) up $(CONTAINER) || true
|
||||
$(COMPOSE) up -d $(CONTAINER) || true
|
||||
|
||||
build:
|
||||
$(COMPOSE) build $(CONTAINER)
|
||||
@ -20,8 +20,8 @@ down:
|
||||
|
||||
destroy:
|
||||
$(COMPOSE) down -v --rmi all
|
||||
#sudo lsof -i :5432 | awk 'NR>1 {print $$2}' | xargs sudo kill -9 || true
|
||||
#sudo lsof -i :80 | awk 'NR>1 {print $$2}' | xargs sudo kill -9 || true
|
||||
sudo lsof -i :5432 | awk 'NR>1 {print $$2}' | xargs sudo kill -9 || true
|
||||
sudo lsof -i :80 | awk 'NR>1 {print $$2}' | xargs sudo kill -9 || true
|
||||
|
||||
logs:
|
||||
$(COMPOSE) logs -f $(CONTAINER)
|
||||
@ -32,7 +32,7 @@ ps:
|
||||
db-shell:
|
||||
$(COMPOSE) exec db psql -U 42student players_db
|
||||
|
||||
re: destroy down up
|
||||
re: destroy up
|
||||
|
||||
help:
|
||||
@echo "Usage:"
|
||||
|
||||
@ -5,6 +5,7 @@ from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
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
|
||||
|
||||
class GameConsumer(AsyncWebsocketConsumer):
|
||||
async def connect(self):
|
||||
@ -18,6 +19,8 @@ class GameConsumer(AsyncWebsocketConsumer):
|
||||
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'])
|
||||
@ -74,10 +77,25 @@ class GameConsumer(AsyncWebsocketConsumer):
|
||||
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} authenticated")
|
||||
await self.join_tournament_waiting_room()
|
||||
else:
|
||||
await self.send(text_data=json.dumps({'type': 'error', 'message': 'Authentication failed'}))
|
||||
print("Authentication failed")
|
||||
|
||||
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 set_game(self, game):
|
||||
|
||||
@ -24,7 +24,8 @@ class Game:
|
||||
'ball_position': {'x': 390, 'y': 190},
|
||||
'ball_velocity': {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])},
|
||||
'player1_score': 0,
|
||||
'player2_score': 0
|
||||
'player2_score': 0,
|
||||
'game_text': ''
|
||||
}
|
||||
else:
|
||||
self.botgame = player2 is None
|
||||
@ -36,7 +37,8 @@ class Game:
|
||||
'ball_position': {'x': 390, 'y': 190},
|
||||
'ball_velocity': {'x': random.choice([-5, 5]), 'y': random.choice([-5, 5])},
|
||||
'player1_score': 0,
|
||||
'player2_score': 0
|
||||
'player2_score': 0,
|
||||
'game-text': ''
|
||||
}
|
||||
self.speed = 1
|
||||
self.game_loop_task = None
|
||||
@ -55,9 +57,13 @@ class Game:
|
||||
|
||||
async def game_loop(self):
|
||||
print(" In the game loop..")
|
||||
x = 0
|
||||
while not self.ended:
|
||||
if self.botgame:
|
||||
await self.update_bot_position()
|
||||
x += 1
|
||||
if x == 60:
|
||||
await self.update_bot_position()
|
||||
x = 0
|
||||
await self.handle_pad_movement()
|
||||
await self.update_game_state()
|
||||
await self.send_game_state()
|
||||
@ -68,9 +74,9 @@ class Game:
|
||||
if self.game_state['player2_position'] < target_y < self.game_state['player2_position'] + 80:
|
||||
pass
|
||||
elif self.game_state['player2_position'] < target_y:
|
||||
self.game_state['player2_position'] = min(self.game_state['player2_position'] + (5 * self.speed), 300)
|
||||
self.game_state['player2_position'] = min(self.game_state['player2_position'] + (50 * self.speed), 300)
|
||||
elif self.game_state['player2_position'] + 80 > target_y:
|
||||
self.game_state['player2_position'] = max(self.game_state['player2_position'] - (5 * self.speed), 0)
|
||||
self.game_state['player2_position'] = max(self.game_state['player2_position'] - (50 * self.speed), 0)
|
||||
|
||||
async def update_game_state(self):
|
||||
if self.ended:
|
||||
@ -94,21 +100,18 @@ class Game:
|
||||
self.game_state['ball_velocity']['x'] *= -1
|
||||
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']} §§§§§§§§§§§")
|
||||
|
||||
# Check if some player won the game
|
||||
if self.game_state['ball_position']['x'] <= 10:
|
||||
self.game_state['player2_score'] += 1
|
||||
if self.game_state['player2_score'] > 2:
|
||||
print("Here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
self.game_state['game_text'] = f"{self.game_state['player2_name']} WINS!"
|
||||
await self.send_game_state()
|
||||
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:
|
||||
print("Here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
self.game_state['game_text'] = f"{self.game_state['player1_name']} WINS!"
|
||||
await self.send_game_state()
|
||||
await self.end_game()
|
||||
self.reset_ball()
|
||||
@ -201,7 +204,8 @@ class Game:
|
||||
'player': disconnected_name
|
||||
})
|
||||
if not self.botgame:
|
||||
await remaining_player.send(message)
|
||||
if not self.localgame:
|
||||
await remaining_player.send(message)
|
||||
# Notify both players that the game has ended
|
||||
end_message = json.dumps({
|
||||
'type': 'game_ended',
|
||||
|
||||
@ -40,7 +40,7 @@ class MatchMaker:
|
||||
await asyncio.sleep(1)
|
||||
self.timer += 1
|
||||
# Waiting for more than 30s -> BOT game
|
||||
if self.timer >= 30 and self.waiting_players:
|
||||
if self.timer >= 15 and self.waiting_players:
|
||||
player1 = self.waiting_players.pop(0)
|
||||
print(f"*** MATCH FOUND: {player1.user.username} vs BOT")
|
||||
self.botgame = True
|
||||
@ -110,6 +110,3 @@ class MatchMaker:
|
||||
|
||||
# Instance of the class
|
||||
match_maker = MatchMaker()
|
||||
|
||||
# to get what you want use get_player_p_win(player_name) !! (voir utils.py)
|
||||
#
|
||||
10
pong/game/templates/pong/tournament_waiting_room.html
Normal file
10
pong/game/templates/pong/tournament_waiting_room.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!-- templates/tournament_waiting_room.html -->
|
||||
<div class="tournament-waiting-room">
|
||||
<h2>Tournament Waiting Room</h2>
|
||||
<p>Players currently waiting: {{ players|length }}</p>
|
||||
<ul>
|
||||
{% for player in players %}
|
||||
<li>{{ player }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
36
pong/game/tournament.py
Normal file
36
pong/game/tournament.py
Normal file
@ -0,0 +1,36 @@
|
||||
# /pong/game/tournament.py
|
||||
|
||||
import json
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
class TournamentMatchMaker:
|
||||
def __init__(self):
|
||||
self.waiting_players = []
|
||||
|
||||
async def add_player(self, player):
|
||||
if player not in self.waiting_players:
|
||||
self.waiting_players.append(player)
|
||||
print(f"User {player.user.username} joins the TOURNAMENT WAITING ROOM")
|
||||
await self.update_waiting_room()
|
||||
|
||||
async def remove_player(self, player):
|
||||
if player in self.waiting_players:
|
||||
self.waiting_players.remove(player)
|
||||
await self.update_waiting_room()
|
||||
|
||||
async def update_waiting_room(self):
|
||||
html = self.generate_waiting_room_html()
|
||||
for player in self.waiting_players:
|
||||
await player.send(json.dumps({
|
||||
'type': 'update_waiting_room',
|
||||
'html': html
|
||||
}))
|
||||
|
||||
def generate_waiting_room_html(self):
|
||||
context = {
|
||||
'players': [player.user.username for player in self.waiting_players]
|
||||
}
|
||||
return render_to_string('pong/tournament_waiting_room.html', context)
|
||||
|
||||
# Instance of the class
|
||||
tournament_match_maker = TournamentMatchMaker()
|
||||
@ -22,6 +22,7 @@ from channels.db import database_sync_to_async
|
||||
await update_player_statistics(p1)
|
||||
print("############# END STAT P1")
|
||||
await update_player_statistics(p2)
|
||||
print("############# END STAT P2")
|
||||
except Exception as e:
|
||||
print(f"Error in endfortheouche: {e}")
|
||||
|
||||
|
||||
@ -6,8 +6,9 @@ Django settings for pong project.
|
||||
Generated by 'django-admin startproject' using Django 3.2.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
import logging.config
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
@ -136,18 +137,36 @@ CHANNEL_LAYERS = {
|
||||
}
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'handlers': {
|
||||
'version': 1, # The version of the logging configuration schema
|
||||
'disable_existing_loggers': False, # Allows existing loggers to keep logging
|
||||
'formatters': { # Defines how log messages will be formatted
|
||||
'json': {
|
||||
'()': 'pythonjsonlogger.jsonlogger.JsonFormatter',
|
||||
# Formatter that outputs logs in JSON format, which is ideal for ingestion by Logstash.
|
||||
},
|
||||
'default': {
|
||||
'format': '[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s',
|
||||
# This is a basic text formatter with timestamp, log level, logger name, line number, and the actual message.
|
||||
},
|
||||
},
|
||||
'handlers': { # Handlers determine where the log messages are sent
|
||||
'file': {
|
||||
'level': 'INFO', # Minimum log level to be handled (INFO and above)
|
||||
'class': 'logging.FileHandler',
|
||||
'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': {
|
||||
'level': 'DEBUG',
|
||||
'level': 'DEBUG', # Minimum log level to be handled (DEBUG and above)
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'default', # Uses the default text formatter
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'handlers': ['console'],
|
||||
'level': 'DEBUG',
|
||||
'loggers': { # Loggers are the actual log streams that get configured
|
||||
'django': { # The Django logger catches all messages sent by the Django framework
|
||||
'handlers': ['file', 'console'], # Sends logs to both the file and the console
|
||||
'level': 'DEBUG', # Minimum log level to be logged
|
||||
'propagate': True, # If True, messages will be passed to the parent loggers as well
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const loginButton2 = document.getElementById('login2');
|
||||
|
||||
const gameContainer = document.getElementById('game1');
|
||||
const tournamentContainer = document.getElementById('tournament-bracket');
|
||||
|
||||
const menuButton = document.querySelector('.burger-menu');
|
||||
const dropdownMenu = document.getElementById('dropdown-menu');
|
||||
@ -351,7 +352,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
function startTournament() {
|
||||
console.log("For now, do nothing, hurry up and work Senor chaku !!!!")
|
||||
tournamentContainer.style.display = 'flex';
|
||||
logo.style.display = 'none';
|
||||
pongElements.style.display = 'none';
|
||||
//menuButton.style.display = 'none';
|
||||
formBlock.style.display = 'none';
|
||||
startWebSocketConnection(token, 42);
|
||||
}
|
||||
|
||||
function startWebSocketConnection(token, players) {
|
||||
@ -360,11 +366,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
socket.onopen = function (event) {
|
||||
console.log('WebSocket connection established');
|
||||
if (players === 1) {
|
||||
console.log("Sending token for 1 player game");
|
||||
console.log("Sending token for a quick match game");
|
||||
socket.send(JSON.stringify({ type: 'authenticate', token: token }));
|
||||
} else {
|
||||
console.log("Sending tokens for 2 player game");
|
||||
} else if (players === 2) {
|
||||
console.log("Sending tokens for a local game");
|
||||
socket.send(JSON.stringify({ type: 'authenticate2', token_1: token, token_2: token2 }));
|
||||
} else {
|
||||
console.log("Sending token for a tournament game")
|
||||
socket.send(JSON.stringify({ type: 'authenticate3', token: token }));
|
||||
}
|
||||
};
|
||||
|
||||
@ -376,7 +385,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('Entered the WAITING ROOM');
|
||||
} else if (data.type === 'game_start') {
|
||||
console.log('Game started:', data.game_id, '(', data.player1, 'vs', data.player2, ')');
|
||||
startGame(data.game_id, data.player1, data.player2);
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
} else if (data.type === 'game_state_update') {
|
||||
updateGameState(data.game_state);
|
||||
} else if (data.type === 'player_disconnected') {
|
||||
@ -385,6 +394,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log("Game ended:", data.game_id);
|
||||
} else if (data.type === 'error') {
|
||||
console.error(data.message);
|
||||
} else if (data.type === 'update_waiting_room') {
|
||||
document.getElementById('tournament-bracket').innerHTML = data.html;
|
||||
} else {
|
||||
console.log('Message from server:', data.type, data.message);
|
||||
}
|
||||
@ -399,14 +410,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
};
|
||||
}
|
||||
|
||||
function startGame(gameCode, player1_name, player2_name) {
|
||||
document.getElementById('gameCode').textContent = `Game Code: ${gameCode}`;
|
||||
document.getElementById('player1-name').textContent = `${player1_name}`;
|
||||
document.getElementById('player2-name').textContent = `${player2_name}`;
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'w' || event.key === 's') {
|
||||
//console.log('Key press: ', event.key);
|
||||
@ -427,24 +430,21 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
function renderGame() {
|
||||
const player1Pad = document.getElementById('player1-pad');
|
||||
player1Pad.style.top = `${gameState.player1_position}px`;
|
||||
document.getElementById('player1-name').textContent = `${gameState.player1_name}`;
|
||||
document.getElementById('player2-name').textContent = `${gameState.player2_name}`;
|
||||
|
||||
const player2Pad = document.getElementById('player2-pad');
|
||||
player2Pad.style.top = `${gameState.player2_position}px`;
|
||||
document.getElementById('player1-pad').style.top = `${gameState.player1_position}px`;
|
||||
document.getElementById('player2-pad').style.top = `${gameState.player2_position}px`;
|
||||
|
||||
const ball = document.getElementById('ball');
|
||||
ball.style.left = `${gameState.ball_position.x}px`;
|
||||
ball.style.top = `${gameState.ball_position.y}px`;
|
||||
document.getElementById('ball').style.left = `${gameState.ball_position.x}px`;
|
||||
document.getElementById('ball').style.top = `${gameState.ball_position.y}px`;
|
||||
|
||||
const player1Score = document.getElementById('player1-score');
|
||||
player1Score.textContent = gameState.player1_score;
|
||||
document.getElementById('player1-score').textContent = gameState.player1_score;
|
||||
document.getElementById('player2-score').textContent = gameState.player2_score;
|
||||
|
||||
const player2Score = document.getElementById('player2-score');
|
||||
player2Score.textContent = gameState.player2_score;
|
||||
document.getElementById('game-text').textContent = gameState.game_text;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////// BEG BURGER BUTTON ////////////////////////////////
|
||||
|
||||
menuButton.addEventListener('click', toggleMenu);
|
||||
@ -557,28 +557,31 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const matchListBody = document.querySelector('#match-list tbody');
|
||||
matchListBody.innerHTML = '';
|
||||
|
||||
if (matches.length === 0) {
|
||||
console.log('No matches to display');
|
||||
}
|
||||
|
||||
matches.forEach(match => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${match.id}</td>
|
||||
<td>${match.player1__name}</td>
|
||||
<td>${match.player2__name}</td>
|
||||
<td>${match.score_player1}</td>
|
||||
<td>${match.score_player2}</td>
|
||||
<td>${match.winner__name}</td>
|
||||
<td>${match.nbr_ball_touch_p1}</td>
|
||||
<td>${match.nbr_ball_touch_p2}</td>
|
||||
<td>${match.duration}</td>
|
||||
<td>${match.date}</td>
|
||||
<td>${match.is_tournoi}</td>
|
||||
<td>${match.tournoi__name}</td>
|
||||
`;
|
||||
matchListBody.appendChild(row);
|
||||
});
|
||||
if (matches.length != 0) {
|
||||
matches.forEach(match => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${match.id}</td>
|
||||
<td>${match.player1__name}</td>
|
||||
<td>${match.player2__name}</td>
|
||||
<td>${match.score_player1}</td>
|
||||
<td>${match.score_player2}</td>
|
||||
<td>${match.winner__name}</td>
|
||||
<td>${match.nbr_ball_touch_p1}</td>
|
||||
<td>${match.nbr_ball_touch_p2}</td>
|
||||
<td>${match.duration}</td>
|
||||
<td>${match.date}</td>
|
||||
<td>${match.is_tournoi}</td>
|
||||
<td>${match.tournoi__name}</td>
|
||||
`;
|
||||
matchListBody.appendChild(row);
|
||||
});
|
||||
} else {
|
||||
row.innerHTML = `
|
||||
<td colspan="12">No matches found.</td>
|
||||
`;
|
||||
matchListBody.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
function displayPlayers(players) {
|
||||
@ -586,51 +589,58 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const playersListBody = document.querySelector('#player-list tbody');
|
||||
playersListBody.innerHTML = '';
|
||||
|
||||
if (players.length === 0) {
|
||||
console.log('No players to display');
|
||||
}
|
||||
if (players.length != 0) {
|
||||
players.forEach(player => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${player.id}</td>
|
||||
<td>${player.name}</td>
|
||||
<td>${player.total_match}</td>
|
||||
<td>${player.total_win}</td>
|
||||
<td>${player.p_win}</td>
|
||||
<td>${player.m_score_match}</td>
|
||||
<td>${player.m_score_adv_match}</td>
|
||||
<td>${player.best_score}</td>
|
||||
<td>${player.m_nbr_ball_touch}</td>
|
||||
<td>${player.total_duration}</td>
|
||||
<td>${player.m_duration}</td>
|
||||
<td>${player.num_participated_tournaments}</td>
|
||||
<td>${player.num_won_tournaments}</td>
|
||||
`;
|
||||
playersListBody.appendChild(row);
|
||||
});
|
||||
} else {
|
||||
row.innerHTML = `
|
||||
<td colspan="12">No matches found.</td>
|
||||
`
|
||||
playersListBody.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
players.forEach(player => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>${player.id}</td>
|
||||
<td>${player.name}</td>
|
||||
<td>${player.total_match}</td>
|
||||
<td>${player.total_win}</td>
|
||||
<td>${player.p_win}</td>
|
||||
<td>${player.m_score_match}</td>
|
||||
<td>${player.m_score_adv_match}</td>
|
||||
<td>${player.best_score}</td>
|
||||
<td>${player.m_nbr_ball_touch}</td>
|
||||
<td>${player.total_duration}</td>
|
||||
<td>${player.m_duration}</td>
|
||||
<td>${player.num_participated_tournaments}</td>
|
||||
<td>${player.num_won_tournaments}</td>
|
||||
`;
|
||||
playersListBody.appendChild(row);
|
||||
});
|
||||
}
|
||||
function displayTournois(tournois) {
|
||||
console.log('Displaying tournois:');
|
||||
const tournoisListBody = document.querySelector('#tournoi-list tbody');
|
||||
tournoisListBody.innerHTML = '';
|
||||
|
||||
function displayTournois(tournois) {
|
||||
console.log('Displaying tournois:');
|
||||
const tournoisListBody = document.querySelector('#tournoi-list tbody');
|
||||
tournoisListBody.innerHTML = '';
|
||||
|
||||
if (tournois.length === 0) {
|
||||
console.log('No tournois to display');
|
||||
}
|
||||
|
||||
tournois.forEach(tournoi => {
|
||||
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.name}</td>
|
||||
`;
|
||||
tournoisListBody.appendChild(row);
|
||||
});
|
||||
if (tournois.length != 0) {
|
||||
tournois.forEach(tournoi => {
|
||||
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.name}</td>
|
||||
`;
|
||||
tournoisListBody.appendChild(row);
|
||||
});
|
||||
} else {
|
||||
row.innerHTML = `
|
||||
<td colspan="12">No matches found.</td>
|
||||
`
|
||||
tournoisListBody.appendChild(row);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////// END BURGER BUTTON ////////////////////////////////
|
||||
|
||||
@ -111,8 +111,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tournament-bracket" style="display: none;"></div>
|
||||
|
||||
<div id="game1" style="display: none;">
|
||||
<div id="gameCode" class="game-code">Game Code : </div>
|
||||
<div id="player1-name" class="name">Player 1</div>
|
||||
<div id="player2-name" class="name">Player 2</div>
|
||||
<div id="game2">
|
||||
@ -121,6 +122,7 @@
|
||||
<div id="player1-pad" class="pad"></div>
|
||||
<div id="player2-pad" class="pad"></div>
|
||||
<div id="ball"></div>
|
||||
<div id="game-text" class="gameText"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -144,27 +146,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for match in matches %}
|
||||
<tr>
|
||||
<td>{{ match.id }}</td>
|
||||
<td>{{ match.player1.name }}</td>
|
||||
<td>{{ match.player2.name }}</td>
|
||||
<td>{{ match.score_player1 }}</td>
|
||||
<td>{{ match.score_player2 }}</td>
|
||||
<td>{{ match.winner.name }}</td>
|
||||
<td>{{ match.nbr_ball_touch_p1 }}</td>
|
||||
<td>{{ match.nbr_ball_touch_p2 }}</td>
|
||||
<td>{{ match.duration }}</td>
|
||||
<td>{{ match.date }}</td>
|
||||
<td>{{ match.is_tournoi }}</td>
|
||||
<td>{{ match.tournoi.name }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="12">No matches found.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -189,28 +171,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for player in players %}
|
||||
<tr>
|
||||
<td>{{ player.id }}</td>
|
||||
<td>{{ player.name }}</td>
|
||||
<td>{{ player.total_match }}</td>
|
||||
<td>{{ player.total_win }}</td>
|
||||
<td>{{ player.p_win }}</td>
|
||||
<td>{{ player.m_score_match }}</td>
|
||||
<td>{{ player.m_score_adv_match }}</td>
|
||||
<td>{{ player.best_score }}</td>
|
||||
<td>{{ player.m_nbr_ball_touch }}</td>
|
||||
<td>{{ player.total_duration }}</td>
|
||||
<td>{{ player.m_duration }}</td>
|
||||
<td>{{ player.num_participated_tournaments }}</td>
|
||||
<td>{{ player.num_won_tournaments }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="13">No players found.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -226,21 +187,8 @@
|
||||
<th>Winner</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tournoi in tournois %}
|
||||
<tr>
|
||||
<td>{{ tournoi.id }}</td>
|
||||
<td>{{ tournoi.name }}</td>
|
||||
<td>{{ tournoi.nbr_player }}</td>
|
||||
<td>{{ tournoi.date }}</td>
|
||||
<td>{{ tournoi.winner.name }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="14">No tournois found.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@ -59,20 +59,10 @@ button:hover {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.game-code {
|
||||
font-size: 24px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
#gameCode {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 24px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
#player1-name {
|
||||
@ -144,6 +134,13 @@ button:hover {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#game-text {
|
||||
font-size: 64px;
|
||||
color: #00ffff;
|
||||
position: absolute;
|
||||
top: 150px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
Django
|
||||
django
|
||||
psycopg2
|
||||
python-dotenv
|
||||
channels
|
||||
daphne
|
||||
djangorestframework
|
||||
web3
|
||||
python-json-logger==2.0.7
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user