feat: add four per-verb match action handlers
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace BattleForge\Http\Handlers;
|
||||||
|
|
||||||
|
use BattleForge\Domain\CombatEngine;
|
||||||
|
use BattleForge\Domain\CombatException;
|
||||||
|
use BattleForge\Domain\Position;
|
||||||
|
use BattleForge\Http\MatchActionSupport;
|
||||||
|
use BattleForge\Http\Request;
|
||||||
|
use BattleForge\Http\Response;
|
||||||
|
|
||||||
|
final class PostMatchAbility
|
||||||
|
{
|
||||||
|
public function __construct(private readonly string $secret)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, string> $params */
|
||||||
|
public function handle(Request $request, array $params): Response
|
||||||
|
{
|
||||||
|
$support = new MatchActionSupport($this->secret);
|
||||||
|
$result = $support->verify($request);
|
||||||
|
if ($result->response !== null) {
|
||||||
|
return $result->response;
|
||||||
|
}
|
||||||
|
$matchId = $result->matchIdAndMatch['matchId'];
|
||||||
|
$match = $result->matchIdAndMatch['match'];
|
||||||
|
|
||||||
|
$payload = json_decode($request->rawBody, true);
|
||||||
|
$unitId = (string) ($payload['unitId'] ?? '');
|
||||||
|
$abilityId = (string) ($payload['abilityId'] ?? '');
|
||||||
|
$x = (int) ($payload['x'] ?? -1);
|
||||||
|
$y = (int) ($payload['y'] ?? -1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$next = (new CombatEngine())->useAbility($match, $unitId, $abilityId, new Position($x, $y));
|
||||||
|
} catch (CombatException $exception) {
|
||||||
|
return PostMatchMove::rejectionResponse($this->secret, $matchId, $match, $exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json(200, PostMatchMove::successResponse($this->secret, $matchId, $next));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace BattleForge\Http\Handlers;
|
||||||
|
|
||||||
|
use BattleForge\Domain\CombatEngine;
|
||||||
|
use BattleForge\Domain\CombatException;
|
||||||
|
use BattleForge\Http\MatchActionSupport;
|
||||||
|
use BattleForge\Http\Request;
|
||||||
|
use BattleForge\Http\Response;
|
||||||
|
|
||||||
|
final class PostMatchAttack
|
||||||
|
{
|
||||||
|
public function __construct(private readonly string $secret)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, string> $params */
|
||||||
|
public function handle(Request $request, array $params): Response
|
||||||
|
{
|
||||||
|
$support = new MatchActionSupport($this->secret);
|
||||||
|
$result = $support->verify($request);
|
||||||
|
if ($result->response !== null) {
|
||||||
|
return $result->response;
|
||||||
|
}
|
||||||
|
$matchId = $result->matchIdAndMatch['matchId'];
|
||||||
|
$match = $result->matchIdAndMatch['match'];
|
||||||
|
|
||||||
|
$payload = json_decode($request->rawBody, true);
|
||||||
|
$attackerId = (string) ($payload['attackerId'] ?? '');
|
||||||
|
$targetId = (string) ($payload['targetId'] ?? '');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$next = (new CombatEngine())->attack($match, $attackerId, $targetId);
|
||||||
|
} catch (CombatException $exception) {
|
||||||
|
return PostMatchMove::rejectionResponse($this->secret, $matchId, $match, $exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json(200, PostMatchMove::successResponse($this->secret, $matchId, $next));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace BattleForge\Http\Handlers;
|
||||||
|
|
||||||
|
use BattleForge\Domain\CombatEngine;
|
||||||
|
use BattleForge\Domain\CombatException;
|
||||||
|
use BattleForge\Http\MatchActionSupport;
|
||||||
|
use BattleForge\Http\Request;
|
||||||
|
use BattleForge\Http\Response;
|
||||||
|
|
||||||
|
final class PostMatchEndTurn
|
||||||
|
{
|
||||||
|
public function __construct(private readonly string $secret)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, string> $params */
|
||||||
|
public function handle(Request $request, array $params): Response
|
||||||
|
{
|
||||||
|
$support = new MatchActionSupport($this->secret);
|
||||||
|
$result = $support->verify($request);
|
||||||
|
if ($result->response !== null) {
|
||||||
|
return $result->response;
|
||||||
|
}
|
||||||
|
$matchId = $result->matchIdAndMatch['matchId'];
|
||||||
|
$match = $result->matchIdAndMatch['match'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$next = (new CombatEngine())->endTurn($match);
|
||||||
|
} catch (CombatException $exception) {
|
||||||
|
return PostMatchMove::rejectionResponse($this->secret, $matchId, $match, $exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json(200, PostMatchMove::successResponse($this->secret, $matchId, $next));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace BattleForge\Http\Handlers;
|
||||||
|
|
||||||
|
use BattleForge\Application\ScenarioSerializer;
|
||||||
|
use BattleForge\Application\TurnToken;
|
||||||
|
use BattleForge\Domain\CombatEngine;
|
||||||
|
use BattleForge\Domain\CombatException;
|
||||||
|
use BattleForge\Domain\Position;
|
||||||
|
use BattleForge\Http\MatchActionSupport;
|
||||||
|
use BattleForge\Http\Request;
|
||||||
|
use BattleForge\Http\Response;
|
||||||
|
|
||||||
|
final class PostMatchMove
|
||||||
|
{
|
||||||
|
public function __construct(private readonly string $secret)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, string> $params */
|
||||||
|
public function handle(Request $request, array $params): Response
|
||||||
|
{
|
||||||
|
$support = new MatchActionSupport($this->secret);
|
||||||
|
$result = $support->verify($request);
|
||||||
|
if ($result->response !== null) {
|
||||||
|
return $result->response;
|
||||||
|
}
|
||||||
|
$matchId = $result->matchIdAndMatch['matchId'];
|
||||||
|
$match = $result->matchIdAndMatch['match'];
|
||||||
|
|
||||||
|
$payload = json_decode($request->rawBody, true);
|
||||||
|
$unitId = (string) ($payload['unitId'] ?? '');
|
||||||
|
$x = (int) ($payload['x'] ?? -1);
|
||||||
|
$y = (int) ($payload['y'] ?? -1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$next = (new CombatEngine())->move($match, $unitId, new Position($x, $y));
|
||||||
|
} catch (CombatException $exception) {
|
||||||
|
return self::rejectionResponse($this->secret, $matchId, $match, $exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json(200, self::successResponse($this->secret, $matchId, $next));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return array<string, mixed> */
|
||||||
|
public static function successResponse(
|
||||||
|
string $secret,
|
||||||
|
string $matchId,
|
||||||
|
\BattleForge\Domain\MatchState $next
|
||||||
|
): array {
|
||||||
|
$turnToken = TurnToken::issue($secret, $matchId, $next->activeTeamId, $next->round, count($next->actionLog));
|
||||||
|
|
||||||
|
return [
|
||||||
|
'match' => ScenarioSerializer::matchToArray($next),
|
||||||
|
'turnToken' => $turnToken,
|
||||||
|
'winnerTeamId' => $next->winnerTeamId,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function rejectionResponse(
|
||||||
|
string $secret,
|
||||||
|
string $matchId,
|
||||||
|
\BattleForge\Domain\MatchState $match,
|
||||||
|
string $reason
|
||||||
|
): Response {
|
||||||
|
$turnToken = TurnToken::issue($secret, $matchId, $match->activeTeamId, $match->round, count($match->actionLog));
|
||||||
|
|
||||||
|
return Response::json(409, [
|
||||||
|
'error' => $reason,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'turnToken' => $turnToken,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,366 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace BattleForge\Tests\Integration;
|
||||||
|
|
||||||
|
use BattleForge\Application\ScenarioSerializer;
|
||||||
|
use BattleForge\Application\TurnToken;
|
||||||
|
use BattleForge\Domain\Archetype;
|
||||||
|
use BattleForge\Domain\Battlefield;
|
||||||
|
use BattleForge\Domain\MatchState;
|
||||||
|
use BattleForge\Domain\Position;
|
||||||
|
use BattleForge\Domain\UnitState;
|
||||||
|
use BattleForge\Http\CsrfToken;
|
||||||
|
use BattleForge\Http\Handlers\PostMatchAbility;
|
||||||
|
use BattleForge\Http\Handlers\PostMatchAttack;
|
||||||
|
use BattleForge\Http\Handlers\PostMatchEndTurn;
|
||||||
|
use BattleForge\Http\Handlers\PostMatchMove;
|
||||||
|
use BattleForge\Http\Request;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class PostMatchActionTest extends TestCase
|
||||||
|
{
|
||||||
|
private const SECRET = 'match-action-test-secret';
|
||||||
|
private const MATCH_ID = '0123456789abcdef';
|
||||||
|
private const HEAL = ['heal'];
|
||||||
|
|
||||||
|
public function testMoveHappyPathReturnsTheUpdatedMatchAndAFreshTurnToken(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchMove(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'unitId' => 'alpha-1',
|
||||||
|
'x' => 1,
|
||||||
|
'y' => 0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(200, $response->status);
|
||||||
|
$body = json_decode($response->body, true);
|
||||||
|
$posKey = $body['match']['units'][0]['position']['x'] . ':' . $body['match']['units'][0]['position']['y'];
|
||||||
|
self::assertSame('1:0', $posKey);
|
||||||
|
self::assertMatchesRegularExpression('/^[a-f0-9]{32}$/', $body['turnToken']);
|
||||||
|
self::assertNull($body['winnerTeamId']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMoveRejectsAnUnreachableDestinationAndDoesNotMutateTheMatch(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchMove(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'unitId' => 'alpha-1',
|
||||||
|
'x' => 0,
|
||||||
|
'y' => 0,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(409, $response->status);
|
||||||
|
$body = json_decode($response->body, true);
|
||||||
|
self::assertStringContainsString('not reachable', $body['error']);
|
||||||
|
$posKey = $body['match']['units'][0]['position']['x'] . ':' . $body['match']['units'][0]['position']['y'];
|
||||||
|
self::assertSame('0:0', $posKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAttackHappyPathReducesTargetHealth(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$matchArray = ScenarioSerializer::matchToArray($match);
|
||||||
|
$matchArray['units'][0]['position'] = ['x' => 6, 'y' => 7];
|
||||||
|
$match = ScenarioSerializer::matchFromArray($matchArray);
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchAttack(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'attackerId' => 'alpha-1',
|
||||||
|
'targetId' => 'bravo-1',
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(200, $response->status);
|
||||||
|
$body = json_decode($response->body, true);
|
||||||
|
$bravo = null;
|
||||||
|
foreach ($body['match']['units'] as $unit) {
|
||||||
|
if ($unit['id'] === 'bravo-1') {
|
||||||
|
$bravo = $unit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::assertNotNull($bravo);
|
||||||
|
self::assertLessThan(10, $bravo['health']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAttackRejectsAnOutOfRangeTarget(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchAttack(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'attackerId' => 'alpha-1',
|
||||||
|
'targetId' => 'bravo-1',
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(409, $response->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAbilityHappyPathHealsAnAlly(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$matchArray = ScenarioSerializer::matchToArray($match);
|
||||||
|
foreach ($matchArray['units'] as &$unit) {
|
||||||
|
if ($unit['id'] === 'alpha-3') {
|
||||||
|
$unit['archetype'] = 'support';
|
||||||
|
$unit['abilities'] = ['heal'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($unit);
|
||||||
|
foreach ($matchArray['units'] as &$unit) {
|
||||||
|
if ($unit['id'] === 'alpha-2') {
|
||||||
|
$unit['health'] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($unit);
|
||||||
|
$match = ScenarioSerializer::matchFromArray($matchArray);
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchAbility(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'unitId' => 'alpha-3',
|
||||||
|
'abilityId' => 'heal',
|
||||||
|
'x' => 0,
|
||||||
|
'y' => 1,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(200, $response->status);
|
||||||
|
$body = json_decode($response->body, true);
|
||||||
|
$healed = null;
|
||||||
|
foreach ($body['match']['units'] as $unit) {
|
||||||
|
if ($unit['id'] === 'alpha-2') {
|
||||||
|
$healed = $unit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::assertGreaterThan(2, $healed['health']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAbilityRejectsATargetOutsideRange(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$matchArray = ScenarioSerializer::matchToArray($match);
|
||||||
|
foreach ($matchArray['units'] as &$unit) {
|
||||||
|
if ($unit['id'] === 'alpha-3') {
|
||||||
|
$unit['archetype'] = 'support';
|
||||||
|
$unit['abilities'] = ['heal'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($unit);
|
||||||
|
$match = ScenarioSerializer::matchFromArray($matchArray);
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchAbility(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
'unitId' => 'alpha-3',
|
||||||
|
'abilityId' => 'heal',
|
||||||
|
'x' => 7,
|
||||||
|
'y' => 7,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(409, $response->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEndTurnHappyPathSwitchesTheActiveTeamAndIncrementsTheRoundAfterBothSides(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$token = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$response = (new PostMatchEndTurn(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $token,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(200, $response->status);
|
||||||
|
$body = json_decode($response->body, true);
|
||||||
|
self::assertSame('bravo', $body['match']['activeTeamId']);
|
||||||
|
self::assertSame(1, $body['match']['round']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEndTurnRejectsARequestWithAStaleTurnToken(): void
|
||||||
|
{
|
||||||
|
$match = $this->freshMatch();
|
||||||
|
$stale = TurnToken::issue(self::SECRET, self::MATCH_ID, 'alpha', 99, 0);
|
||||||
|
$wrongRound = TurnToken::issue(self::SECRET, self::MATCH_ID, 'alpha', 2, 0);
|
||||||
|
$good = $this->tokenFor($match);
|
||||||
|
[$csrf, $cookie] = CsrfToken::issue(self::SECRET);
|
||||||
|
|
||||||
|
$staleResponse = (new PostMatchEndTurn(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $stale,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
self::assertSame(409, $staleResponse->status);
|
||||||
|
$body = json_decode($staleResponse->body, true);
|
||||||
|
self::assertSame('turn', $body['error'] ?? null);
|
||||||
|
|
||||||
|
$wrongRoundResponse = (new PostMatchEndTurn(self::SECRET))->handle(
|
||||||
|
$this->buildRequest(
|
||||||
|
match: $match,
|
||||||
|
csrf: $csrf,
|
||||||
|
turnToken: $wrongRound,
|
||||||
|
cookies: ['__csrf' => $cookie],
|
||||||
|
body: [
|
||||||
|
'matchId' => self::MATCH_ID,
|
||||||
|
'match' => ScenarioSerializer::matchToArray($match),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
self::assertSame(409, $wrongRoundResponse->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function freshMatch(): MatchState
|
||||||
|
{
|
||||||
|
$support = new UnitState(
|
||||||
|
'alpha-3',
|
||||||
|
'alpha',
|
||||||
|
new Position(1, 1),
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
false,
|
||||||
|
Archetype::Support,
|
||||||
|
self::HEAL,
|
||||||
|
);
|
||||||
|
|
||||||
|
return new MatchState(
|
||||||
|
new Battlefield(8, 8),
|
||||||
|
[
|
||||||
|
new UnitState('alpha-1', 'alpha', new Position(0, 0), 10, 10, 3, 3, 2, 2, false, Archetype::Defender),
|
||||||
|
new UnitState('alpha-2', 'alpha', new Position(0, 1), 10, 10, 3, 3, 2, 2, false, Archetype::Defender),
|
||||||
|
$support,
|
||||||
|
new UnitState('bravo-1', 'bravo', new Position(7, 7), 10, 10, 3, 3, 2, 2, false, Archetype::Striker),
|
||||||
|
new UnitState('bravo-2', 'bravo', new Position(6, 6), 10, 10, 3, 3, 2, 2, false, Archetype::Striker),
|
||||||
|
new UnitState('bravo-3', 'bravo', new Position(5, 7), 10, 10, 3, 3, 2, 2, false, Archetype::Striker),
|
||||||
|
],
|
||||||
|
'alpha',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function tokenFor(MatchState $match): string
|
||||||
|
{
|
||||||
|
return TurnToken::issue(
|
||||||
|
self::SECRET,
|
||||||
|
self::MATCH_ID,
|
||||||
|
$match->activeTeamId,
|
||||||
|
$match->round,
|
||||||
|
count($match->actionLog),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $cookies
|
||||||
|
* @param array<string, mixed> $body
|
||||||
|
*/
|
||||||
|
private function buildRequest(
|
||||||
|
MatchState $match,
|
||||||
|
string $csrf,
|
||||||
|
string $turnToken,
|
||||||
|
array $cookies,
|
||||||
|
array $body
|
||||||
|
): Request {
|
||||||
|
return new Request([], [], [], $cookies, [
|
||||||
|
'HTTP_X_CSRF_TOKEN' => $csrf,
|
||||||
|
'HTTP_X_TURN_TOKEN' => $turnToken,
|
||||||
|
'__csrf_secret' => self::SECRET,
|
||||||
|
'CONTENT_TYPE' => 'application/json',
|
||||||
|
], '', 'POST', '/matches/current/test', 'application/json', json_encode($body, JSON_THROW_ON_ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user