From 4739afbaf01aaa35dace7e98824e011d571f711a Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 11:32:49 +0100 Subject: [PATCH 01/16] block: fix: .exists() --- profiles/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/views.py b/profiles/views.py index 06b5f0c..e32a8cf 100644 --- a/profiles/views.py +++ b/profiles/views.py @@ -12,7 +12,7 @@ class BlockView(APIView): def get(self, request, pk): block = BlockModel.objects.filter(pk=pk) - if (block): + if (block.exists()): return Response(serializers.serialize("json", block), status=status.HTTP_200_OK) else: return Response("Not Found", status=status.HTTP_404_NOT_FOUND) From bfc58e74a9f8188e2548127135edb65ce7f19f03 Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 11:33:06 +0100 Subject: [PATCH 02/16] game: add: retrive view --- games/serializers.py | 3 ++- games/urls.py | 9 +++++++++ games/views.py | 3 --- games/viewset.py | 27 +++++++++++++++++++++++++++ transcendence/urls.py | 1 + 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 games/urls.py delete mode 100644 games/views.py create mode 100644 games/viewset.py diff --git a/games/serializers.py b/games/serializers.py index 5bd2fc6..0c19b0b 100644 --- a/games/serializers.py +++ b/games/serializers.py @@ -21,4 +21,5 @@ class GameSerializer(serializers.ModelSerializer): return "waiting" def get_players_id(self, instance: GameModel): - players_id = [player_game.member_id for player_game in GameMembersModel.objects.filter(game_id=instance.pk)] \ No newline at end of file + players_id = [player_game.player_id for player_game in GameMembersModel.objects.filter(game_id = instance.pk)] + return players_id \ No newline at end of file diff --git a/games/urls.py b/games/urls.py new file mode 100644 index 0000000..96d61a8 --- /dev/null +++ b/games/urls.py @@ -0,0 +1,9 @@ +from django.urls import path, re_path +from django.conf import settings +from django.conf.urls.static import static + +from .viewset import GameViewSet + +urlpatterns = [ + path("", GameViewSet.as_view({"get": "retrieve"}), name="game_page"), +] \ No newline at end of file diff --git a/games/views.py b/games/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/games/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/games/viewset.py b/games/viewset.py new file mode 100644 index 0000000..622cdf1 --- /dev/null +++ b/games/viewset.py @@ -0,0 +1,27 @@ +from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework import permissions, status +from rest_framework.authentication import SessionAuthentication + +from django.http import HttpRequest +from django.db.models import QuerySet + +from .models import GameModel +from .serializers import GameSerializer + +# Create your views here. +class GameViewSet(viewsets.ModelViewSet): + + queryset = GameModel.objects + serializer_class = GameSerializer + permission_classes = (permissions.IsAuthenticated,) + authentication_classes = (SessionAuthentication,) + + def retrieve(self, request: HttpRequest, pk): + + if (not self.queryset.filter(pk = pk).exists()): + return Response({"detail": "Game not found."}, status=status.HTTP_404_NOT_FOUND) + + game = self.queryset.get(pk=pk) + + return Response(self.serializer_class(game).data, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/transcendence/urls.py b/transcendence/urls.py index 38eb6d0..d0d06ad 100644 --- a/transcendence/urls.py +++ b/transcendence/urls.py @@ -23,5 +23,6 @@ urlpatterns = [ path('api/accounts/', include('accounts.urls')), path('api/chat/', include('chat.urls')), path('api/tournaments/', include('tournament.urls')), + path('api/games/', include('games.urls')), path('', include('frontend.urls')), ] From 2e8eebc7886f0dd4ec507d7abcfb6388286677a9 Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 11:34:18 +0100 Subject: [PATCH 03/16] game: allow any to get game data --- games/viewset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/games/viewset.py b/games/viewset.py index 622cdf1..17e25a1 100644 --- a/games/viewset.py +++ b/games/viewset.py @@ -14,7 +14,7 @@ class GameViewSet(viewsets.ModelViewSet): queryset = GameModel.objects serializer_class = GameSerializer - permission_classes = (permissions.IsAuthenticated,) + permission_classes = (permissions.AllowAny,) authentication_classes = (SessionAuthentication,) def retrieve(self, request: HttpRequest, pk): From f11af8336a70548c1e2cf80726338ed0fc5c52a8 Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 12:01:52 +0100 Subject: [PATCH 04/16] game: init: class --- games/objects/GameMember.py | 17 +++++++++++++++++ games/objects/GameRoom.py | 9 +++++++++ games/objects/GameRoomManager.py | 18 ++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 games/objects/GameMember.py create mode 100644 games/objects/GameRoom.py create mode 100644 games/objects/GameRoomManager.py diff --git a/games/objects/GameMember.py b/games/objects/GameMember.py new file mode 100644 index 0000000..a2cdcb9 --- /dev/null +++ b/games/objects/GameMember.py @@ -0,0 +1,17 @@ +from channels.generic.websocket import AsyncWebsocketConsumer + +from transcendence.abstract.AbstractRoomMember import AbstractRoomMember + +class GameMember(AbstractRoomMember): + + def __init__(self, user_id: int, socket: AsyncWebsocketConsumer): + super().__init__(user_id, socket) + self.is_a_player = False + + def receive(self, data: dict): + if (not self.is_a_player): + self.send("You are not a player.") + return + + def send_ball(self, ball): + pass \ No newline at end of file diff --git a/games/objects/GameRoom.py b/games/objects/GameRoom.py new file mode 100644 index 0000000..1ee12f8 --- /dev/null +++ b/games/objects/GameRoom.py @@ -0,0 +1,9 @@ +from transcendence.abstract.AbstractRoom import AbstractRoom + +from .GameRoomManager import GameRoomManager + +class GameRoom(AbstractRoom): + + def __init__(self, game_room_manager: GameRoomManager, game_id: int): + super().__init__(game_room_manager) + self.game_id = game_id \ No newline at end of file diff --git a/games/objects/GameRoomManager.py b/games/objects/GameRoomManager.py new file mode 100644 index 0000000..e304541 --- /dev/null +++ b/games/objects/GameRoomManager.py @@ -0,0 +1,18 @@ +from transcendence.abstract.AbstractRoomManager import AbstractRoomManager + +from ..models import GameModel + +class GameRoomManager(AbstractRoomManager): + + def get(self, game_id: int): + + for room in self._room_list: + if (room.game_id == game_id): + return room + + if (GameModel.objects.filter(pk = tournament_id).exists()): + room = TournamentRoom(self, game_id) + self.append(room) + return room + + return None \ No newline at end of file From 231622a2c23ada428483bd37fda1fe1a7f3d6329 Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 12:02:39 +0100 Subject: [PATCH 05/16] game: init: consumer --- games/consumers.py | 42 ++++++++++++++++++++++++++++++++++++++++++ games/models.py | 8 +++++++- games/routing.py | 6 ++++++ tournament/routing.py | 2 +- transcendence/asgi.py | 4 +++- 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 games/consumers.py create mode 100644 games/routing.py diff --git a/games/consumers.py b/games/consumers.py new file mode 100644 index 0000000..473e2da --- /dev/null +++ b/games/consumers.py @@ -0,0 +1,42 @@ +from channels.generic.websocket import AsyncWebsocketConsumer + +from django.contrib.auth.models import User + +from games.models import GameModel + +import json + +from .models import game_room_manager + +class GameWebSocket(AsyncWebsocketConsumer): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.channel_name = "games" + self.group_name = "games" + + def connect(self): + + self.user: User = self.scope["user"] + if (self.user.is_anonymous or not self.user.is_authenticated): + return + + self.channel_layer.group_add(self.group_name, self.channel_name) + + self.game_id = int(self.scope['url_route']['kwargs']['game_id']) + + self.room = game_room_manager.get(self.game_id) + + if (self.room is None): + self.member.send("Tournament not found") + self.disconnect(1017) + + self.room.append(self.member) + + def receive(self, text_data: str = None, bytes_data: bytes = None): + self.member.receive(text_data, bytes_data) + + def disconnect(self, close_code): + member = self.room.get_member_by_socket(self) + if (member is not None): + self.room.remove(self.member, close_code) \ No newline at end of file diff --git a/games/models.py b/games/models.py index 36d5394..a504972 100644 --- a/games/models.py +++ b/games/models.py @@ -1,5 +1,9 @@ from django.db import models +from .objects.GameRoomManager import GameRoomManager + +from channels.generic.websocket import AsyncWebsocketConsumer + # Create your models here. class GameModel(models.Model): @@ -18,4 +22,6 @@ class GameModel(models.Model): class GameMembersModel(models.Model): game_id = models.IntegerField() - player_id = models.IntegerField() \ No newline at end of file + player_id = models.IntegerField() + +game_room_manager: GameRoomManager = GameRoomManager() \ No newline at end of file diff --git a/games/routing.py b/games/routing.py new file mode 100644 index 0000000..7271972 --- /dev/null +++ b/games/routing.py @@ -0,0 +1,6 @@ +from django.urls import re_path +from . import consumers + +websocket_urlpatterns = [ + re_path(r'ws/tournaments/(?P\d+)$', consumers.TournamentWebConsumer.as_asgi()) +] diff --git a/tournament/routing.py b/tournament/routing.py index 7271972..eed3b1c 100644 --- a/tournament/routing.py +++ b/tournament/routing.py @@ -2,5 +2,5 @@ from django.urls import re_path from . import consumers websocket_urlpatterns = [ - re_path(r'ws/tournaments/(?P\d+)$', consumers.TournamentWebConsumer.as_asgi()) + re_path(r'ws/games/(?P\d+)$', consumers.GameWebSocket.as_asgi()) ] diff --git a/transcendence/asgi.py b/transcendence/asgi.py index 939a8ed..cb8ac86 100644 --- a/transcendence/asgi.py +++ b/transcendence/asgi.py @@ -14,6 +14,7 @@ from channels.auth import AuthMiddlewareStack import chat.routing import matchmaking.routing import tournament.routing +import games.routing from django.core.asgi import get_asgi_application @@ -25,7 +26,8 @@ application = ProtocolTypeRouter({ URLRouter( chat.routing.websocket_urlpatterns + matchmaking.routing.websocket_urlpatterns + - tournament.routing.websocket_urlpatterns + tournament.routing.websocket_urlpatterns + + games.routing.websocket_urlpatterns ) ) }) From 5db03a3c69b306b6b0b47122c473255a1cb49910 Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 15:20:25 +0100 Subject: [PATCH 06/16] tournament: fix --- tournament/routing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tournament/routing.py b/tournament/routing.py index eed3b1c..4434723 100644 --- a/tournament/routing.py +++ b/tournament/routing.py @@ -2,5 +2,5 @@ from django.urls import re_path from . import consumers websocket_urlpatterns = [ - re_path(r'ws/games/(?P\d+)$', consumers.GameWebSocket.as_asgi()) + re_path(r'ws/games/(?P\d+)$', consumers.TournamentWebConsumer.as_asgi()) ] From 072944c5037a01f53115f744654eb46b64eabf1d Mon Sep 17 00:00:00 2001 From: starnakin Date: Thu, 28 Dec 2023 15:21:02 +0100 Subject: [PATCH 07/16] game: add: config --- games/config.py | 9 +++++++++ games/urls.py | 2 ++ games/views.py | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 games/config.py create mode 100644 games/views.py diff --git a/games/config.py b/games/config.py new file mode 100644 index 0000000..feed4aa --- /dev/null +++ b/games/config.py @@ -0,0 +1,9 @@ +PADDLE_SPEED_MAX = 1 +PADDLE_SIZE_HEIGHT = 10 +PADDLE_SIZE_WIDTH = 100 + +PADDLE_RAIL = PADDLE_SIZE_WIDTH * 5 + +BALL_SPEED_INC = 1 +BALL_SPEED_START = 1 +BALL_SIZE = 4 diff --git a/games/urls.py b/games/urls.py index 96d61a8..8495b34 100644 --- a/games/urls.py +++ b/games/urls.py @@ -3,7 +3,9 @@ from django.conf import settings from django.conf.urls.static import static from .viewset import GameViewSet +from .views import GameConfigView urlpatterns = [ path("", GameViewSet.as_view({"get": "retrieve"}), name="game_page"), + path("", GameConfigView.as_view(), name = "game_config") ] \ No newline at end of file diff --git a/games/views.py b/games/views.py new file mode 100644 index 0000000..2675031 --- /dev/null +++ b/games/views.py @@ -0,0 +1,23 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import permissions, status + +from django.http import HttpRequest + +from . import config + +class GameConfigView(APIView): + + permission_classes = (permissions.AllowAny,) + + def get(self, request): + config_data = { + "BALL_SIZE": config.BALL_SIZE, + "PADDLE_SPEED_MAX": config.PADDLE_SPEED_MAX, + "PADDLE_SIZE_HEIGHT": config.PADDLE_SIZE_HEIGHT, + "PADDLE_SIZE_WIDTH": config.PADDLE_SIZE_WIDTH, + "PADDLE_RAIL": config.PADDLE_RAIL, + "BALL_SPEED_INC": config.BALL_SPEED_INC, + "BALL_SPEED_START": config.BALL_SPEED_START + } + return Response(config_data, status = status.HTTP_200_OK) \ No newline at end of file From 7a595d37ec72ce3289f1eae4e725d7a8d2874fd4 Mon Sep 17 00:00:00 2001 From: AdrienLSH Date: Fri, 5 Jan 2024 11:40:22 +0100 Subject: [PATCH 08/16] add: boostrap navbar --- frontend/static/js/index.js | 5 +++++ frontend/templates/index.html | 26 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index db5c608..303a360 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -109,10 +109,15 @@ document.addEventListener("DOMContentLoaded", () => { document.body.addEventListener("click", e => { if (e.target.matches("[data-link]")) { e.preventDefault(); + document.querySelectorAll('[data-link]').forEach(e => { + e.classList.remove('active'); + }); + e.target.classList.add('active'); navigateTo(e.target.href.slice(location.origin.length)); } }); router(location.pathname); + document.querySelector('a[href=\'' + location.pathname + '\']').classList.add('active'); }); export { client, navigateTo } diff --git a/frontend/templates/index.html b/frontend/templates/index.html index 70f227e..3c37643 100644 --- a/frontend/templates/index.html +++ b/frontend/templates/index.html @@ -4,18 +4,24 @@ - Single Page App + Bozo Pong + - - -
+ + +
+
From 57b318ea8118ef973a8588bf47e02677fb322d03 Mon Sep 17 00:00:00 2001 From: AdrienLSH Date: Fri, 5 Jan 2024 11:58:41 +0100 Subject: [PATCH 09/16] del: useless shit --- frontend/static/css/index.css | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 frontend/static/css/index.css diff --git a/frontend/static/css/index.css b/frontend/static/css/index.css deleted file mode 100644 index a3a39b6..0000000 --- a/frontend/static/css/index.css +++ /dev/null @@ -1,10 +0,0 @@ - -body { - margin: 0.5em; - font-family: 'Quicksand', sans-serif; - font-size: 30px; -} - -a { - color: #009579; -} From 01d50f1d8c4911dfd3b9919ff6b9f38eecc728f5 Mon Sep 17 00:00:00 2001 From: AdrienLSH Date: Fri, 5 Jan 2024 12:17:23 +0100 Subject: [PATCH 10/16] fix: oopsies --- frontend/static/js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index 303a360..4b7e01d 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -117,7 +117,7 @@ document.addEventListener("DOMContentLoaded", () => { } }); router(location.pathname); - document.querySelector('a[href=\'' + location.pathname + '\']').classList.add('active'); + document.querySelector('a[href=\'' + location.pathname + '\']')?.classList.add('active'); }); export { client, navigateTo } From 3b28e4e59493e998e97b5524d339a65dac0ee3df Mon Sep 17 00:00:00 2001 From: AdrienLSH Date: Fri, 5 Jan 2024 14:17:56 +0100 Subject: [PATCH 11/16] fix: remove index.css link in html --- frontend/templates/index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/templates/index.html b/frontend/templates/index.html index 3c37643..c5cac24 100644 --- a/frontend/templates/index.html +++ b/frontend/templates/index.html @@ -6,7 +6,6 @@ Bozo Pong -