Should be ok

This commit is contained in:
Theouche 2024-09-15 16:51:56 +02:00
commit a96e2b2d99
11 changed files with 541 additions and 177 deletions

View File

@ -13,6 +13,6 @@ COPY certs/ certs/
RUN python3 -m venv venv RUN python3 -m venv venv
RUN venv/bin/pip3 install --upgrade pip RUN venv/bin/pip3 install --upgrade pip
RUN venv/bin/pip3 install --no-cache-dir -r requirements.txt RUN venv/bin/pip3 install --no-cache-dir -r requirements.txt -v
EXPOSE 8080 EXPOSE 8080

240
docker-compose.yml.old Normal file
View File

@ -0,0 +1,240 @@
services:
setup:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
container_name: setup
user: "0"
volumes:
- certs:/usr/share/elasticsearch/config/certs
command: >
bash -c '
if [ x${ELASTIC_PASSWORD} == x ]; then
echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
exit 1;
elif [ x${KIBANA_PASSWORD} == x ]; then
echo "Set the KIBANA_PASSWORD environment variable in the .env file";
exit 1;
fi;
if [ ! -f config/certs/ca.zip ]; then
echo "Creating CA";
bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
unzip config/certs/ca.zip -d config/certs;
fi;
if [ ! -f config/certs/certs.zip ]; then
echo "Creating certs";
echo -ne \
"instances:\n"\
" - name: es01\n"\
" dns:\n"\
" - es01\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
" - name: kibana\n"\
" dns:\n"\
" - kibana\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
> config/certs/instances.yml;
bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
unzip config/certs/certs.zip -d config/certs;
fi;
echo "Setting file permissions"
chown -R root:root config/certs;
find . -type d -exec chmod 750 \{\} \;;
find . -type f -exec chmod 640 \{\} \;;
echo "Waiting for Elasticsearch availability";
until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
echo "Setting kibana_system password";
until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
echo "All done!";
'
healthcheck:
test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
interval: 1s
timeout: 5s
retries: 120
backend:
build:
context: .
dockerfile: Dockerfile
image: backend
container_name: backend
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 collectstatic --noinput &&
venv/bin/daphne -e ssl:8080:privateKey=./certs/ssl/backend-key.pem:certKey=./certs/ssl/backend-cert.pem pong.asgi:application"
volumes:
- pong:/transcendence/pong
- pong_django_logs:/transcendence/logs
ports:
- 8080:8080
networks:
- app-network
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: ${POSTGRES_DB}
DB_USER: ${POSTGRES_USER}
DB_PASSWORD: ${POSTGRES_PASSWORD}
SECURE_SSL_REDIRECT: True
SECURE_HSTS_SECONDS: 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS: True
SECURE_HSTS_PRELOAD: True
depends_on:
- db
healthcheck:
test: ["CMD-SHELL", "curl", "http://localhost:8080"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
db:
image: postgres:latest
container_name: postgres
restart: always
volumes:
- pong_pg_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- app-network
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
container_name: es01
depends_on:
setup:
condition: service_healthy
volumes:
- certs:/usr/share/elasticsearch/config/certs:ro
- pong_es_data_01:/usr/share/elasticsearch/data
labels:
co.elastic.logs/module: elasticsearch
ports:
- 9200:9200
environment:
- node.name=es01
- cluster.name=${CLUSTER_NAME}
- discovery.type=single-node
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es01/es01.key
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es01/es01.key
- xpack.security.transport.ssl.certificate=certs/es01/es01.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
kibana:
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
container_name: kibana
labels:
co.elastic.logs/module: kibana
depends_on:
es01:
condition: service_healthy
volumes:
- certs:/usr/share/kibana/config/certs:ro
- pong_kibana:/usr/share/kibana/data
ports:
- 5601:5601
environment:
- SERVERNAME=kibana
- ELASTICSEARCH_HOSTS=https://es01:9200
- ELASTICSEARCH_USERNAME=${KIBANA_USERNAME}
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
- XPACK_SECURITY_ENCRYPTIONKEY=${ENCRYPTION_KEY}
- XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${ENCRYPTION_KEY}
- XPACK_REPORTING_ENCRYPTIONKEY=${ENCRYPTION_KEY}
healthcheck:
test:
[
"CMD-SHELL",
"curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'"
]
interval: 10s
timeout: 10s
retries: 120
logstash01:
image: docker.elastic.co/logstash/logstash:${STACK_VERSION}
container_name: logstash01
labels:
co.elastic.logs/module: logstash
user: root
depends_on:
es01:
condition: service_healthy
kibana:
condition: service_healthy
volumes:
- 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
environment:
- NODE_NAME="logstash"
- ELASTIC_HOSTS=https://es01:9200
- ELASTIC_USER=${ELASTIC_USERNAME}
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- xpack.monitoring.enabled=false
volumes:
pong:
driver: local
driver_opts:
type: none
device: ${PROJECT_PATH}
o: bind
pong_django_logs:
driver: local
pong_pg_data:
driver: local
pong_es_data_01:
driver: local
pong_kibana:
driver: local
pong_logstash_data01:
driver: local
certs:
driver: local
networks:
app-network:
name: app-network
driver: bridge

View File

@ -4,14 +4,11 @@ import json
import asyncio import asyncio
import random import random
from datetime import datetime from datetime import datetime
from .utils import handle_game_data, getlen, create_player, create_match from .utils import handle_game_data, getlen
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
from .models import Tournoi from .models import Tournoi
from concurrent.futures import ThreadPoolExecutor
class Game: class Game:
# Global variable to handle the using of the database
USING_DB = False
def __init__(self, game_id, player1, player2, localgame): def __init__(self, game_id, player1, player2, localgame):
self.game_id = game_id self.game_id = game_id
@ -47,6 +44,7 @@ class Game:
} }
self.speed = 1 self.speed = 1
self.game_loop_task = None self.game_loop_task = None
self.database = None
self.ended = False self.ended = False
self.p1_mov = 0 self.p1_mov = 0
self.p2_mov = 0 self.p2_mov = 0
@ -57,18 +55,13 @@ class Game:
async def start_game(self): async def start_game(self):
print(f"- Game #{self.game_id} STARTED ({self.game_state['player1_name']} vs {self.game_state['player2_name']}) --- ({self})") print(f"- Game #{self.game_id} STARTED ({self.game_state['player1_name']} vs {self.game_state['player2_name']}) --- ({self})")
await sync_to_async(create_player)(self.game_state['player1_name'], self.game_state['player2_name'])
self.game_loop_task = asyncio.create_task(self.game_loop()) self.game_loop_task = asyncio.create_task(self.game_loop())
print(f" Begin MATCH at: {self.start_time}") print(f" Begin MATCH at: {self.start_time}")
async def game_loop(self): async def game_loop(self):
print(" In the game loop..") print(" In the game loop..")
x = 59 x = 59
while not self.ended: while not self.ended:
print(f" ended : {self.ended}")
if self.botgame: if self.botgame:
x += 1 x += 1
if x == 60: if x == 60:
@ -82,33 +75,6 @@ class Game:
await self.update_game_state() await self.update_game_state()
await self.send_game_state() await self.send_game_state()
await asyncio.sleep(1/60) # Around 60 FPS await asyncio.sleep(1/60) # Around 60 FPS
if self.ended:
print(f" IN WHILE EXIT ???????? ended : {self.ended}")
print("IN WHILE here !!!!!")
try:
await self.save_match()
print("IN WHILE end here !!!!")
except Exception as e:
print(f"Erreur lors de l'appel de save_match: {e}")
print(f" OUT WHILE EXIT ???????? ended : {self.ended}")
if self.ended :
print(" OUT WHILE here !!!!!")
try:
#await self.save_match()
print("OUT WHILE end here !!!!")
except Exception as e:
print(f"Erreur lors de l'appel de save_match: {e}")
async def save_match(self) :
avd, d = (True, self.tournament.tournoi_reg) if hasattr(self, 'tournament') else (False, None)
end_time = datetime.now()
duration = (end_time - self.start_time).total_seconds() / 60
print("CALL IN SYNC")
await sync_to_async(create_match, thread_sensitive=True)(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, avd, d
)
async def update_bot_position(self): async def update_bot_position(self):
#future_ball_position = self.predict_ball_trajectory() #future_ball_position = self.predict_ball_trajectory()
@ -172,16 +138,14 @@ class Game:
if self.game_state['player2_score'] > 2: if self.game_state['player2_score'] > 2:
self.game_state['game_text'] = f"{self.game_state['player2_name']} WINS!" self.game_state['game_text'] = f"{self.game_state['player2_name']} WINS!"
await self.send_game_state() await self.send_game_state()
await self.end_game(self) await self.end_game()
#printf("player2 wins")
self.reset_ball() self.reset_ball()
elif self.game_state['ball_position']['x'] >= 790: elif self.game_state['ball_position']['x'] >= 790:
self.game_state['player1_score'] += 1 self.game_state['player1_score'] += 1
if self.game_state['player1_score'] > 2: if self.game_state['player1_score'] > 2:
self.game_state['game_text'] = f"{self.game_state['player1_name']} WINS!" self.game_state['game_text'] = f"{self.game_state['player1_name']} WINS!"
await self.send_game_state() await self.send_game_state()
await self.end_game(self) await self.end_game()
#printf("player1 wins")
self.reset_ball() self.reset_ball()
def reset_ball(self): def reset_ball(self):
@ -251,17 +215,18 @@ class Game:
elif self.p2_mov == 1: elif self.p2_mov == 1:
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'] + (5 * self.speed), 300)
async def end_game(self, disconnected_player=None): async def end_game(self, disconnected_player=None):
if not self.ended: if not self.ended:
self.ended = True self.ended = True
#if self.game_loop_task:
# self.game_loop_task.cancel()
print(f"- Game #{self.game_id} ENDED --- ({self})") print(f"- Game #{self.game_id} ENDED --- ({self})")
#await sync_to_async(save_match)() end_time = datetime.now()
duration = (end_time - self.start_time).total_seconds() / 60
# Notify that one player left the game # Notify that one player left the game
""" if disconnected_player: if disconnected_player:
printf("Disconnected player")
remaining_player = self.player2 if disconnected_player == self.player1 else self.player1 remaining_player = self.player2 if disconnected_player == self.player1 else self.player1
disconnected_name = disconnected_player.user.username disconnected_name = disconnected_player.user.username
message = json.dumps({ message = json.dumps({
@ -271,35 +236,25 @@ class Game:
if not self.botgame: if not self.botgame:
if not self.localgame: if not self.localgame:
await remaining_player.send(message) await remaining_player.send(message)
# Notify both players that the game has ended # Notify both players that the game has ended
end_message = json.dumps({ end_message = json.dumps({
'type': 'game_ended', 'type': 'game_ended',
'game_id': self.game_id 'game_id': self.game_id
}) })
await self.player1.send(end_message) await self.player1.send(end_message)
if not self.botgame: if not self.botgame:
if not self.localgame: if not self.localgame:
await self.player2.send(end_message) """ await self.player2.send(end_message)
avd, d = (True, self.tournament.tournoi_reg) if hasattr(self, 'tournament') else (False, None)
await sync_to_async(handle_game_data)(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, avd, d)
print(f"Try to save game #{self.game_id} ({self})")
#avd, d = (True, self.tournament.tournoi_reg) if hasattr(self, 'tournament') else (False, None)
# Essaye d'appeler handle_game_data
print("TRY CREATE MATCH")
#await sync_to_async(create_match)(
# 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, avd, d
#)
print("MATCH OK")
#if self.game_loop_task:
# self.game_loop_task.cancel()

View File

@ -0,0 +1,69 @@
# Generated by Django 5.1.1 on 2024-09-15 14:26
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('game', '0005_remove_player_num_won_tournaments'),
]
operations = [
migrations.AddField(
model_name='player',
name='best_score',
field=models.PositiveSmallIntegerField(default=0),
),
migrations.AddField(
model_name='player',
name='m_duration',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AddField(
model_name='player',
name='m_nbr_ball_touch',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AddField(
model_name='player',
name='m_score_adv_match',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AddField(
model_name='player',
name='m_score_match',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True),
),
migrations.AddField(
model_name='player',
name='num_won_tournaments',
field=models.PositiveSmallIntegerField(default=0),
),
migrations.AddField(
model_name='player',
name='total_duration',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
),
migrations.AlterField(
model_name='match',
name='player1',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player1', to='game.player'),
),
migrations.AlterField(
model_name='match',
name='player2',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player2', to='game.player'),
),
migrations.AlterField(
model_name='match',
name='winner',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='won_matches', to='game.player'),
),
migrations.AlterField(
model_name='tournoi',
name='winner',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='game.player'),
),
]

View File

@ -10,7 +10,14 @@ class Player(models.Model):
total_match = models.PositiveSmallIntegerField(default=0) total_match = models.PositiveSmallIntegerField(default=0)
total_win = models.PositiveSmallIntegerField(default=0) total_win = models.PositiveSmallIntegerField(default=0)
p_win = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) p_win = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
m_score_match = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
m_score_adv_match = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
best_score = models.PositiveSmallIntegerField(default=0)
m_nbr_ball_touch = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
total_duration = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
m_duration = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
num_participated_tournaments = models.PositiveSmallIntegerField(default=0) num_participated_tournaments = models.PositiveSmallIntegerField(default=0)
num_won_tournaments = models.PositiveSmallIntegerField(default=0)
def __str__(self): def __str__(self):
return self.name return self.name
@ -19,17 +26,17 @@ class Tournoi(models.Model):
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
nbr_player = models.PositiveSmallIntegerField() nbr_player = models.PositiveSmallIntegerField()
date = models.DateField(auto_now_add=True) date = models.DateField(auto_now_add=True)
winner = models.CharField(max_length=200, null=True, blank=True) winner = models.ForeignKey('Player', on_delete=models.SET_NULL, null=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Match(models.Model): class Match(models.Model):
player1 = models.CharField(max_length=100) player1 = models.ForeignKey('Player', related_name='match_as_player1', on_delete=models.CASCADE)
player2 = models.CharField(max_length=100) player2 = models.ForeignKey('Player', related_name='match_as_player2', on_delete=models.CASCADE)
score_player1 = models.PositiveSmallIntegerField() score_player1 = models.PositiveSmallIntegerField()
score_player2 = models.PositiveSmallIntegerField() score_player2 = models.PositiveSmallIntegerField()
winner = models.CharField(max_length=100) winner = models.ForeignKey('Player', related_name='won_matches',on_delete=models.CASCADE, null=True)
nbr_ball_touch_p1 = models.PositiveIntegerField() nbr_ball_touch_p1 = models.PositiveIntegerField()
nbr_ball_touch_p2 = models.PositiveIntegerField() nbr_ball_touch_p2 = models.PositiveIntegerField()
duration = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) duration = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
@ -37,5 +44,18 @@ class Match(models.Model):
is_tournoi = models.BooleanField() is_tournoi = models.BooleanField()
tournoi = models.ForeignKey('Tournoi', related_name='matches', on_delete=models.SET_NULL, null=True) tournoi = models.ForeignKey('Tournoi', related_name='matches', on_delete=models.SET_NULL, null=True)
def clean(self):
if self.score_player1 < 0 or self.score_player2 < 0:
raise ValidationError('Les scores doivent être positifs.')
if self.score_player1 > self.score_player2 and self.winner != self.player1:
raise ValidationError('Le gagnant ne correspond pas aux scores.')
if self.score_player2 > self.score_player1 and self.winner != self.player2:
raise ValidationError('Le gagnant ne correspond pas aux scores.')
super().clean()
def save(self, *args, **kwargs):
self.clean()
super().save(*args, **kwargs)
def __str__(self): def __str__(self):
return f"{self.player1} vs {self.player2}" return f"{self.player1.name} vs {self.player2.name}"

View File

@ -1,75 +1,87 @@
# /pong/game/utils.py
from .models import Player, Tournoi, Match from .models import Player, Tournoi, Match
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.db.models import Max, Sum, F from django.db.models import Max, Sum, F
from datetime import timedelta
from asgiref.sync import sync_to_async from channels.db import database_sync_to_async
from django.db.models import Q
import asyncio
players_name_list = []
tournament_participations = {}
def handle_game_data(p1, p2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament): def handle_game_data(p1, p2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament):
try: try:
print("Here !!!!!!!!") player_1 = get_or_create_player(p1)
#get_or_create_player(p1, p2) player_2 = get_or_create_player(p2)
#print("FIRST PLAYER REGISTERD")
#await sync_to_async(get_or_create_player)(p2)
#print("SECOND PLAYER REGISTERD")
print("CHAKU & THEOUCHE are the BEST") print("CHAKU & THEOUCHE are the BEST")
create_match(p1, p2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament) create_match(player_1, player_2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament)
print("and ADRIANO is the PEST") print("and ADRIANO is the PEST")
#update_player_statistics(p1) update_player_statistics(p1)
print("END UPDATE FISRT PLAYER") print("UPDATE PLAYER 1")
#update_player_statistics(p2) update_player_statistics(p2)
print("END UPDATE SECOND PLAYER") print("UPDATE PLAYER 2")
except Exception as e: except Exception as e:
print(f"Error in endfortheouche: {e}") print(f"Error in endfortheouche: {e}")
def get_player_by_name(name):
exists = Player.objects.filter(name=name).exists()
return exists
def create_player(name_p1, name_p2):
print("Get or create player")
global players_name_list
# Utilise get_or_create pour chercher un joueur existant ou en créer un nouveau avec les valeurs par défaut def get_player(name):
print("Check player exist") return Player.objects.get(name=name)
if name_p1 in players_name_list:
print(f"Player 1 {name_p1} exists")
else :
print(f"Player 1 {name_p1} does not exists")
player1 = Player(
name = name_p1,
total_match = 0,
total_win = 0,
p_win = 0,
num_participated_tournaments = 0)
player1.save()
players_name_list.append(name_p1)
print(f"Player {name_p1} creation done")
if name_p2 in players_name_list:
print(f"Player 2 {name_p2} exists")
else :
print(f"Player 2 {name_p2} does not exists")
player2 = Player(
name = name_p2,
total_match = 0,
total_win = 0,
p_win = 0,
num_participated_tournaments = 0)
player2.save()
players_name_list.append(name_p2)
print(f"Player {name_p2} creation done")
#return player def get_or_create_player(name):
player_exists = get_player_by_name(name)
if not player_exists:
player = create_player(name)
return player
else:
player = get_player(name)
return player
def create_player(
name,
total_match=0,
total_win=0,
p_win= None,
m_score_match= None,
m_score_adv_match= None,
best_score=0,
m_nbr_ball_touch= None,
total_duration= None,
m_duration= None,
num_participated_tournaments=0,
num_won_tournaments=0
):
player = Player(
name=name,
total_match=total_match,
total_win=total_win,
p_win=p_win,
m_score_match=m_score_match,
m_score_adv_match=m_score_adv_match,
best_score=best_score,
m_nbr_ball_touch=m_nbr_ball_touch,
total_duration=total_duration,
m_duration=m_duration,
num_participated_tournaments=num_participated_tournaments,
num_won_tournaments=num_won_tournaments
)
player.save()
return player
def create_tournoi(name, nbr_player, date, winner):
tournoi = Tournoi(name=name, nbr_player=nbr_player, date=date, winner=winner)
tournoi.save()
return tournoi
def create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_p1, nbr_ball_touch_p2, duration, is_tournoi, tournoi): def create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_p1, nbr_ball_touch_p2, duration, is_tournoi, tournoi):
print("MATCH BEING REGISTERD")
match = Match( match = Match(
player1=player1, player1=player1,
player2=player2, player2=player2,
@ -89,39 +101,81 @@ def create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_
else: else:
match.winner = None match.winner = None
print("MATCH SAVE IN DB")
match.save() match.save()
print("MATCH DONE") return match
update_player_statistics(player1, match.winner, is_tournoi, tournoi)
print("STAT P1 DONE")
update_player_statistics(player2, match.winner, is_tournoi, tournoi)
print("STAT P2 DONE")
def update_player_statistics(player_name, winner, is_tournoi, tournoi): def update_player_statistics(player_name):
print(f"HERE for {player_name} §§§§§§§§§§§§")
print("UPDATED DATA")
global tournament_participations
print("GET PLAYER")
player = get_object_or_404(Player, name=player_name) player = get_object_or_404(Player, name=player_name)
print("PLAYER FIND") print(f"GET PLAYER {player.name} !!!!!!")
player.total_match += 1 matches_as_player1 = Match.objects.filter(player1=player)
if winner == player.name : #print(f"GET MATCH AS PLAYER 1 {matches_as_player1.player1.name} !!!!!!")
player.total_win += 1 matches_as_player2 = Match.objects.filter(player2=player)
#print(f"GET MATCH AS PLAYER 2 {matches_as_player2.player2.name} !!!!!!")
if player.total_match > 0: total_match = matches_as_player1.count() + matches_as_player2.count()
player.p_win = player.total_win / player.total_match
if is_tournoi: # avoid dividing by 0
if tournoi.name not in tournament_participations: if total_match == 0:
tournament_participations[tournoi] = [] player.total_match = total_match
player.total_win = 0
player.p_win = 0
player.m_score_match = 0
player.m_score_adv_match = 0
player.best_score = 0
player.m_nbr_ball_touch = 0
player.total_duration = 0
player.m_duration = 0
player.num_participated_tournaments = 0
player.num_won_tournaments = 0
player.save()
return
if player_name not in tournament_participations[tournoi]: won_matches = Match.objects.filter(winner=player)
tournament_participations[tournoi].append(player.name) part_tourn_as_p1 = Tournoi.objects.filter(matches__is_tournoi=True, matches__player1=player)
player.num_participated_tournaments += 1 part_tourn_as_p2 = Tournoi.objects.filter(matches__is_tournoi=True, matches__player2=player)
won_tourn = Tournoi.objects.filter(winner=player)
total_score = matches_as_player1.aggregate(Sum('score_player1'))['score_player1__sum'] or 0
total_score += matches_as_player2.aggregate(Sum('score_player2'))['score_player2__sum'] or 0
total_score_adv = matches_as_player1.aggregate(Sum('score_player2'))['score_player2__sum'] or 0
total_score_adv += matches_as_player2.aggregate(Sum('score_player1'))['score_player1__sum'] or 0
total_win = won_matches.count()
p_win = (total_win / total_match) * 100
m_score_match = total_score / total_match
m_score_adv_match = total_score_adv / total_match
nbr_ball_touch = matches_as_player1.aggregate(Sum('nbr_ball_touch_p1'))['nbr_ball_touch_p1__sum'] or 0
nbr_ball_touch += matches_as_player2.aggregate(Sum('nbr_ball_touch_p2'))['nbr_ball_touch_p2__sum'] or 0
m_nbr_ball_touch = nbr_ball_touch / total_match
total_duration = matches_as_player1.aggregate(Sum('duration'))['duration__sum'] or 0
total_duration += matches_as_player2.aggregate(Sum('duration'))['duration__sum'] or 0
m_duration = total_duration / total_match
total_tourn_p = part_tourn_as_p1.count() + part_tourn_as_p2.count()
total_win_tourn = won_tourn.count()
p_win_tourn = (total_win_tourn / total_tourn_p) * 100 if total_tourn_p else 0
best_score_as_player1 = matches_as_player1.aggregate(Max('score_player1'))['score_player1__max'] or 0
best_score_as_player2 = matches_as_player2.aggregate(Max('score_player2'))['score_player2__max'] or 0
best_score = max(best_score_as_player1, best_score_as_player2)
player.total_match = total_match
player.total_win = total_win
player.p_win = p_win
player.m_score_match = m_score_match
player.m_score_adv_match = m_score_adv_match
player.best_score = best_score
player.m_nbr_ball_touch = m_nbr_ball_touch
player.total_duration = total_duration
player.m_duration = m_duration
player.num_participated_tournaments = total_tourn_p
player.num_won_tournaments = total_win_tourn
player.save() player.save()
@ -131,21 +185,23 @@ def get_player_p_win(player_name):
def create_tournament(name, nbr_player): def create_tournament(name, nbr_player):
print("tournoi created!!!") print("tournoi created!!!")
tournoi=Tournoi(name=name, nbr_player=nbr_player, winner="No one yet ...") tournoi=Tournoi(name=name, nbr_player=nbr_player, winner=None)
tournoi.save() tournoi.save()
print(f"tournoi name : {tournoi.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*") print(f"tournoi name : {tournoi.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*")
return tournoi return tournoi
def update_tournament(name_tournoi, winner_name): def update_tournament(name_tournoi, winner_name):
tournoi = get_object_or_404(Tournoi, name=name_tournoi) tournoi = get_object_or_404(Tournoi, name=name_tournoi)
winner_p = get_object_or_404(Player, name=winner_name)
print(f"in update tourna - tournoi name : {tournoi.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*") print(f"in update tourna - tournoi name : {tournoi.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*")
print(f"in update tourna - winner is : {winner_p.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*")
tournoi.winner = winner_p
tournoi.winner = winner_name print(f"in update tourna - TOURNOI winner is : {tournoi.winner.name} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*")
print(f"in update tourna - TOURNOI winner is : {tournoi.winner} *******!*!*!*!**!*!**!*!*!*!*!*!*!*!*!*")
tournoi.save() tournoi.save()
def getlen(): def getlen():
return Tournoi.objects.count() return Tournoi.objects.count()

View File

@ -3,6 +3,7 @@
from django.shortcuts import render from django.shortcuts import render
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from .models import Player, Tournoi, Match from .models import Player, Tournoi, Match
from .utils import create_player, create_tournoi, create_match
from django.http import JsonResponse from django.http import JsonResponse
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
@ -70,8 +71,8 @@ def match_list_json(request):
matches = Match.objects.all() matches = Match.objects.all()
data = { data = {
'matches': list(matches.values( 'matches': list(matches.values(
'id', 'player1', 'player2', 'score_player1', 'score_player2', 'id', 'player1__name', 'player2__name', 'score_player1', 'score_player2',
'winner', 'nbr_ball_touch_p1', 'nbr_ball_touch_p2', 'duration', 'date', 'winner__name', 'nbr_ball_touch_p1', 'nbr_ball_touch_p2', 'duration', 'date',
'is_tournoi', 'tournoi__name' 'is_tournoi', 'tournoi__name'
)) ))
} }
@ -83,7 +84,9 @@ def player_list_json(request):
data = { data = {
'players': list(players.values( 'players': list(players.values(
'id', 'name', 'total_match', 'total_win', 'p_win', 'id', 'name', 'total_match', 'total_win', 'p_win',
'num_participated_tournaments' 'm_score_match', 'm_score_adv_match', 'best_score',
'm_nbr_ball_touch', 'total_duration', 'm_duration',
'num_participated_tournaments', 'num_won_tournaments'
)) ))
} }
return JsonResponse(data) return JsonResponse(data)
@ -94,11 +97,14 @@ def get_tournoi_data(tournoi):
"name": tournoi.name, "name": tournoi.name,
"nbr_player": tournoi.nbr_player, "nbr_player": tournoi.nbr_player,
"date": tournoi.date, "date": tournoi.date,
"winner": tournoi.winner "winner": {
"id": tournoi.winner.id,
"name": tournoi.winner.name
} if tournoi.winner else None
} }
def tournoi_list_json(request): def tournoi_list_json(request):
tournois = Tournoi.objects.all() # Charge les données du gagnant tournois = Tournoi.objects.select_related('winner').all() # Charge les données du gagnant
tournois_data = [get_tournoi_data(tournoi) for tournoi in tournois] tournois_data = [get_tournoi_data(tournoi) for tournoi in tournois]
return JsonResponse({"tournois": tournois_data}) return JsonResponse({"tournois": tournois_data})
@ -167,4 +173,3 @@ def write_data(request):
# tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash) # tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
# print("Transaction receipt:", tx_receipt) # print("Transaction receipt:", tx_receipt)
print("-----------------------------") print("-----------------------------")

View File

@ -29,14 +29,15 @@ ALLOWED_HOSTS = ['*']
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'django.contrib.admin', #'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', #'django.contrib.sessions',
'django.contrib.messages', #'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'channels', 'channels',
'pong.game', 'pong.game',
#'django_db_conn_pool',
'rest_framework' 'rest_framework'
] ]
@ -46,7 +47,7 @@ MIDDLEWARE = [
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', #'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ]
@ -81,6 +82,7 @@ DATABASES = {
'PASSWORD': os.getenv('DB_PASSWORD'), 'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'), 'HOST': os.getenv('DB_HOST'),
'PORT': '5432', 'PORT': '5432',
'CONN_MAX_AGE': None,
} }
} }

View File

@ -104,16 +104,17 @@ document.addEventListener('DOMContentLoaded', () => {
const matchListBody = document.querySelector('#match-list tbody'); const matchListBody = document.querySelector('#match-list tbody');
matchListBody.innerHTML = ''; matchListBody.innerHTML = '';
if (matches.length != 0) { if (matches.length != 0) {
matches.forEach(match => { matches.forEach(match => {
const row = document.createElement('tr'); const row = document.createElement('tr');
row.innerHTML = ` row.innerHTML = `
<td>${match.id}</td> <td>${match.id}</td>
<td>${match.player1}</td> <td>${match.player1__name}</td>
<td>${match.player2}</td> <td>${match.player2__name}</td>
<td>${match.score_player1}</td> <td>${match.score_player1}</td>
<td>${match.score_player2}</td> <td>${match.score_player2}</td>
<td>${match.winner}</td> <td>${match.winner__name}</td>
<td>${match.nbr_ball_touch_p1}</td> <td>${match.nbr_ball_touch_p1}</td>
<td>${match.nbr_ball_touch_p2}</td> <td>${match.nbr_ball_touch_p2}</td>
<td>${match.duration}</td> <td>${match.duration}</td>
@ -137,16 +138,24 @@ document.addEventListener('DOMContentLoaded', () => {
const playersListBody = document.querySelector('#player-list tbody'); const playersListBody = document.querySelector('#player-list tbody');
playersListBody.innerHTML = ''; playersListBody.innerHTML = '';
if (players.length != 0) { if (players.length != 0) {
players.forEach(player => { players.forEach(player => {
const row = document.createElement('tr'); const row = document.createElement('tr');
row.innerHTML = ` row.innerHTML = `
<td>${player.id}</td> <td>${player.id}</td>
<td>${player.name}</td> <td>${player.name}</td>
<td>${player.total_match}</td> <td>${player.total_match}</td>
<td>${player.total_win}</td> <td>${player.total_win}</td>
<td>${player.p_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_participated_tournaments}</td>
<td>${player.num_won_tournaments}</td>
`; `;
playersListBody.appendChild(row); playersListBody.appendChild(row);
}); });
@ -166,13 +175,15 @@ document.addEventListener('DOMContentLoaded', () => {
if (tournois.length != 0) { if (tournois.length != 0) {
tournois.forEach(tournoi => { tournois.forEach(tournoi => {
const row = document.createElement('tr'); console.log('Winner:', tournoi.winner); //debug !!!!!!!!!!!!!!!!!
console.log('Winner:', tournoi.winner__name); //debug !!!!!!!!!!!!!!!!!
const row = document.createElement('tr');
row.innerHTML = ` row.innerHTML = `
<td>${tournoi.id}</td> <td>${tournoi.id}</td>
<td>${tournoi.name}</td> <td>${tournoi.name}</td>
<td>${tournoi.nbr_player}</td> <td>${tournoi.nbr_player}</td>
<td>${tournoi.date}</td> <td>${tournoi.date}</td>
<td>${tournoi.winner}</td> <td>${tournoi.winner ? tournoi.winner.name : 'No one yet ...'}</td>
`; `;
tournoisListBody.appendChild(row); tournoisListBody.appendChild(row);
}); });

View File

@ -161,6 +161,12 @@
<th>Total Matches</th> <th>Total Matches</th>
<th>Total Wins</th> <th>Total Wins</th>
<th>Win Percentage</th> <th>Win Percentage</th>
<th>Average Match Score</th>
<th>Average Opponent Score</th>
<th>Best Score</th>
<th>Average Ball Touches</th>
<th>Total Duration</th>
<th>Average Duration</th>
<th>Participated Tournaments</th> <th>Participated Tournaments</th>
<th>Won Tournaments</th> <th>Won Tournaments</th>
</tr> </tr>