diff --git a/docker-compose.yml b/docker-compose.yml index 062be5a..06ddc5c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,63 +1,5 @@ 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: . @@ -112,103 +54,7 @@ services: 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: @@ -221,14 +67,7 @@ volumes: 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: diff --git a/docker-compose_save.yml b/docker-compose_save.yml new file mode 100644 index 0000000..062be5a --- /dev/null +++ b/docker-compose_save.yml @@ -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 diff --git a/makefile b/makefile index e7fbc31..7cd710f 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ COMPOSE_FILE=docker-compose.yml COMPOSE=docker compose -f $(COMPOSE_FILE) CONTAINER=$(c) -up: down +up: $(COMPOSE) build $(COMPOSE) up -d $(CONTAINER) || true diff --git a/pong/game/game.py b/pong/game/game.py index a7ca65e..d89521e 100644 --- a/pong/game/game.py +++ b/pong/game/game.py @@ -9,6 +9,9 @@ from asgiref.sync import sync_to_async from .models import Tournoi class Game: + # Global variable to handle the using of the database + USING_DB = False + def __init__(self, game_id, player1, player2, localgame): self.game_id = game_id self.player1 = player1 @@ -137,6 +140,7 @@ class Game: self.game_state['game_text'] = f"{self.game_state['player2_name']} WINS!" await self.send_game_state() await self.end_game() + #printf("player2 wins") self.reset_ball() elif self.game_state['ball_position']['x'] >= 790: self.game_state['player1_score'] += 1 @@ -144,6 +148,7 @@ class Game: self.game_state['game_text'] = f"{self.game_state['player1_name']} WINS!" await self.send_game_state() await self.end_game() + #printf("player1 wins") self.reset_ball() def reset_ball(self): @@ -225,6 +230,7 @@ class Game: # Notify that one player left the game if disconnected_player: + printf("Disconnected player") remaining_player = self.player2 if disconnected_player == self.player1 else self.player1 disconnected_name = disconnected_player.user.username message = json.dumps({ @@ -251,44 +257,45 @@ class Game: success = False print(f"Try to save game #{self.game_id} ({self})") - while attempt < max_attempts and not success: - try: - if hasattr(self, 'tournament'): - print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} ENDED ***") - - # Essaye d'appeler 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_score'], self.game_state['player2_score'], - self.bt1, self.bt2, duration, True, self.tournament.tournoi_reg - ) - - # Vérification explicite de la réussite - if result is not None: # Si handle_game_data peut retourner un résultat indicatif - success = True - 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") - + #while attempt < max_attempts and not success: + try: + if hasattr(self, 'tournament'): + print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} ENDED ***") + + # Essaye d'appeler 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_score'], self.game_state['player2_score'], + self.bt1, self.bt2, duration, True, self.tournament.tournoi_reg + ) + + # Vérification explicite de la réussite + if result is not None: # Si handle_game_data peut retourner un résultat indicatif + success = True + print(f"*** Game #{self.game_id} from tournament: {self.tournament.tournoi_reg.name} is REGISTERED ***") else: - print(f"*** Game #{self.game_id} simple game ENDED ***") - 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 - ) + raise ValueError("handle_game_data returned an unexpected result") - if result is not None: - success = True - print(f"Non-tournament game {self.game_id} data registered") - else: - raise ValueError("handle_game_data returned an unexpected result") + else: + print(f"*** Game #{self.game_id} simple game ENDED ***") + 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 + ) + print("result done !!!") - except Exception as e: - attempt += 1 - print(f"Attempt {attempt}: Failed to register game data - {e}") - await asyncio.sleep(1) # Délai avant de réessayer + if result is not None: + success = True + print(f"Non-tournament game {self.game_id} data registered") + else: + raise ValueError("handle_game_data returned an unexpected result") - if attempt >= max_attempts: - print("Max attempts reached. Could not register game data.") - break + except Exception as e: + attempt += 1 + 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 diff --git a/pong/game/migrations/0001_initial.py b/pong/game/migrations/0001_initial.py index 2f03168..dd2cf41 100644 --- a/pong/game/migrations/0001_initial.py +++ b/pong/game/migrations/0001_initial.py @@ -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 from django.db import migrations, models @@ -20,12 +20,6 @@ class Migration(migrations.Migration): ('total_match', models.PositiveSmallIntegerField(default=0)), ('total_win', models.PositiveSmallIntegerField(default=0)), ('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_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')), ('name', models.CharField(max_length=200)), ('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')), ], ), @@ -53,7 +47,7 @@ class Migration(migrations.Migration): ('is_tournoi', models.BooleanField()), ('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')), - ('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')), ], ), diff --git a/pong/game/migrations/0002_alter_match_winner.py b/pong/game/migrations/0002_alter_match_winner.py deleted file mode 100644 index fe0f120..0000000 --- a/pong/game/migrations/0002_alter_match_winner.py +++ /dev/null @@ -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'), - ), - ] diff --git a/pong/game/migrations/0003_alter_tournoi_date.py b/pong/game/migrations/0003_alter_tournoi_date.py deleted file mode 100644 index 6bfda6c..0000000 --- a/pong/game/migrations/0003_alter_tournoi_date.py +++ /dev/null @@ -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), - ), - ] diff --git a/pong/game/models.py b/pong/game/models.py index 4f63102..7fcab85 100644 --- a/pong/game/models.py +++ b/pong/game/models.py @@ -10,12 +10,6 @@ class Player(models.Model): total_match = models.PositiveSmallIntegerField(default=0) total_win = models.PositiveSmallIntegerField(default=0) 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_won_tournaments = models.PositiveSmallIntegerField(default=0) diff --git a/pong/game/tournament.py b/pong/game/tournament.py index 24de2fc..ce2badd 100644 --- a/pong/game/tournament.py +++ b/pong/game/tournament.py @@ -82,13 +82,13 @@ class TournamentMatchMaker: # Tournament start method async def start_tournament(self): - - if len(self.waiting_players) < 2: + if len(self.waiting_players) < 3: return False - if len(self.waiting_players) % 2 == 0: - await self.add_player(None) - self.tournament_state = "in_progress" 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 len_tournament = await sync_to_async(getlen)() self.final_name = self.name + " #" + str(len_tournament + 1) @@ -97,7 +97,7 @@ class TournamentMatchMaker: return True async def advance_tournament(self): - players = self.waiting_players + players = self.waiting_players while len(players) > 1: self.current_round += 1 print(f"Starting round {self.current_round} with {len(players)} players") @@ -110,7 +110,8 @@ class TournamentMatchMaker: await asyncio.sleep(1) # Wait for 1 second before checking again # Get winners for the next round 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 await self.update_brackets() 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['player2_score'] = 0 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): winners = [] diff --git a/pong/game/utils.py b/pong/game/utils.py index 8113f7c..6a81eb7 100644 --- a/pong/game/utils.py +++ b/pong/game/utils.py @@ -4,74 +4,54 @@ from django.shortcuts import get_object_or_404 from django.db.models import Max, Sum, F from datetime import timedelta 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): try: print("Here !!!!!!!!") player_1 = get_or_create_player(p1) + print("FIRST PLAYER REGISTERD") 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") create_match(player_1, player_2, s_p1, s_p2, bt_p1, bt_2, dur, is_tournoi, name_tournament) print("and ADRIANO is the PEST") update_player_statistics(p1) + print("END UPDATE FISRT PLAYER") update_player_statistics(p2) - + print("END UPDATE SECOND PLAYER") + except Exception as 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): - 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( + print("Get or create player") + # Utilise get_or_create pour chercher un joueur existant ou en créer un nouveau avec les valeurs par défaut + player, created = Player.objects.get_or_create( 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 + defaults={ + 'total_match': 0, + 'total_win': 0, + 'p_win': None, + 'num_participated_tournaments': 0, + 'num_won_tournaments': 0 + } ) - player.save() + if created: + print("Player created") + else: + print("Player exists") return player + + def create_tournoi(name, nbr_player, date, winner): tournoi = Tournoi(name=name, nbr_player=nbr_player, date=date, winner=winner) tournoi.save() @@ -101,71 +81,50 @@ def create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_ return match def update_player_statistics(player_name): + print("UPDATED DATA") 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 if total_match == 0: 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 + + 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_p2 = Tournoi.objects.filter(matches__is_tournoi=True, matches__matches_as_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_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_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 diff --git a/pong/game/views.py b/pong/game/views.py index 304cf1d..97eb65f 100644 --- a/pong/game/views.py +++ b/pong/game/views.py @@ -3,7 +3,7 @@ from django.shortcuts import render from django.core.exceptions import ObjectDoesNotExist 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.contrib.auth.models import User from django.contrib.auth import authenticate @@ -84,8 +84,6 @@ def player_list_json(request): data = { 'players': list(players.values( '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' )) } diff --git a/pong/static/burger.js b/pong/static/burger.js index ca45088..0573b22 100644 --- a/pong/static/burger.js +++ b/pong/static/burger.js @@ -148,12 +148,6 @@ document.addEventListener('DOMContentLoaded', () => {