diff --git a/api/app/Http/Controllers/GameController.php b/api/app/Http/Controllers/GameController.php index 9f1f95c..77401b4 100644 --- a/api/app/Http/Controllers/GameController.php +++ b/api/app/Http/Controllers/GameController.php @@ -59,10 +59,79 @@ class GameController extends Controller */ public function store(StoreGameRequest $request) { - $game = Game::create($request->validated()); - return response()->json($game, 201); + $validated = $request->validated(); + $user = $request->user(); + + $type = $validated['variant'] === 'bisca-3' ? '3' : '9'; + $initialState = $this->initializeGameState($type); + + $game = Game::create([ + 'type' => $type, + 'status' => 'in_progress', + 'player1_user_id' => $user->id, + 'player2_user_id' => $validated['mode'] === 'multiplayer' + ? $validated['opponent_id'] + : 1, // REPLACE 1 with your actual Bot User ID + 'began_at' => now(), + 'custom' => json_encode($initialState), + 'player1_points' => 0, + 'player2_points' => 0, + ]); + + return response()->json([ + 'message' => 'Game created successfully', + 'game_id' => $game->id, + 'game_state' => $initialState, + ], 201); } + private function initializeGameState($type) + { + $handSize = $type === 'S' ? 3 : 9; + + $suits = ['H', 'D', 'C', 'S']; + $ranks = ['2', '3', '4', '5', '6', '7', 'J', 'Q', 'K', 'A']; + + $values = [ + '2' => 0, '3' => 0, '4' => 0, '5' => 0, '6' => 0, + '7' => 10, 'J' => 3, 'Q' => 2, 'K' => 4, 'A' => 11 + ]; + + $deck = []; + foreach ($suits as $suit) { + foreach ($ranks as $rank) { + $deck[] = ['suit' => $suit, 'rank' => $rank, 'value' => $values[$rank]]; + } + } + + // Shuffle and deal + shuffle($deck); + $player1Hand = array_splice($deck, 0, $handSize); + $player2Hand = array_splice($deck, 0, $handSize); + + // Trump is the suit of the last card in the remaining stock + $trumpCard = null; + if (count($deck) > 0) { + $trumpCard = $deck[count($deck) - 1]; // Bottom card + } + + return [ + 'player1_hand' => $player1Hand, + 'player2_hand' => $player2Hand, + 'stock' => $deck, + 'trump' => $trumpCard ? $trumpCard['suit'] : null, + 'current_trick' => [], + 'current_turn' => 'player1', + 'score' => [ + 'player1' => 0, + 'player2' => 0 + ], + 'captured' => [ + 'player1' => [], + 'player2' => [] + ] + ]; + } /** * Display the specified resource. */ diff --git a/api/app/Http/Controllers/UserController.php b/api/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..3359954 --- /dev/null +++ b/api/app/Http/Controllers/UserController.php @@ -0,0 +1,11 @@ + 'required|in:bisca-3,bisca-9', + 'mode' => 'required|in:single-player,multiplayer', + 'opponent_id' => $this->mode === 'multiplayer' + ? 'required|exists:users,id' + : 'nullable', ]; } } diff --git a/api/composer.json b/api/composer.json index 5b5a9c0..bd2f68f 100644 --- a/api/composer.json +++ b/api/composer.json @@ -17,7 +17,7 @@ "require-dev": { "fakerphp/faker": "^1.23", "laravel/pail": "^1.2.2", - "laravel/pint": "^1.24", + "laravel/pint": "^1.26", "laravel/sail": "^1.48", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.6", diff --git a/api/composer.lock b/api/composer.lock index f127d15..3780ad4 100644 --- a/api/composer.lock +++ b/api/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ad8f0aa2267878e2374cd4ba4042946", + "content-hash": "353b4e6bf34bd12906db0059bb3a9207", "packages": [ { "name": "brick/math", @@ -6575,16 +6575,16 @@ }, { "name": "laravel/pint", - "version": "v1.25.1", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9" + "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9", - "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/69dcca060ecb15e4b564af63d1f642c81a241d6f", + "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f", "shasum": "" }, "require": { @@ -6595,13 +6595,13 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.87.2", - "illuminate/view": "^11.46.0", - "larastan/larastan": "^3.7.1", - "laravel-zero/framework": "^11.45.0", + "friendsofphp/php-cs-fixer": "^3.90.0", + "illuminate/view": "^12.40.1", + "larastan/larastan": "^3.8.0", + "laravel-zero/framework": "^12.0.4", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.1", - "pestphp/pest": "^2.36.0" + "nunomaduro/termwind": "^2.3.3", + "pestphp/pest": "^3.8.4" }, "bin": [ "builds/pint" @@ -6627,6 +6627,7 @@ "description": "An opinionated code formatter for PHP.", "homepage": "https://laravel.com", "keywords": [ + "dev", "format", "formatter", "lint", @@ -6637,7 +6638,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-09-19T02:57:12+00:00" + "time": "2025-11-25T21:15:52+00:00" }, { "name": "laravel/sail", @@ -9380,12 +9381,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": {}, + "platform-dev": [], "plugin-api-version": "2.6.0" } diff --git a/api/routes/api.php b/api/routes/api.php index a32a56c..fd10844 100644 --- a/api/routes/api.php +++ b/api/routes/api.php @@ -2,11 +2,12 @@ use App\Http\Controllers\AuthController; use App\Http\Controllers\GameController; +use App\Http\Controllers\UserController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; - +# Authentication Routes Route::post('/login', [AuthController::class, 'login']); Route::middleware('auth:sanctum')->group(function () { @@ -18,4 +19,10 @@ Route::middleware('auth:sanctum')->group(function () { Route::post('/register', [AuthController::class, 'register']); -Route::apiResource('games', GameController::class); \ No newline at end of file +# Game Routes - Protected +Route::middleware('auth:sanctum')->group(function () { + Route::apiResource('games', GameController::class); + Route::post('/games/{game}/resign', [GameController::class, 'resign']); + Route::post('/games/{game}/play-card', [GameController::class, 'playCard']); + Route::get('/users/{user}/matches', [UserController::class, 'getMatches']); +}); \ No newline at end of file diff --git a/frontend/src/stores/game.js b/frontend/src/stores/game.js index ae36656..61a2429 100644 --- a/frontend/src/stores/game.js +++ b/frontend/src/stores/game.js @@ -38,7 +38,7 @@ export const useGameStore = defineStore('game', () => { // Initialize deck const initializeDeck = () => { - const suits = ['♥', '♦', '♣', '♠'] + const suits = ['H', 'D', 'C', 'S'] const ranks = ['2', '3', '4', '5', '6', '7', 'J', 'Q', 'K', 'A'] const values = { '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, 'J': 2, 'Q': 3, 'K': 4, 'A': 11 }