From a0dcff2c2a4d5e7d5eb43ddab45590b5450e9f1c Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Sat, 25 Jul 2026 22:21:25 -0500 Subject: [PATCH] fix: round-trip match objectives through ScenarioSerializer --- src/Application/ScenarioSerializer.php | 19 +++++++++- .../Application/ScenarioSerializerTest.php | 37 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Application/ScenarioSerializer.php b/src/Application/ScenarioSerializer.php index f9c0c60..49a95dc 100644 --- a/src/Application/ScenarioSerializer.php +++ b/src/Application/ScenarioSerializer.php @@ -130,6 +130,14 @@ final class ScenarioSerializer $units[] = self::unitToArray($unit); } + $objectives = []; + foreach ($match->objectives as $id => $objective) { + $objectives[(string) $id] = [ + 'id' => $objective->id, + 'position' => self::positionToArray($objective->position), + ]; + } + return [ 'battlefield' => [ 'width' => $match->battlefield->width, @@ -141,6 +149,7 @@ final class ScenarioSerializer 'round' => $match->round, 'winnerTeamId' => $match->winnerTeamId, 'actionLog' => $match->actionLog, + 'objectives' => $objectives, 'victoryCondition' => $match->victoryCondition->value, 'holdRoundsRequired' => $match->holdRoundsRequired, 'objectiveControl' => $match->objectiveControl, @@ -166,6 +175,14 @@ final class ScenarioSerializer $units[] = self::unitFromArray($row); } + $objectives = []; + foreach (($data['objectives'] ?? []) as $id => $row) { + $objectives[(string) $id] = new ObjectiveMarker( + (string) $row['id'], + self::positionFromArray($row['position']), + ); + } + return new MatchState( battlefield: $battlefield, units: $units, @@ -173,7 +190,7 @@ final class ScenarioSerializer round: (int) $data['round'], winnerTeamId: $data['winnerTeamId'] ?? null, actionLog: array_map(static fn (mixed $entry): string => (string) $entry, $data['actionLog'] ?? []), - objectives: [], + objectives: $objectives, victoryCondition: VictoryCondition::from((string) $data['victoryCondition']), holdRoundsRequired: (int) $data['holdRoundsRequired'], objectiveControl: $data['objectiveControl'] ?? [], diff --git a/tests/Unit/Application/ScenarioSerializerTest.php b/tests/Unit/Application/ScenarioSerializerTest.php index f64b8e9..e34d11e 100644 --- a/tests/Unit/Application/ScenarioSerializerTest.php +++ b/tests/Unit/Application/ScenarioSerializerTest.php @@ -135,4 +135,41 @@ final class ScenarioSerializerTest extends TestCase // missing 'name', 'battlefield', 'units', etc. ]); } + + public function testMatchRoundTripsItsObjectives(): void + { + $battlefield = new Battlefield(10, 8); + $units = [ + new UnitState('a1', 'alpha', new Position(0, 0), 10, 10, 3, 3, 2, 2, false), + new UnitState('a2', 'alpha', new Position(1, 0), 10, 10, 3, 3, 2, 2, false), + new UnitState('a3', 'alpha', new Position(2, 0), 10, 10, 3, 3, 2, 2, false), + new UnitState('b1', 'bravo', new Position(9, 7), 10, 10, 3, 3, 2, 2, false), + new UnitState('b2', 'bravo', new Position(8, 7), 10, 10, 3, 3, 2, 2, false), + new UnitState('b3', 'bravo', new Position(7, 7), 10, 10, 3, 3, 2, 2, false), + ]; + $objective = new ObjectiveMarker('objective-1', new Position(5, 4)); + $original = new MatchState( + battlefield: $battlefield, + units: $units, + activeTeamId: 'alpha', + objectives: ['objective-1' => $objective], + victoryCondition: VictoryCondition::HoldObjective, + holdRoundsRequired: 3, + ); + + $array = ScenarioSerializer::matchToArray($original); + self::assertArrayHasKey('objectives', $array); + self::assertSame( + ['id' => 'objective-1', 'position' => ['x' => 5, 'y' => 4]], + $array['objectives']['objective-1'] ?? null, + ); + + $rebuilt = ScenarioSerializer::matchFromArray($array); + self::assertArrayHasKey('objective-1', $rebuilt->objectives); + self::assertSame('objective-1', $rebuilt->objectives['objective-1']->id); + self::assertSame(5, $rebuilt->objectives['objective-1']->position->x); + self::assertSame(4, $rebuilt->objectives['objective-1']->position->y); + self::assertSame(VictoryCondition::HoldObjective, $rebuilt->victoryCondition); + self::assertSame(3, $rebuilt->holdRoundsRequired); + } }