diff --git a/backend/src/api.py b/backend/src/api.py index 052738d..ba5f1a4 100644 --- a/backend/src/api.py +++ b/backend/src/api.py @@ -2,6 +2,8 @@ from flask import Flask, jsonify, request from flask_cors import CORS from game.tile import * +from game.hand import * +from game.game import * from game.error import * app = Flask(__name__) @@ -38,6 +40,46 @@ def get_tile(tile_id): 'svg': svg }) +@app.route('/api/random_hand', methods=['GET']) +def get_random_hand(): + """Récupère une main aléatoire de 13 tuiles""" + hand = Hand.random() + hand_data = [ + { + 'id': tile.id, + 'family': str(tile.family), + 'value': str(tile.value), + 'svg': tile.get_img() + } + for tile in hand.tiles + ] + return jsonify({'hand': hand_data}) + +@app.route('/api/hand_with_draw', methods=['GET']) +def get_hand_with_draw(): + """Crée une partie et retourne le hand_player avec une tuile piochée""" + game = Game() + game.draw_tile(game.hand_player) + + hand_data = [ + { + 'id': tile.id, + 'family': str(tile.family), + 'value': str(tile.value), + 'svg': tile.get_img() + } + for tile in game.hand_player.tiles + ] + + draw_data = { + 'id': game.hand_player.draw.id, + 'family': str(game.hand_player.draw.family), + 'value': str(game.hand_player.draw.value), + 'svg': game.hand_player.draw.get_img() + } if game.hand_player.draw else None + + return jsonify({'hand': hand_data, 'draw': draw_data}) + # ============== POST ================ if __name__ == '__main__': diff --git a/backend/src/game/game.py b/backend/src/game/game.py new file mode 100644 index 0000000..a16f9a5 --- /dev/null +++ b/backend/src/game/game.py @@ -0,0 +1,19 @@ +from .hand import * +from .wall import * + +import random as rd + +class Game: + def __init__(self): + self.wall = Wall() + + self.hand_player = self.wall.draw_hand() + self.bot_hands = [self.wall.draw_hand() for _ in range(3)] + + def draw_tile(self, hand: Hand): + tile = self.wall.draw() + hand.draw_tile(tile) + + def put_tile(self, hand: Hand, id: int): + self.wall.tiles.append(hand.discard_tile(id)) + self.wall.shuffle() \ No newline at end of file diff --git a/backend/src/game/hand.py b/backend/src/game/hand.py index e69de29..af3bbce 100644 --- a/backend/src/game/hand.py +++ b/backend/src/game/hand.py @@ -0,0 +1,38 @@ +from .tile import * + +import random as rd + +class Hand: + def __init__(self, tiles: list[Tile], draw: Tile|None = None): + self.tiles: list[Tile] = tiles + self.draw: Tile|None = draw + + def sort(self) -> None: + self.tiles.sort() + + def fold(self) -> None: + if self.draw is not None: + self.tiles.append(self.draw) + self.draw = None + self.sort() + + def draw_tile(self, tile: Tile) -> None: + self.draw = tile + + def discard_tile(self, id: int) -> Tile|None: + if self.draw is not None and self.draw.id == id: + draw = self.draw + self.draw = None + return draw + for i, tile in enumerate(self.tiles): + if tile.id == id: + return self.tiles.pop(i) + return None + + @staticmethod + def random() -> Hand: + tiles = Tile.generateAll() + rd.shuffle(tiles) + hand = Hand(tiles[:13]) + hand.sort() + return hand \ No newline at end of file diff --git a/backend/src/game/tile.py b/backend/src/game/tile.py index 3a11a59..a0dd56c 100644 --- a/backend/src/game/tile.py +++ b/backend/src/game/tile.py @@ -1,6 +1,8 @@ from game.error import * from game.value import * +from functools import total_ordering +@total_ordering class Tile: def __init__(self, family, value, id): self.family = family @@ -74,7 +76,11 @@ class Tile: return self.value == other.value and self.family == other.family def __lt__(self, other: Tile): - return (self.family < other.family) or (self.family == other.family and self.value < other.value) + if self.family.value != other.family.value: + return self.family.value < other.family.value + if hasattr(self.value, 'value'): + return self.value.value < other.value.value + return self.value < other.value @staticmethod def generateAll(): diff --git a/backend/src/game/wall.py b/backend/src/game/wall.py index e69de29..e6a91c3 100644 --- a/backend/src/game/wall.py +++ b/backend/src/game/wall.py @@ -0,0 +1,22 @@ +from .tile import * +from .hand import * + +import random as rd + +class Wall: + def __init__(self): + self.tiles = Tile.generateAll() + self.shuffle() + + def shuffle(self): + rd.shuffle(self.tiles) + + def draw(self) -> Tile: + if len(self.tiles) == 0: + raise Exception("No more tiles in the wall") + return self.tiles.pop() + + def draw_hand(self) -> Hand: + hand_tiles = [self.draw() for _ in range(13)] + hand_tiles.sort() + return Hand(hand_tiles) \ No newline at end of file diff --git a/components/menu.html b/components/menu.html index 9ee01a2..b71b35a 100644 --- a/components/menu.html +++ b/components/menu.html @@ -11,7 +11,7 @@ Riichi
diff --git a/frontend/css/hand.css b/frontend/css/hand.css new file mode 100644 index 0000000..44fcaed --- /dev/null +++ b/frontend/css/hand.css @@ -0,0 +1,102 @@ +/* Hand Display Styles */ + +.hand-display { + margin-bottom: 30px; + grid-column: 1 / -1; + display: grid; + grid-template-columns: 100px 1fr; + gap: 30px; + align-items: start; +} + +.hand-label { + color: #ffffff; + margin: 0; + font-size: 1.2rem; + white-space: nowrap; +} + +.hand-tiles { + display: grid; + grid-template-columns: repeat(13, minmax(0, 1fr)); + gap: 3px; + flex: 0 0 auto; +} + +.hand-tile-item { + padding: 0; + text-align: center; + border-radius: 4px; + display: flex; + justify-content: center; + align-items: center; +} + +/* Hand container - gère l'affichage des tuiles et du draw */ +.hand-container { + display: flex; + gap: 20px; + align-items: flex-start; +} + +.hand-tile-item.draw-tile { + /* Le draw s'affiche simplement à droite grâce à flex */ + flex: 0 0 auto; +} + +/* Orientation variations */ +.hand-display.vertical { + grid-template-columns: 100px 1fr; +} + +.hand-display.horizontal { + grid-template-columns: 1fr; +} + +.hand-display.horizontal .hand-label { + grid-column: 1; + margin-bottom: 10px; +} + +.hand-display.horizontal .hand-tiles { + grid-column: 1; +} + +/* Position variations */ +.hand-display.left-label { + grid-template-columns: 100px 1fr; +} + +.hand-display.top-label { + grid-template-columns: 1fr; +} + +.hand-display.top-label .hand-label { + grid-column: 1; + margin-bottom: 10px; +} + +.hand-display.top-label .hand-tiles { + grid-column: 1; +} + +/* Tilt variations */ +.hand-display.tilt-left { + transform: rotate(90deg); + transform-origin: center; +} + +.hand-display.tilt-right { + transform: rotate(-90deg); + transform-origin: center; +} + +.hand-display.tilt-upside-down { + transform: rotate(180deg); + transform-origin: center; +} + +.hand-display.tilt-none { + transform: rotate(0deg); + transform-origin: center; +} diff --git a/frontend/js/fr/texts.js b/frontend/js/fr/texts.js index d68b5d8..d994a58 100644 --- a/frontend/js/fr/texts.js +++ b/frontend/js/fr/texts.js @@ -32,6 +32,19 @@ const texts = {