From 88e89209ac69f478deb1cfa3708e0e7304480443 Mon Sep 17 00:00:00 2001 From: Faraphel Date: Mon, 13 Mar 2023 09:01:59 +0100 Subject: [PATCH] comment in the _test et core modules --- source/_test/core.py | 11 ++++ source/_test/network.py | 14 ++--- source/_test/position.py | 37 ++++++++++++++ source/_test/utils.py | 24 +++++++++ source/core/Board.py | 65 +++++++++++++----------- source/core/Boat.py | 9 ++-- source/core/enums/BombState.py | 14 ++--- source/core/enums/Orientation.py | 2 +- source/core/error/InvalidBoatPosition.py | 4 ++ source/core/error/InvalidBombPosition.py | 4 ++ source/core/error/PositionAlreadyShot.py | 4 ++ 11 files changed, 141 insertions(+), 47 deletions(-) diff --git a/source/_test/core.py b/source/_test/core.py index b8e742e..0824ef3 100644 --- a/source/_test/core.py +++ b/source/_test/core.py @@ -8,8 +8,15 @@ from source.core.error import InvalidBoatPosition, InvalidBombPosition, Position class TestCore(unittest.TestCase): + """ + Unité de test pour tester l'implémentation du jeu. + """ def test_boats(self): + """ + Test pour le placement des bateaux + """ + board = Board(width=5, height=5) board.add_boat(Boat(5, Orientation.HORIZONTAL), (0, 0)) @@ -46,6 +53,10 @@ class TestCore(unittest.TestCase): ) def test_bombs(self): + """ + Test pour le placement des bombes + """ + board = Board(width=5, height=5) board.add_boat(Boat(5, Orientation.HORIZONTAL), (0, 0)) board.add_boat(Boat(4, Orientation.VERTICAL), (1, 1)) diff --git a/source/_test/network.py b/source/_test/network.py index 05d9304..9799358 100644 --- a/source/_test/network.py +++ b/source/_test/network.py @@ -8,13 +8,15 @@ from typing import Optional import numpy as np from source.core.enums import BombState -from source.network.packet import PacketChat, PacketUsername, PacketQuit, PacketAskSave, PacketBoatPlaced, \ - PacketLoadOldSave, PacketResponseSave, PacketHaveSaveBeenFound, PacketBombPlaced, PacketBombState, PacketSettings, \ - PacketBoatsData +from source.network.packet import * from source.network.packet.abc import Packet class TestNetwork(unittest.TestCase): + """ + Unité de test pour le réseau + """ + PORT: int = 54200 def __init__(self, *args, **kwargs): @@ -39,11 +41,11 @@ class TestNetwork(unittest.TestCase): thread_client.join() def __del__(self): + # ferme les connexions lorsque l'objet est supprimé self.co_client.close() self.so_server.close() - # tous les tests de packet sont réunis dans la même fonction pour éviter de réouvrir des sockets sur le mêmes - # ports encore et encore + # tous les tests de packet sont réunis dans la même fonction pour éviter de rouvrir des sockets sur le même port def test_packet(self): # PacketChat for _ in range(100): @@ -161,7 +163,7 @@ class TestNetwork(unittest.TestCase): # Packet Générique for _ in range(100): - # prend un packet signal aléatoire (sont plus simples a initialisé) + # prend un packet "signal" ou "variable lengh" aléatoire (sont les plus simples a initialisé) packet_sent_type = random.choice([PacketQuit, PacketAskSave, PacketBoatPlaced, PacketUsername, PacketChat]) if packet_sent_type in [PacketUsername, PacketChat]: diff --git a/source/_test/position.py b/source/_test/position.py index d6a4142..b4fb6e0 100644 --- a/source/_test/position.py +++ b/source/_test/position.py @@ -21,33 +21,62 @@ class TestBoxWidget(BoxWidget): super().__init__(x=100, y=200, width=150, height=175, scene=scene) +# Créer un objet widget qui pourra être utilisé dans les tests window = TestWindow() scene = TestScene(window) widget = TestBoxWidget(scene) class TestPosition(unittest.TestCase): + """ + Unité de test pour les unités de positionnement + """ + def test_unit_px(self): + """ + Test des unités px (pixel) + """ + for value in range(1, 500): self.assertEqual((value*px)(widget), value) def test_unit_vw(self): + """ + Test des unités vw (viewport width) + """ + for value in range(1, 200): self.assertEqual((value*vw)(widget), int(window.width * (value / 100))) def test_unit_vh(self): + """ + Test des unités vh (viewport height) + """ + for value in range(1, 200): self.assertEqual((value*vh)(widget), int(window.height * (value / 100))) def test_unit_ww(self): + """ + Test des unités ww (widget width) + """ + for value in range(1, 200): self.assertEqual((value*ww)(widget), int(widget.width * (value / 100))) def test_unit_wh(self): + """ + Test des unités wh (widget height) + """ + for value in range(1, 200): self.assertEqual((value * wh)(widget), int(widget.height * (value / 100))) def test_unit_add(self): + """ + Test des additions d'unités + """ + for value_px in range(1, 100): for value_vw in range(1, 100): self.assertEqual( @@ -56,6 +85,10 @@ class TestPosition(unittest.TestCase): ) def test_unit_sub(self): + """ + Test des soustractions d'unités + """ + for value_px in range(1, 100): for value_vw in range(1, 100): self.assertEqual( @@ -64,6 +97,10 @@ class TestPosition(unittest.TestCase): ) def test_unit_rsub(self): + """ + Test des soustractions d'unités (inversé) + """ + for value_px in range(1, 100): for value_vw in range(1, 100): self.assertEqual( diff --git a/source/_test/utils.py b/source/_test/utils.py index 8a39626..d81be14 100644 --- a/source/_test/utils.py +++ b/source/_test/utils.py @@ -5,7 +5,15 @@ from source.utils import dict_filter, dict_filter_prefix, dict_add_prefix, copy_ class TestDict(unittest.TestCase): + """ + Unité de test des fonctionnalités utilitaire pour dictionnaire + """ + def test_dict_filter(self): + """ + Test du filtre de dictionnaire + """ + self.assertEqual( dict_filter( lambda key, value: key.startswith("valeur"), @@ -31,6 +39,10 @@ class TestDict(unittest.TestCase): ) def test_dict_filter_prefix(self): + """ + Test du filtre de dictionnaire par prefix + """ + self.assertEqual( dict_filter_prefix( "valeur", @@ -56,6 +68,10 @@ class TestDict(unittest.TestCase): ) def test_dict_add_prefix(self): + """ + Test de l'ajout de prefix dans un dictionnaire + """ + self.assertEqual( dict_add_prefix( "valeur", @@ -82,7 +98,15 @@ class TestDict(unittest.TestCase): class TestMatrice(unittest.TestCase): + """ + Unité de test des fonctionnalités utilitaire pour matrice + """ + def test_copy_array_offset(self): + """ + Test de la copie d'une matrice dans une autre avec décalage + """ + src = np.array([ [1, 2, 3, 4], [5, 6, 7, 8] diff --git a/source/core/Board.py b/source/core/Board.py index 9129df0..09fb970 100644 --- a/source/core/Board.py +++ b/source/core/Board.py @@ -1,7 +1,7 @@ import numpy as np from source.core import Boat -from source.core.enums import Orientation, BombState +from source.core.enums import BombState from source.core.error import InvalidBoatPosition, PositionAlreadyShot, InvalidBombPosition from source.type import Point2D from source.utils import copy_array_offset @@ -9,8 +9,8 @@ from source.utils import copy_array_offset class Board: """ - Represent a board for the game. - Boat can be added and bomb can be placed. + Représente la planche de jeu. + Des bateaux et des bombes peuvent y être placé. """ __slots__ = ("width", "height", "boats", "bombs") @@ -41,76 +41,76 @@ class Board: def add_boat(self, boat: Boat, position: Point2D) -> None: """ - Add a boat to the board. Check before if the position is valid. - :boat: the boat to add - :position: the position where to add the boat - :raise: InvalidBoatPosition if the boat position is not valid + Ajoute un bateau à la planche. Vérifie avant si la position est valide. + :param boat: le bateau a placé + :param position: la position du bateau sur la planche + :raise: InvalidBoatPosition si la position du bateau est invalide """ - # get the old board matrice sum + # récupère l'ancienne somme total de la grille matriciel board_matrice = self.boats.copy() board_matrice_sum_old: int = board_matrice.sum() board_matrice_max = np.max(board_matrice) - # get the sum of the boat + # récupère la somme du bateau matriciel boat_matrice: np.array = boat.get_matrice(board_matrice_max+1) boat_matrice_sum: int = boat_matrice.sum() - # add the boat to the board matrice + # ajoute la matrice du bateau à la matrice de la grille try: copy_array_offset(boat_matrice, board_matrice, offset=position) except ValueError: raise InvalidBoatPosition(boat, position) - # get the new board matrice sum + # récupère la nouvelle somme de la grille matricielle board_matrice_sum_new: int = board_matrice.sum() - # if the sum of the old board plus the boat sum is different from the new board sum, - # then the boat have been incorrectly placed (overlapping, outside of bounds, ...) + # si la somme de l'ancienne planche et de la matrice du bateau n'est pas égal à celle de la nouvelle grille, + # alors le bateau n'est pas correctement placé (hors de la grille, par dessus un autre bateau, ...) if board_matrice_sum_old + boat_matrice_sum != board_matrice_sum_new: raise InvalidBoatPosition(boat, position) - # otherwise accept the boat in the boats dict + # sinon remplace l'ancienne matrice par la nouvelle self.boats = board_matrice def bomb(self, position: Point2D) -> BombState: """ - Hit a position on the board - :position: the position where to shoot - :raise: PositionAlreadyShot if the position have already been shot before + Place une bombe sur la grille + :position: la position de la bombe + :raise: PositionAlreadyShot si la bombe a déjà été placé ici, InvalidBombPosition si la position est invalide. """ - # if the bomb is inside the board + # si la bombe est bien dans les limites de la grille x, y = position if x >= self.width or y >= self.height: raise InvalidBombPosition(position) - # if this position have already been shot + # si une bombe a déjà été placé ici if not self.bombs[y, x]: raise PositionAlreadyShot(position) - # get the old board matrice + # récupère l'ancienne somme de la matrice de la grille board_mat_old_sum = self.get_matrice().sum() - # place the bomb (setting the position to False cause the matrice multiplication to remove the boat if any) + # place la bombe dessus (False équivaut à placer une bombe) self.bombs[y, x] = False - # get the new board matrice + # récupère la nouvelle somme de la matrice de la grille board_mat_new = self.get_matrice() board_mat_new_sum = board_mat_new.sum() - # if the board sum is 0, then there is no boat left on the board + # si la somme de la grille matricielle est 0, alors il n'y a plus de bateau sur la grille if board_mat_new_sum == 0: return BombState.WON - # get the difference between the old and new board sum. - # if the board sum changed, then the difference is the number of the boat that have been hit + # récupère la différence entre l'ancienne et la nouvelle somme de la grille + # si la somme a changé, alors un bateau a été touché. boat_touched: int = board_mat_old_sum - board_mat_new_sum - # if no boat have been touched, ignore + # si aucun bateau n'a été touché, ignore if boat_touched == 0: return BombState.NOTHING - # if the boat have sinked (no more tile with the boat on it) + # si le bateau a coulé (il n'y a plus de case correspondant à ce bateau) if not np.isin(boat_touched, board_mat_new): return BombState.SUNKEN - # if the boat have been touched, but without sinking + # si le bateau a été touché partiellement return BombState.TOUCHED def remove_bomb(self, cell: Point2D): @@ -129,10 +129,12 @@ class Board: def get_matrice(self) -> np.array: """ - :return: the boats and bombs represented as a matrice + :return: les bateaux et les bombes représentés sur une même matrice """ - return self.boats * self.bombs # Remove the position that have been bombed + # En multipliant la matrice des bombes par la matrice des bateaux, + # tous les bateaux avec une bombe dessus seront mis à 0 puisqu'une bombe placée vaut "False". + return self.boats * self.bombs def get_score(self) -> int: """ @@ -145,6 +147,7 @@ class Board: return boat_total - boat_left def to_json(self) -> dict: + # converti en json les données return { "boats": self.boats.tolist(), "bombs": self.bombs.tolist() @@ -152,12 +155,14 @@ class Board: @classmethod def from_json(cls, json_: dict) -> "Board": + # charge à partir de json les données return Board( boats=np.array(json_["boats"], dtype=np.ushort), bombs=np.array(json_["bombs"], dtype=np.bool_) ) def __copy__(self): + # fait une copie de la grille return self.__class__( boats=self.boats.copy(), bombs=self.bombs.copy(), diff --git a/source/core/Boat.py b/source/core/Boat.py index 9e032e8..3589483 100644 --- a/source/core/Boat.py +++ b/source/core/Boat.py @@ -5,8 +5,8 @@ from source.core.enums import Orientation class Boat: """ - Represent a boat. - It can be added to a board. + Représente un bateau. + Il peut être ajouté à une grille. """ __slots__ = ("orientation", "length") @@ -20,7 +20,8 @@ class Boat: def get_matrice(self, value: int = 1) -> np.array: """ - :return: the boat represented as a matrice + Représente le bateau sous la forme d'une matrice + :return: le bateau sous la forme d'une matrice """ return np.full( (1, self.length) if self.orientation == Orientation.HORIZONTAL else @@ -30,6 +31,7 @@ class Boat: ) def to_json(self) -> dict: + # converti le bateau en json return { "length": self.length, "orientation": self.orientation.to_json(), @@ -37,6 +39,7 @@ class Boat: @classmethod def from_json(cls, json_: dict) -> "Boat": + # charge le bateau à partir de json return Boat( length=json_["length"], orientation=Orientation.from_json(json_["orientation"]), diff --git a/source/core/enums/BombState.py b/source/core/enums/BombState.py index bd56ee6..661d97f 100644 --- a/source/core/enums/BombState.py +++ b/source/core/enums/BombState.py @@ -3,19 +3,19 @@ from enum import Enum class BombState(Enum): """ - This class represent the state of a bomb after being place on the board. + Cette classe représente les états d'une bombe après avoir été placé sur la grille. """ - NOTHING = 0 # the bomb missed - TOUCHED = 1 # the bomb touched a boat - SUNKEN = 2 # the bomb touched the last part of a boat - WON = 3 # the bomb sunk the last boat + NOTHING = 0 # la bombe a manqué + TOUCHED = 1 # la bombe a touché un bateau + SUNKEN = 2 # la bombe a coulé un bateau + WON = 3 # la bombe a coulé le dernier bateau - ERROR = -1 # the bomb could not be placed + ERROR = -1 # la bombe n'a pas été placé @property def success(self): """ - :return: Vrai si la valeur correspond à une case qui a été touché + :return: Vrai si une case a été touché """ return self in [self.TOUCHED, self.SUNKEN, self.WON] diff --git a/source/core/enums/Orientation.py b/source/core/enums/Orientation.py index 0e8d2d5..90986fd 100644 --- a/source/core/enums/Orientation.py +++ b/source/core/enums/Orientation.py @@ -3,7 +3,7 @@ from enum import Enum class Orientation(Enum): """ - Represent the orientation of a boat. + Les possibles orientations pour un bateau """ HORIZONTAL = "H" diff --git a/source/core/error/InvalidBoatPosition.py b/source/core/error/InvalidBoatPosition.py index 14f5894..97ad1f0 100644 --- a/source/core/error/InvalidBoatPosition.py +++ b/source/core/error/InvalidBoatPosition.py @@ -3,5 +3,9 @@ from source.type import Point2D class InvalidBoatPosition(Exception): + """ + Erreur utilisée lorsque le bateau n'a pas pu être placé + """ + def __init__(self, boat: Boat, position: Point2D): super().__init__(f"The boat {boat} can't be placed at {position}.") diff --git a/source/core/error/InvalidBombPosition.py b/source/core/error/InvalidBombPosition.py index c961274..7e252d0 100644 --- a/source/core/error/InvalidBombPosition.py +++ b/source/core/error/InvalidBombPosition.py @@ -2,5 +2,9 @@ from source.type import Point2D class InvalidBombPosition(Exception): + """ + Erreur utilisée lorsque la bombe n'a pas pu être placé + """ + def __init__(self, position: Point2D): super().__init__(f"The bomb can't be placed at {position}.") diff --git a/source/core/error/PositionAlreadyShot.py b/source/core/error/PositionAlreadyShot.py index 2db497c..e15e50e 100644 --- a/source/core/error/PositionAlreadyShot.py +++ b/source/core/error/PositionAlreadyShot.py @@ -2,6 +2,10 @@ from source.type import Point2D class PositionAlreadyShot(Exception): + """ + Erreur utilisée lorsque la bombe vise une case déjà touchée + """ + def __init__(self, position: Point2D): super().__init__(f"The position {position} have already been shot.")