From fb9c54c8dfaa748d662b3f1d59f9b11ffe41a9e9 Mon Sep 17 00:00:00 2001 From: Theouche Date: Thu, 1 Aug 2024 17:26:14 +0200 Subject: [PATCH] add list selection players et match, need to move it on the side and use a icone --- env_template | 6 +- .../migrations/0002_alter_match_winner.py | 19 +++ pong/game/models.py | 2 +- pong/game/urls.py | 9 +- pong/game/views.py | 152 ++++-------------- pong/settings.py | 1 + pong/static/game.js | 91 +++++++++++ pong/static/index.html | 103 +++++++++++- pong/static/styles.css | 13 ++ requirements.txt | 3 +- 10 files changed, 273 insertions(+), 126 deletions(-) create mode 100644 pong/game/migrations/0002_alter_match_winner.py diff --git a/env_template b/env_template index ffa026a..a22175d 100644 --- a/env_template +++ b/env_template @@ -4,9 +4,9 @@ DEBUG=True DJANGO_ALLOWED_HOSTS=['*'] # PostgreSQL settings -POSTGRES_DB= -POSTGRES_USER= -POSTGRES_PASSWORD= +POSTGRES_DB=players_db +POSTGRES_USER=42student +POSTGRES_PASSWORD=test DB_HOST=db DB_PORT=5432 diff --git a/pong/game/migrations/0002_alter_match_winner.py b/pong/game/migrations/0002_alter_match_winner.py new file mode 100644 index 0000000..6dca924 --- /dev/null +++ b/pong/game/migrations/0002_alter_match_winner.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.7 on 2024-07-31 16:58 + +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/models.py b/pong/game/models.py index a4525b6..2586446 100644 --- a/pong/game/models.py +++ b/pong/game/models.py @@ -37,7 +37,7 @@ class Match(models.Model): player2 = models.ForeignKey('Player', related_name='match_as_player2', on_delete=models.CASCADE) score_player1 = models.PositiveSmallIntegerField() score_player2 = models.PositiveSmallIntegerField() - winner = models.ForeignKey('Player', related_name='won_matches',on_delete=models.CASCADE) + winner = models.ForeignKey('Player', related_name='won_matches',on_delete=models.CASCADE, null=True) nbr_ball_touch_p1 = models.PositiveIntegerField() nbr_ball_touch_p2 = models.PositiveIntegerField() duration = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) diff --git a/pong/game/urls.py b/pong/game/urls.py index 570f027..8da5f37 100644 --- a/pong/game/urls.py +++ b/pong/game/urls.py @@ -1,8 +1,13 @@ # /pong/game/urls.py -from django.urls import path +from django.urls import path, include from . import views from .views import player_list, tournoi_list, match_list +from rest_framework.routers import DefaultRouter +from .views import match_list_json +from .views import player_list_json + + urlpatterns = [ path('', views.index, name='index'), @@ -12,4 +17,6 @@ urlpatterns = [ path('players/', player_list, name='player_list'), path('matches/', match_list, name='match_list'), path('tournois/', tournoi_list, name='tournoi_list'), + path('api/match_list/', match_list_json, name='match_list_json'), + path('api/player_list/', player_list_json, name='player_list_json'), ] diff --git a/pong/game/views.py b/pong/game/views.py index 2743fa6..a6cc709 100644 --- a/pong/game/views.py +++ b/pong/game/views.py @@ -12,6 +12,9 @@ from django.http import JsonResponse from django.contrib.auth.models import User from django.contrib.auth import authenticate from django.views.decorators.csrf import csrf_exempt +""" from .serializers import MatchSerializer """ +from rest_framework import viewsets + import json import uuid @@ -69,124 +72,6 @@ def get_or_create_token(user): ####################### THEOUCHE PART ############################ - -@csrf_exempt -def create_player_view(request): - if request.method == 'POST': - try: - data = json.loads(request.body) - name = data.get('name') - - # Vérifier que le nom est présent - if not name: - return JsonResponse({'error': 'Name is required'}, status=400) - - # Appeler la fonction create_player et traiter les exceptions - player = create_player( - name=name, - total_match=data.get('total_match', 0), - total_win=data.get('total_win', 0), - p_win=data.get('p_win'), - m_score_match=data.get('m_score_match'), - m_score_adv_match=data.get('m_score_adv_match'), - best_score=data.get('best_score', 0), - m_nbr_ball_touch=data.get('m_nbr_ball_touch'), - total_duration=data.get('total_duration'), - m_duration=data.get('m_duration'), - num_participated_tournaments=data.get('num_participated_tournaments', 0), - num_won_tournaments=data.get('num_won_tournaments', 0) - ) - return JsonResponse({'id': player.id, 'name': player.name}) - - except ValueError as e: - # Erreur spécifique à la validation - return JsonResponse({'error': str(e)}, status=400) - except json.JSONDecodeError: - # Erreur de décodage JSON - return JsonResponse({'error': 'Invalid JSON format'}, status=400) - except Exception as e: - # Erreur générale - return JsonResponse({'error': 'An unexpected error occurred', 'details': str(e)}, status=500) - - # Méthode HTTP non supportée - return JsonResponse({'error': 'Invalid HTTP method'}, status=405) - - - -@csrf_exempt -def create_tournoi_view(request): - if request.method == 'POST': - data = json.loads(request.body) - name = data.get('name') - nbr_player = data.get('nbr_player') - date = data.get('date') - winner_id = data.get('winner_id') - if not (name and nbr_player and date): - return JsonResponse({'error': 'Name, number of players, and date are required'}, status=400) - - winner = None - if winner_id: - try: - winner = Player.objects.get(id=winner_id) - except Player.DoesNotExist: - return JsonResponse({'error': 'Winner not found'}, status=404) - - tournoi = create_tournoi(name, nbr_player, date, winner) - return JsonResponse({ - 'id': tournoi.id, - 'name': tournoi.name, - 'nbr_player': tournoi.nbr_player, - 'date': tournoi.date.isoformat(), - 'winner': winner.id if winner else None - }) - return JsonResponse({'error': 'Invalid HTTP method'}, status=405) - -@csrf_exempt -def create_match_view(request): - if request.method == 'POST': - data = json.loads(request.body) - player1_id = data.get('player1_id') - player2_id = data.get('player2_id') - score_player1 = data.get('score_player1', 0) - score_player2 = data.get('score_player2', 0) - nbr_ball_touch_p1 = data.get('nbr_ball_touch_p1', 0) - nbr_ball_touch_p2 = data.get('nbr_ball_touch_p2', 0) - duration = data.get('duration') - is_tournoi = data.get('is_tournoi', False) - tournoi_id = data.get('tournoi_id') - - if not (player1_id and player2_id and duration): - return JsonResponse({'error': 'Player IDs and duration are required'}, status=400) - - try: - player1 = Player.objects.get(id=player1_id) - player2 = Player.objects.get(id=player2_id) - except Player.DoesNotExist: - return JsonResponse({'error': 'One or both players not found'}, status=404) - - tournoi = None - if tournoi_id: - try: - tournoi = Tournoi.objects.get(id=tournoi_id) - except Tournoi.DoesNotExist: - return JsonResponse({'error': 'Tournoi not found'}, status=404) - - match = create_match(player1, player2, score_player1, score_player2, nbr_ball_touch_p1, nbr_ball_touch_p2, duration, is_tournoi, tournoi) - return JsonResponse({ - 'id': match.id, - 'player1': match.player1.id, - 'player2': match.player2.id, - 'score_player1': match.score_player1, - 'score_player2': match.score_player2, - 'nbr_ball_touch_p1': match.nbr_ball_touch_p1, - 'nbr_ball_touch_p2': match.nbr_ball_touch_p2, - 'duration': str(match.duration), - 'is_tournoi': match.is_tournoi, - 'tournoi': match.tournoi.id if match.tournoi else None - }) - return JsonResponse({'error': 'Invalid HTTP method'}, status=405) - - def player_list(request): players = Player.objects.all() return render(request, 'pong/player_list.html', {'players': players}) @@ -199,4 +84,35 @@ def tournoi_list(request): tournois = Tournoi.objects.select_related('winner').all() return render(request, 'pong/tournoi_list.html', {'tournois': tournois}) +from django.http import JsonResponse + +def match_list_json(request): + matches = Match.objects.select_related('player1', 'player2', 'winner', 'tournoi').all() + data = { + 'matches': list(matches.values( + 'id', 'player1__name', 'player2__name', 'score_player1', 'score_player2', + 'winner__name', 'nbr_ball_touch_p1', 'nbr_ball_touch_p2', 'duration', 'date', + 'is_tournoi', 'tournoi__name' + )) + } + return JsonResponse(data) + +def player_list_json(request): + # Récupère tous les joueurs + players = Player.objects.all() + + # Crée un dictionnaire avec les informations des joueurs + 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' + )) + } + + # Renvoie les données en JSON + return JsonResponse(data) + + ####################### THEOUCHE PART ############################ diff --git a/pong/settings.py b/pong/settings.py index e9f5627..83bd985 100644 --- a/pong/settings.py +++ b/pong/settings.py @@ -36,6 +36,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'channels', # Add Django Channels 'pong.game', # Your game app + 'rest_framework' ] MIDDLEWARE = [ diff --git a/pong/static/game.js b/pong/static/game.js index d857501..9437df0 100644 --- a/pong/static/game.js +++ b/pong/static/game.js @@ -11,6 +11,9 @@ document.addEventListener('DOMContentLoaded', () => { const loginForm = document.getElementById('login-form'); const registerForm = document.getElementById('register-form'); const formBlock = document.getElementById('block-form'); + const viewSelector = document.getElementById('view-selector'); + const playerList = document.getElementById('player-list'); + const matchList = document.getElementById('match-list'); let socket; @@ -241,4 +244,92 @@ document.addEventListener('DOMContentLoaded', () => { player2Score.textContent = gameState.player2_score; } + viewSelector.addEventListener('change', function() { + const selectedView = this.value; + + // Masquer les deux listes par défaut + playerList.style.display = 'none'; + matchList.style.display = 'none'; + + // Afficher la liste sélectionnée + if (selectedView === 'player-list') { + playerList.style.display = 'block'; + fetchPlayers(); + } else if (selectedView === 'match-list') { + matchList.style.display = 'block'; + fetchMatches(); + } + }) + + function fetchMatches() { + fetch('/api/match_list/') + .then(response => response.json()) + .then(data => { + if (data.matches) { + displayMatches(data.matches); + } + }) + .catch(error => console.error('Error fetching match data:', error)); + } + + function fetchPlayers(){ + fetch('/api/player_list/') + .then(response => response.json()) + .then(data => { + if (data.players) { + displayPlayers(data.players); + } + }) + .catch(error => console.error('Error fetching match data:', error)); + } + + function displayMatches(matches) { + const matchListBody = document.querySelector('#match-list tbody'); + matchListBody.innerHTML = ''; + + matches.forEach(match => { + const row = document.createElement('tr'); + row.innerHTML = ` + ${match.id} + ${match.player1__name} + ${match.player2__name} + ${match.score_player1} + ${match.score_player2} + ${match.winner__name} + ${match.nbr_ball_touch_p1} + ${match.nbr_ball_touch_p2} + ${match.duration} + ${match.date} + ${match.is_tournoi} + ${match.tournoi__name} + `; + matchListBody.appendChild(row); + }); + } + + function displayPlayers(players) { + const playersListBody = document.querySelector('#player-list tbody'); + playersListBody.innerHTML = ''; + + players.forEach(player => { + const row = document.createElement('tr'); + row.innerHTML = ` + ${player.id} + ${player.name} + ${player.total_match} + ${player.total_win} + ${player.p_win} + ${player.m_score_match} + ${player.m_score_adv_match} + ${player.best_score} + ${player.m_nbr_ball_touch} + ${player.total_duration} + ${player.m_duration} + ${player.num_participated_tournaments} + ${player.num_won_tournaments} + `; + playersListBody.appendChild(row); + }); + } + }); diff --git a/pong/static/index.html b/pong/static/index.html index 63fc79c..73bfccf 100644 --- a/pong/static/index.html +++ b/pong/static/index.html @@ -10,7 +10,6 @@ - @@ -46,6 +45,14 @@ + + + + + + + - \ No newline at end of file + diff --git a/pong/static/styles.css b/pong/static/styles.css index 460feb3..821277b 100644 --- a/pong/static/styles.css +++ b/pong/static/styles.css @@ -250,4 +250,17 @@ button:hover { position: relative; z-index: 10; max-width: 80%; +} + +.menu { + margin-top: 20px; + text-align: center; +} + +select#view-selector { + padding: 10px; + font-size: 16px; + border-radius: 5px; + border: 1px solid #ccc; + cursor: pointer; } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9b9e85a..3c23d90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ Django psycopg2 python-dotenv channels -daphne \ No newline at end of file +daphne +djangorestframework \ No newline at end of file