Skip to content

Commit

Permalink
Improve responses payload (#42)
Browse files Browse the repository at this point in the history
* Deal with shitty php enum and related tools
* Refactor RestStartGame
  • Loading branch information
NolwennD authored Jan 11, 2023
1 parent faa98b3 commit 7b9868f
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 45 deletions.
43 changes: 37 additions & 6 deletions qvgds-back/app/Http/Controllers/DTO/RestGame.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,57 @@
*/
private function __construct(
#[OA\Property]
public string $id,
private string $id,

#[OA\Property]
public string $player,
private string $player,

#[OA\Property]
public int $step,
private int $step,

#[OA\Property]
public int $shitcoins,
private int $shitcoins,

#[OA\Property]
public GameStatus $status,
private GameStatus $status,

#[OA\Property(items: new OA\Items(type: RestJoker::class))]
public array $jokers
private array $jokers
)
{
}

public function getId(): string
{
return $this->id;
}

public function getPlayer(): string
{
return $this->player;
}

public function getStep(): int
{
return $this->step;
}

public function getShitcoins(): int
{
return $this->shitcoins;
}

public function getStatus(): string
{
return $this->status->name;
}

public function getJokers(): array
{
return $this->jokers;
}


public static function from(Game $game): self
{
return new self(
Expand Down
8 changes: 8 additions & 0 deletions qvgds-back/app/Http/Controllers/DTO/RestStartGame.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

use OpenApi\Attributes\Property;
use OpenApi\Attributes\Schema;
use QVGDS\Game\Domain\GameId;
use QVGDS\Game\Domain\GameStart;
use QVGDS\Session\Domain\SessionId;

#[Schema(
title: "Game start",
Expand All @@ -20,4 +23,9 @@ public function __construct(
)
{
}

public function toDomain(): GameStart
{
return new GameStart(GameId::newId(), SessionId::from($this->session), $this->player);
}
}
31 changes: 3 additions & 28 deletions qvgds-back/app/Http/Controllers/GamesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use QVGDS\Game\Service\GamesManager;
use QVGDS\Session\Domain\Question\Answer;
use QVGDS\Session\Domain\Question\Question;
use QVGDS\Session\Domain\SessionId;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -59,11 +58,7 @@ public function start(Request $request): Response
/** @var RestStartGame $restStartGame */
$restStartGame = $this->serializer->deserialize($request->getContent(), RestStartGame::class, "json");

$game = $this->games->start(
GameId::newId(),
new SessionId(Uuid::fromString($restStartGame->session)),
$restStartGame->player
);
$game = $this->games->start($restStartGame->toDomain());

return new JsonResponse(
$this->serializer->normalize(RestGame::from($game))
Expand Down Expand Up @@ -100,7 +95,7 @@ public function list(): Response
{
$games = $this->games->list();
$json = array_map(
fn(Game $game): array => $this->serializeWithQuestions($game),
fn(Game $game): array => $this->serializer->normalize(RestGame::from($game)),
$games
);
return new JsonResponse($json);
Expand Down Expand Up @@ -133,7 +128,7 @@ public function guess(Request $request, string $gameId): Response
[
"shitcoins" => $gameOrFail->game->shitCoins()->amount(),
"goodAnswer" => $gameOrFail->game->currentQuestion()->goodAnswer()->text,
"gameStatus" => $gameOrFail->game->status()->value
"gameStatus" => $gameOrFail->game->status()->name
],
Response::HTTP_BAD_REQUEST
);
Expand All @@ -149,25 +144,6 @@ public function fiftyFifty(string $gameId): Response
return new JsonResponse(["badAnswers" => $json]);
}

/**
* @return array<string, mixed>
*/
private function serializeWithQuestions(Game $game): array
{
return [
"id" => $game->id()->get(),
"player" => $game->player(),
"step" => $game->step(),
"status" => $game->status(),
"questions" => [
array_map(
fn(Question $q): array => ["question" => $q->text(), "answers" => $this->serializeAnswers($q)],
$game->session()->questions()
)
]
];
}

public function jokers(string $gameId): Response
{
$game = $this->getGame($gameId);
Expand All @@ -194,5 +170,4 @@ private function serializeAnswers(Question $question): array

return array_map(fn(Answer $a): array => ["answer" => $a->text], $answers);
}

}
11 changes: 10 additions & 1 deletion qvgds-back/app/Repositories/LaravelGamesRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private function toDomain(LaravelGame $laravelGame): Game
$laravelGame->player,
new Jokers(...$laravelGame->jokers()->get()->map(fn(LaravelJoker $joker) => $this->buildJoker($joker))->toArray()),
$laravelGame->session()->get()->map(fn(LaravelSession $session): Session => LaravelSessionsRepository::toDomain($session))->first(),
GameStatus::from($laravelGame->status),
$this->buildGameStatus($laravelGame->status),
$laravelGame->step
);
}
Expand All @@ -103,4 +103,13 @@ private function match(string $status): JokerStatus
JokerStatus::ALREADY_USED->name => JokerStatus::ALREADY_USED,
};
}

private function buildGameStatus(string $status): GameStatus
{
return match ($status) {
GameStatus::IN_PROGRESS->name => GameStatus::IN_PROGRESS,
GameStatus::LOST->name => GameStatus::LOST,
GameStatus::FORGIVEN->name => GameStatus::FORGIVEN,
};
}
}
14 changes: 14 additions & 0 deletions qvgds-back/src/Game/Domain/GameStart.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);

namespace QVGDS\Game\Domain;

use QVGDS\Session\Domain\SessionId;

final readonly class GameStart
{

public function __construct(public GameId $gameId, public SessionId $sessionId, public string $player)
{
}
}
8 changes: 4 additions & 4 deletions qvgds-back/src/Game/Domain/GameStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
use OpenApi\Attributes\Schema;

#[Schema(title: "Game status")]
enum GameStatus: string
enum GameStatus
{
case LOST = "LOST";
case FORGIVEN = "FORGIVEN";
case IN_PROGRESS = "IN_PROGRESS";
case LOST;
case FORGIVEN;
case IN_PROGRESS;
}
8 changes: 4 additions & 4 deletions qvgds-back/src/Game/Service/GamesManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use QVGDS\Game\Domain\Game;
use QVGDS\Game\Domain\GameId;
use QVGDS\Game\Domain\GamesRepository;
use QVGDS\Game\Domain\GameStart;
use QVGDS\Game\Domain\UnknownGameException;
use QVGDS\Session\Domain\Question\Answer;
use QVGDS\Session\Domain\Question\Question;
use QVGDS\Session\Domain\SessionId;
use QVGDS\Session\Domain\SessionNotFoundException;
use QVGDS\Session\Domain\SessionsRepository;

Expand All @@ -20,14 +20,14 @@ public function __construct(private readonly GamesRepository $games, private rea
{
}

public function start(GameId $id, SessionId $sessionId, string $player): Game
public function start(GameStart $gameStart): Game
{
$session = $this->sessions->get($sessionId);
$session = $this->sessions->get($gameStart->sessionId);
if ($session === null) {
throw new SessionNotFoundException();
}

$game = Game::start($id, $player, $session);
$game = Game::start($gameStart->gameId, $gameStart->player, $session);

$this->games->save($game);

Expand Down
36 changes: 36 additions & 0 deletions qvgds-back/tests/App/Http/Controllers/DTO/RestGameTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Http\Controllers\DTO;

use PHPUnit\Framework\TestCase;
use QVGDS\Tests\Game\GameFixtures;
use QVGDS\Tests\Json\JsonHelper;

class RestGameTest extends TestCase
{
/**
* @test
*/
public function shouldSerializeToJson(): void
{
$json = JsonHelper::writeAsJson(RestGame::from(GameFixtures::newGame()));

self::assertEquals($this->json(), $json);
}

private function json(): string
{
return
'{"id":"7cb03186-5430-45c2-9bdb-d5993a4ad209",'
. '"player":"Toto",'
. '"step":1,'
. '"shitcoins":0,'
. '"status":"IN_PROGRESS",'
. '"jokers":['
. '{"type":"FIFTY_FIFTY","status":"AVAILABLE"},'
. '{"type":"CALL_A_FRIEND","status":"AVAILABLE"},'
. '{"type":"AUDIENCE_HELP","status":"AVAILABLE"}]'
. '}';
}

}
36 changes: 36 additions & 0 deletions qvgds-back/tests/App/Http/Controllers/DTO/RestStartGameTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use App\Http\Controllers\DTO\RestStartGame;
use PHPUnit\Framework\TestCase;
use QVGDS\Game\Domain\GameId;
use QVGDS\Session\Domain\SessionId;
use QVGDS\Tests\Json\JsonHelper;

class RestStartGameTest extends TestCase
{
/**
* @test
*/
public function shouldDeserializeFromJson(): void
{
/** @var RestStartGame $restStartGame */
$restStartGame = JsonHelper::readFromJson($this->json(), RestStartGame::class);

$gameStart = $restStartGame->toDomain();

self::assertEquals($gameStart->player, "toto");
self::assertEquals($gameStart->sessionId, SessionId::from("b72ff86d-20fc-47f6-bbce-cd931a1a925d"));
self::assertInstanceOf(GameId::class, $gameStart->gameId);
}

private function json(): string
{
return <<<'JSON'
{
"player": "toto",
"session": "b72ff86d-20fc-47f6-bbce-cd931a1a925d"
}
JSON;

}
}
6 changes: 6 additions & 0 deletions qvgds-back/tests/Game/GameFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use QVGDS\Game\Domain\Game;
use QVGDS\Game\Domain\GameId;
use QVGDS\Game\Domain\GameStart;
use QVGDS\Tests\Session\SessionFixtures;
use Ramsey\Uuid\Uuid;

Expand All @@ -24,4 +25,9 @@ public static function player(): string
{
return "Toto";
}

public static function gameStart(): GameStart
{
return new GameStart(self::gameId(), SessionFixtures::sessionId(), self::player());
}
}
4 changes: 2 additions & 2 deletions qvgds-back/tests/Game/Service/GamesManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected function setUp(): void
public function shouldNotStartAGameWithUnknownSession(): void
{
$this->expectException(SessionNotFoundException::class);
$this->service->start(GameId::newId(), SessionFixtures::sessionId(), "Toto");
$this->service->start(GameFixtures::gameStart());
}

/**
Expand Down Expand Up @@ -128,6 +128,6 @@ public function shouldForgiveAGame(): void
private function prepareGame(): void
{
$this->sessions->save(SessionFixtures::sessionWithQuestions());
$this->service->start(GameFixtures::gameId(), SessionFixtures::sessionId(), "Toto");
$this->service->start(GameFixtures::gameStart());
}
}
36 changes: 36 additions & 0 deletions qvgds-back/tests/Json/JsonHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);

namespace QVGDS\Tests\Json;

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;

final class JsonHelper
{
public static function writeAsJson(object $from): string
{
return self::serializer()->serialize($from, "json");
}

/**
* @template T of object
* @param class-string<T> $className
* @return T
*/
public static function readFromJson(string $payload, string $className): object
{
return self::serializer()->deserialize($payload, $className, "json");
}

private static function serializer(): SerializerInterface
{
$encoders = [new JsonEncoder()];
$normalizers = [new GetSetMethodNormalizer(), new PropertyNormalizer()];

return new Serializer($normalizers, $encoders);
}
}

0 comments on commit 7b9868f

Please sign in to comment.