reduce requete

This commit is contained in:
Theouche 2024-09-13 15:23:11 +02:00
commit 7689cf2da0
15 changed files with 357 additions and 363 deletions

View File

@ -1,63 +1,5 @@
services: 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: backend:
build: build:
context: . context: .
@ -112,103 +54,7 @@ services:
timeout: 5s timeout: 5s
retries: 5 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: volumes:
pong: pong:
@ -221,14 +67,7 @@ volumes:
driver: local driver: local
pong_pg_data: pong_pg_data:
driver: local driver: local
pong_es_data_01:
driver: local
pong_kibana:
driver: local
pong_logstash_data01:
driver: local
certs:
driver: local
networks: networks:
app-network: app-network:

236
docker-compose_save.yml Normal file
View File

@ -0,0 +1,236 @@
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 -b 0.0.0.0 -p 8080 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}
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

@ -2,7 +2,7 @@ COMPOSE_FILE=docker-compose.yml
COMPOSE=docker compose -f $(COMPOSE_FILE) COMPOSE=docker compose -f $(COMPOSE_FILE)
CONTAINER=$(c) CONTAINER=$(c)
up: down up:
$(COMPOSE) build $(COMPOSE) build
$(COMPOSE) up -d $(CONTAINER) || true $(COMPOSE) up -d $(CONTAINER) || true

View File

@ -9,6 +9,9 @@ from asgiref.sync import sync_to_async
from .models import Tournoi from .models import Tournoi
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
self.player1 = player1 self.player1 = player1
@ -137,6 +140,7 @@ class Game:
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() 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
@ -144,6 +148,7 @@ class Game:
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() await self.end_game()
#printf("player1 wins")
self.reset_ball() self.reset_ball()
def reset_ball(self): def reset_ball(self):
@ -225,6 +230,7 @@ class Game:
# 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({
@ -251,44 +257,45 @@ class Game:
success = False success = False
print(f"Try to save game #{self.game_id} ({self})") print(f"Try to save game #{self.game_id} ({self})")
while attempt < max_attempts and not success: #while attempt < max_attempts and not success:
try: try:
if hasattr(self, 'tournament'): if hasattr(self, 'tournament'):
print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} ENDED ***") print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} ENDED ***")
# Essaye d'appeler handle_game_data # Essaye d'appeler handle_game_data
result = await sync_to_async(handle_game_data)( result = await sync_to_async(handle_game_data)(
self.game_state['player1_name'], self.game_state['player2_name'], self.game_state['player1_name'], self.game_state['player2_name'],
self.game_state['player1_score'], self.game_state['player2_score'], self.game_state['player1_score'], self.game_state['player2_score'],
self.bt1, self.bt2, duration, True, self.tournament.tournoi_reg self.bt1, self.bt2, duration, True, self.tournament.tournoi_reg
) )
# Vérification explicite de la réussite # Vérification explicite de la réussite
if result is not None: # Si handle_game_data peut retourner un résultat indicatif if result is not None: # Si handle_game_data peut retourner un résultat indicatif
success = True success = True
print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} is REGISTERED ***") print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} is REGISTERED ***")
else:
raise ValueError("handle_game_data returned an unexpected result")
else: else:
print(f"*** Game #{self.game_id} simple game ENDED ***") raise ValueError("handle_game_data returned an unexpected result")
result = 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, False, None
)
if result is not None: else:
success = True print(f"*** Game #{self.game_id} simple game ENDED ***")
print(f"Non-tournament game {self.game_id} data registered") result = await sync_to_async(handle_game_data)(
else: self.game_state['player1_name'], self.game_state['player2_name'],
raise ValueError("handle_game_data returned an unexpected result") self.game_state['player1_score'], self.game_state['player2_score'],
self.bt1, self.bt2, duration, False, None
)
print("result done !!!")
except Exception as e: if result is not None:
attempt += 1 success = True
print(f"Attempt {attempt}: Failed to register game data - {e}") print(f"Non-tournament game {self.game_id} data registered")
await asyncio.sleep(1) # Délai avant de réessayer else:
raise ValueError("handle_game_data returned an unexpected result")
if attempt >= max_attempts: except Exception as e:
print("Max attempts reached. Could not register game data.") attempt += 1
break print(f"Attempt {attempt}: Failed to register game data - {e}")
await asyncio.sleep(1) # Délai avant de réessayer
if attempt >= max_attempts:
print("Max attempts reached. Could not register game data.")
#break

View File

@ -1,4 +1,4 @@
# Generated by Django 5.0.7 on 2024-07-31 16:01 # Generated by Django 5.1.1 on 2024-09-13 11:41
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models from django.db import migrations, models
@ -20,12 +20,6 @@ class Migration(migrations.Migration):
('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(blank=True, decimal_places=2, max_digits=5, null=True)), ('p_win', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
('m_score_match', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
('m_score_adv_match', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
('best_score', models.PositiveSmallIntegerField(default=0)),
('m_nbr_ball_touch', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
('total_duration', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
('m_duration', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
('num_participated_tournaments', models.PositiveSmallIntegerField(default=0)), ('num_participated_tournaments', models.PositiveSmallIntegerField(default=0)),
('num_won_tournaments', models.PositiveSmallIntegerField(default=0)), ('num_won_tournaments', models.PositiveSmallIntegerField(default=0)),
], ],
@ -36,7 +30,7 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)), ('name', models.CharField(max_length=200)),
('nbr_player', models.PositiveSmallIntegerField()), ('nbr_player', models.PositiveSmallIntegerField()),
('date', models.DateField()), ('date', models.DateField(auto_now_add=True)),
('winner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='game.player')), ('winner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='game.player')),
], ],
), ),
@ -53,7 +47,7 @@ class Migration(migrations.Migration):
('is_tournoi', models.BooleanField()), ('is_tournoi', models.BooleanField()),
('player1', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player1', to='game.player')), ('player1', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player1', to='game.player')),
('player2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player2', to='game.player')), ('player2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='match_as_player2', to='game.player')),
('winner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='won_matches', to='game.player')), ('winner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='won_matches', to='game.player')),
('tournoi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='matches', to='game.tournoi')), ('tournoi', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='matches', to='game.tournoi')),
], ],
), ),

View File

@ -1,19 +0,0 @@
# Generated by Django 5.0.7 on 2024-07-31 16:04
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('game', '0001_initial'),
]
operations = [
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'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.1 on 2024-09-10 14:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('game', '0002_alter_match_winner'),
]
operations = [
migrations.AlterField(
model_name='tournoi',
name='date',
field=models.DateField(auto_now_add=True),
),
]

View File

@ -10,12 +10,6 @@ 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) num_won_tournaments = models.PositiveSmallIntegerField(default=0)

View File

@ -82,13 +82,13 @@ class TournamentMatchMaker:
# Tournament start method # Tournament start method
async def start_tournament(self): async def start_tournament(self):
if len(self.waiting_players) < 3:
if len(self.waiting_players) < 2:
return False return False
if len(self.waiting_players) % 2 == 0:
await self.add_player(None)
self.tournament_state = "in_progress"
random.shuffle(self.waiting_players) random.shuffle(self.waiting_players)
'''if (len(self.waiting_players) % 2) != 0:
print("Adding a BYE to the tournament..")
await self.add_player(None)'''
self.tournament_state = "in_progress"
self.current_round = 0 self.current_round = 0
len_tournament = await sync_to_async(getlen)() len_tournament = await sync_to_async(getlen)()
self.final_name = self.name + " #" + str(len_tournament + 1) self.final_name = self.name + " #" + str(len_tournament + 1)
@ -97,7 +97,7 @@ class TournamentMatchMaker:
return True return True
async def advance_tournament(self): async def advance_tournament(self):
players = self.waiting_players players = self.waiting_players
while len(players) > 1: while len(players) > 1:
self.current_round += 1 self.current_round += 1
print(f"Starting round {self.current_round} with {len(players)} players") print(f"Starting round {self.current_round} with {len(players)} players")
@ -110,7 +110,8 @@ class TournamentMatchMaker:
await asyncio.sleep(1) # Wait for 1 second before checking again await asyncio.sleep(1) # Wait for 1 second before checking again
# Get winners for the next round # Get winners for the next round
players = self.get_round_winners() players = self.get_round_winners()
print(f"Round {self.current_round} finished. {len(players)} players advancing.") print(f"Round {self.current_round} finished. {len(players)} players advancing.")
await asyncio.sleep(10)
# Tournament has ended # Tournament has ended
await self.update_brackets() await self.update_brackets()
await self.end_tournament(players[0] if players else None) await self.end_tournament(players[0] if players else None)
@ -180,6 +181,14 @@ class TournamentMatchMaker:
match.game_state['player1_score'] = 3 match.game_state['player1_score'] = 3
match.game_state['player2_score'] = 0 match.game_state['player2_score'] = 0
await match.end_game() await match.end_game()
await self.send_game_text(match.player1, "You lucky bastard!\n You got an auto-win!")
async def send_game_text(self, player, text):
message = json.dumps({
'type': 'game_text_update',
'game_text': text
})
await player.send(message)
def get_round_winners(self): def get_round_winners(self):
winners = [] winners = []

View File

@ -4,74 +4,54 @@ 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 datetime import timedelta
from channels.db import database_sync_to_async from channels.db import database_sync_to_async
from asgiref.sync import sync_to_async
from django.db.models import Q
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 !!!!!!!!") print("Here !!!!!!!!")
player_1 = get_or_create_player(p1) player_1 = get_or_create_player(p1)
print("FIRST PLAYER REGISTERD")
player_2 = get_or_create_player(p2) player_2 = get_or_create_player(p2)
print("SECOND PLAYER REGISTERD")
if (not player_1 or not player_2) :
print("AIIEJJDFKJBDBKJJKB PROBLEME ORIOL ")
print("CHAKU & THEOUCHE are the BEST") print("CHAKU & THEOUCHE are the BEST")
create_match(player_1, player_2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament) 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")
update_player_statistics(p2) update_player_statistics(p2)
print("END UPDATE SECOND PLAYER")
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 get_player(name):
return Player.objects.get(name=name)
def get_or_create_player(name): def get_or_create_player(name):
player_exists = get_player_by_name(name) print("Get or create player")
if not player_exists: # Utilise get_or_create pour chercher un joueur existant ou en créer un nouveau avec les valeurs par défaut
player = create_player(name) player, created = Player.objects.get_or_create(
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, name=name,
total_match=total_match, defaults={
total_win=total_win, 'total_match': 0,
p_win=p_win, 'total_win': 0,
m_score_match=m_score_match, 'p_win': None,
m_score_adv_match=m_score_adv_match, 'num_participated_tournaments': 0,
best_score=best_score, 'num_won_tournaments': 0
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() if created:
print("Player created")
else:
print("Player exists")
return player return player
def create_tournoi(name, nbr_player, date, winner): def create_tournoi(name, nbr_player, date, winner):
tournoi = Tournoi(name=name, nbr_player=nbr_player, date=date, winner=winner) tournoi = Tournoi(name=name, nbr_player=nbr_player, date=date, winner=winner)
tournoi.save() tournoi.save()
@ -101,71 +81,50 @@ def create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_
return match return match
def update_player_statistics(player_name): def update_player_statistics(player_name):
print("UPDATED DATA")
player = get_object_or_404(Player, name=player_name) player = get_object_or_404(Player, name=player_name)
matches_as_player1 = Match.objects.filter(player1=player)
matches_as_player2 = Match.objects.filter(player2=player)
total_match = matches_as_player1.count() + matches_as_player2.count() matches = Match.objects.filter(Q(player1=player) | Q(player2=player))
total_match = matches.count()
# avoid dividing by 0 # avoid dividing by 0
if total_match == 0: if total_match == 0:
player.total_match = total_match player.total_match = total_match
player.total_win = 0 player.total_win = 0
player.p_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_participated_tournaments = 0
player.num_won_tournaments = 0 player.num_won_tournaments = 0
player.save() player.save()
return return
nb_win =0
won_matches = Match.objects.filter(winner=player) for match in matches :
if match.winner == player:
nb_win = nb_win + 1
#won_matches = Match.objects.filter(winner=player)
#part_tourn_as_p1 = Tournoi.objects.filter(matches__is_tournoi=True, matches__matches_as_player1=player) #part_tourn_as_p1 = Tournoi.objects.filter(matches__is_tournoi=True, matches__matches_as_player1=player)
#part_tourn_as_p2 = Tournoi.objects.filter(matches__is_tournoi=True, matches__matches_as_player2=player) #part_tourn_as_p2 = Tournoi.objects.filter(matches__is_tournoi=True, matches__matches_as_player2=player)
#won_tourn = Tournoi.objects.filter(winner=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_win = won_matches.count()
p_win = (nb_win/ total_match) * 100
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_tourn_p = part_tourn_as_p1.count() + part_tourn_as_p2.count()
#total_win_tourn = won_tourn.count() #total_win_tourn = won_tourn.count()
#p_win_tourn = (total_win_tourn / total_tourn_p) * 100 if total_tourn_p else 0 #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_match = total_match
player.total_win = total_win player.total_win = total_win
player.p_win = p_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_participated_tournaments = total_tourn_p
#player.num_won_tournaments = total_win_tourn #player.num_won_tournaments = total_win_tourn

View File

@ -3,7 +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 .utils import 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
@ -84,8 +84,6 @@ 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',
'm_score_match', 'm_score_adv_match', 'best_score',
'm_nbr_ball_touch', 'total_duration', 'm_duration',
'num_participated_tournaments', 'num_won_tournaments' 'num_participated_tournaments', 'num_won_tournaments'
)) ))
} }

View File

@ -148,12 +148,6 @@ document.addEventListener('DOMContentLoaded', () => {
<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> <td>${player.num_won_tournaments}</td>
`; `;

View File

@ -388,6 +388,8 @@ document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('keydown', handleKeyDown); document.addEventListener('keydown', handleKeyDown);
} else if (data.type === 'game_state_update') { } else if (data.type === 'game_state_update') {
updateGameState(data.game_state); updateGameState(data.game_state);
} else if (data.type === 'game_text_update') {
updateGameText(data.game_text);
} else if (data.type === 'player_disconnected') { } else if (data.type === 'player_disconnected') {
console.log('Player disconnected:', data.player); console.log('Player disconnected:', data.player);
} else if (data.type === 'game_ended') { } else if (data.type === 'game_ended') {
@ -462,6 +464,10 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementById('game-text').textContent = gameState.game_text; document.getElementById('game-text').textContent = gameState.game_text;
} }
function updateGameText(gameText) {
document.getElementById('game-text').textContent = gameText;
}
const starsContainer = document.getElementById('stars'); const starsContainer = document.getElementById('stars');
for (let i = 0; i < 500; i++) { for (let i = 0; i < 500; i++) {
const star = document.createElement('div'); const star = document.createElement('div');

View File

@ -161,12 +161,6 @@
<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>

View File

@ -1,8 +1,9 @@
django django>=3.2
psycopg2 psycopg[binary]
python-dotenv python-dotenv
channels channels
daphne daphne
djangorestframework djangorestframework
web3 web3
python-json-logger==2.0.7 python-json-logger==2.0.7