221 lines
7.5 KiB
Python
221 lines
7.5 KiB
Python
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__)
|
|
import threading
|
|
CORS(app)
|
|
|
|
tiles = Tile.generateAll()
|
|
current_game = None # Stockage de la partie actuelle
|
|
game_lock = threading.Lock()
|
|
|
|
# ============= GET ================
|
|
@app.route('/api/tiles', methods=['GET'])
|
|
def get_all_tiles():
|
|
"""Récupère toutes les tuiles"""
|
|
tiles_data = [
|
|
{
|
|
'id': tile.id,
|
|
'family': str(tile.family),
|
|
'value': str(tile.value),
|
|
'svg': tile.get_img()
|
|
}
|
|
for tile in tiles
|
|
]
|
|
return jsonify({'tiles': tiles_data})
|
|
|
|
@app.route('/api/tiles/<int:tile_id>', methods=['GET'])
|
|
def get_tile(tile_id):
|
|
if tile_id < 0 or tile_id >= len(tiles):
|
|
return jsonify({'error': 'Tuile non trouvée'}), 404
|
|
|
|
tile = tiles[tile_id]
|
|
svg = f'<svg viewBox="0 0 500 700" width="100" height="140">{tile.get_img()}</svg>'
|
|
return jsonify({
|
|
'id': tile.id,
|
|
'family': str(tile.family),
|
|
'value': str(tile.value),
|
|
'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"""
|
|
global current_game
|
|
with game_lock:
|
|
current_game = Game()
|
|
current_game.draw_tile(current_game.hand_player)
|
|
hand_data = [
|
|
{
|
|
'id': tile.id,
|
|
'family': str(tile.family),
|
|
'value': str(tile.value),
|
|
'svg': tile.get_img()
|
|
}
|
|
for tile in current_game.hand_player.tiles
|
|
]
|
|
draw_data = {
|
|
'id': current_game.hand_player.draw.id,
|
|
'family': str(current_game.hand_player.draw.family),
|
|
'value': str(current_game.hand_player.draw.value),
|
|
'svg': current_game.hand_player.draw.get_img()
|
|
} if getattr(current_game.hand_player, 'draw', None) else None
|
|
return jsonify({'hand': hand_data, 'draw': draw_data})
|
|
|
|
@app.route('/api/discard', methods=['POST'])
|
|
def discard_tile():
|
|
"""Défausse une tuile de la main du joueur et pioche une nouvelle"""
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
data = request.json
|
|
tile_id = data.get('tile_id')
|
|
if tile_id is None:
|
|
return jsonify({'error': 'tile_id manquant'}), 400
|
|
current_game.put_tile(current_game.hand_player, tile_id)
|
|
current_game.draw_tile(current_game.hand_player)
|
|
hand_data = [
|
|
{
|
|
'id': tile.id,
|
|
'family': str(tile.family),
|
|
'value': str(tile.value),
|
|
'svg': tile.get_img()
|
|
}
|
|
for tile in current_game.hand_player.tiles
|
|
]
|
|
draw_data = {
|
|
'id': current_game.hand_player.draw.id,
|
|
'family': str(current_game.hand_player.draw.family),
|
|
'value': str(current_game.hand_player.draw.value),
|
|
'svg': current_game.hand_player.draw.get_img()
|
|
} if getattr(current_game.hand_player, 'draw', None) else None
|
|
return jsonify({'hand': hand_data, 'draw': draw_data})
|
|
|
|
# ============== POST ================
|
|
# ============== GAME MANAGEMENT ================
|
|
|
|
# Démarrer une nouvelle partie
|
|
@app.route('/api/game/start', methods=['POST'])
|
|
def start_game():
|
|
global current_game
|
|
with game_lock:
|
|
current_game = Game()
|
|
return jsonify({'status': 'started', 'state': current_game.get_state()})
|
|
|
|
# Récupérer l'état de la partie
|
|
@app.route('/api/game/state', methods=['GET'])
|
|
def game_state():
|
|
global current_game
|
|
with game_lock:
|
|
print(f"[API] /api/game/state called. current_game is {'None' if current_game is None else 'OK'}")
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
return jsonify({'state': current_game.get_state()})
|
|
|
|
# Passer au tour suivant
|
|
@app.route('/api/game/next_turn', methods=['POST'])
|
|
def game_next_turn():
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
current_game.next_turn()
|
|
return jsonify({'state': current_game.get_state()})
|
|
|
|
# Déclarer Riichi
|
|
@app.route('/api/game/riichi', methods=['POST'])
|
|
def game_declare_riichi():
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
data = request.json
|
|
player_id = data.get('player_id')
|
|
if player_id is None:
|
|
return jsonify({'error': 'player_id manquant'}), 400
|
|
current_game.declare_riichi(player_id)
|
|
return jsonify({'state': current_game.get_state()})
|
|
|
|
# Récupérer la main d'un joueur
|
|
@app.route('/api/game/hand/<int:player_id>', methods=['GET'])
|
|
def game_get_hand(player_id):
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
hand = current_game.get_hand(player_id)
|
|
return jsonify({'hand': hand})
|
|
|
|
# Récupérer les défausses d'un joueur
|
|
@app.route('/api/game/discards/<int:player_id>', methods=['GET'])
|
|
def game_get_discards(player_id):
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
discards = current_game.get_discards(player_id)
|
|
return jsonify({'discards': discards})
|
|
|
|
# Récupérer les actions possibles pour un joueur
|
|
@app.route('/api/game/actions/<int:player_id>', methods=['GET'])
|
|
def game_get_actions(player_id):
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
actions = current_game.get_possible_actions(player_id)
|
|
return jsonify({'actions': actions})
|
|
|
|
@app.route('/api/play_draw', methods=['POST'])
|
|
def play_draw_api():
|
|
global current_game
|
|
with game_lock:
|
|
print('[API] /api/play_draw called')
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
current_game.play_draw()
|
|
return jsonify({'state': current_game.get_state()})
|
|
|
|
@app.route('/api/discard_tile', methods=['POST'])
|
|
def api_discard_tile():
|
|
global current_game
|
|
with game_lock:
|
|
if current_game is None:
|
|
return jsonify({'error': 'Aucune partie en cours'}), 400
|
|
data = request.json
|
|
tile_id = data.get('tile_id')
|
|
if tile_id is None:
|
|
return jsonify({'error': 'tile_id manquant'}), 400
|
|
discarded = current_game.discard_tile(tile_id)
|
|
if not discarded:
|
|
return jsonify({'error': 'Tuile non trouvée ou non défaussée'}), 400
|
|
return jsonify({'state': current_game.get_state(), 'discarded': {
|
|
'id': discarded.id,
|
|
'family': str(discarded.family),
|
|
'value': str(discarded.value),
|
|
'svg': discarded.get_img()
|
|
}})
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True, port=5000)
|