From 39b209caf0249eceb14bb5e878bf096af0fd93f1 Mon Sep 17 00:00:00 2001 From: hided62 Date: Sat, 25 Jul 2026 18:15:27 +0000 Subject: [PATCH] test(compare): trace CreateManyNPC monthly action --- .../fixtures/monthly_create_many_npc.json | 15 +++ hwe/compare/monthly_event_trace.php | 102 ++++++++++++++++-- 2 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 hwe/compare/fixtures/monthly_create_many_npc.json diff --git a/hwe/compare/fixtures/monthly_create_many_npc.json b/hwe/compare/fixtures/monthly_create_many_npc.json new file mode 100644 index 00000000..b8b61c1a --- /dev/null +++ b/hwe/compare/fixtures/monthly_create_many_npc.json @@ -0,0 +1,15 @@ +{ + "action": "CreateManyNPC", + "args": [2, 0], + "environment": { + "year": 193, + "month": 5, + "startyear": 190, + "turnterm": 10, + "turntime": "0193-05-01 00:00:00" + }, + "setup": { + "resetGenerals": true + }, + "observe": {} +} diff --git a/hwe/compare/monthly_event_trace.php b/hwe/compare/monthly_event_trace.php index 7ed323bb..b4051d9d 100644 --- a/hwe/compare/monthly_event_trace.php +++ b/hwe/compare/monthly_event_trace.php @@ -185,6 +185,7 @@ function comparisonMonthlyEventTraceMain(): void 'ProcessSemiAnnual', 'ProcessWarIncome', 'CreateAdminNPC', + 'CreateManyNPC', ]; if (!in_array($actionName, $supportedActions, true)) { throw new \InvalidArgumentException('unsupported monthly action'); @@ -235,6 +236,8 @@ function comparisonMonthlyEventTraceMain(): void } $db = DB::db(); + $generalIdBeforeAction = + (int)($db->queryFirstField('SELECT COALESCE(MAX(no), 0) FROM general') ?? 0); $snapshotRequest = ['observe' => $request['observe'] ?? []]; $snapshotRequest['observe']['logAfterId'] = (int)($db->queryFirstField('SELECT COALESCE(MAX(id), 0) FROM general_record') ?? 0); @@ -273,6 +276,12 @@ function comparisonMonthlyEventTraceMain(): void throw new \InvalidArgumentException('ProcessSemiAnnual requires resource'); } $action = new $actionClass($resource); + } elseif ($actionName === 'CreateManyNPC') { + $args = $request['args'] ?? []; + if (!is_array($args) || count($args) > 2) { + throw new \InvalidArgumentException('CreateManyNPC args must be an array with at most two entries'); + } + $action = new $actionClass(...$args); } else { $action = new $actionClass(); } @@ -290,22 +299,97 @@ function comparisonMonthlyEventTraceMain(): void $actionEnvironment['killturn'] = $killturn; $actionEnvironment['turnterm'] = $turnterm; } + if ($actionName === 'CreateManyNPC') { + $turnterm = $environment['turnterm'] ?? null; + $turntime = $environment['turntime'] ?? null; + if (!is_int($turnterm) || $turnterm <= 0 || !is_string($turntime)) { + throw new \InvalidArgumentException('CreateManyNPC requires positive turnterm and string turntime'); + } + $actionEnvironment += [ + 'turnterm' => $turnterm, + 'turntime' => $turntime, + 'show_img_level' => 3, + 'stored_icons' => [], + 'icon_path' => '.', + 'fiction' => [0], + ]; + } $action->run($actionEnvironment); unset($action); gc_collect_cycles(); $after = comparisonTurnStateSnapshot($snapshotRequest); $afterDetails = comparisonMonthlyDetails($snapshotRequest['observe'], $worldHistoryAfterId); + $createdGenerals = []; + if ($actionName === 'CreateManyNPC') { + foreach ($db->query('SELECT * FROM general WHERE no > %i ORDER BY no', $generalIdBeforeAction) as $row) { + $generalId = (int)$row['no']; + $turnRows = $db->query( + 'SELECT turn_idx, action, arg FROM general_turn WHERE general_id = %i ORDER BY turn_idx', + $generalId, + ); + $createdGenerals[] = comparisonPickRow( + $row, + [ + 'id' => 'no', + 'name' => 'name', + 'nationId' => 'nation', + 'cityId' => 'city', + 'leadership' => 'leadership', + 'strength' => 'strength', + 'intelligence' => 'intel', + 'experience' => 'experience', + 'dedication' => 'dedication', + 'officerLevel' => 'officer_level', + 'gold' => 'gold', + 'rice' => 'rice', + 'crew' => 'crew', + 'crewTypeId' => 'crewtype', + 'train' => 'train', + 'atmos' => 'atmos', + 'turnTime' => 'turntime', + 'killturn' => 'killturn', + 'age' => 'age', + 'npcState' => 'npc', + 'npcOriginalState' => 'npc_org', + 'affinity' => 'affinity', + 'personality' => 'personal', + 'specialDomestic' => 'special', + 'specialWar' => 'special2', + 'specAge' => 'specage', + 'specAge2' => 'specage2', + 'bornYear' => 'bornyear', + 'deadYear' => 'deadyear', + 'picture' => 'picture', + ], + ) + [ + 'turnCount' => count($turnRows), + 'turnActions' => array_values(array_unique(array_column($turnRows, 'action'))), + 'rankCount' => (int)$db->queryFirstField( + 'SELECT count(*) FROM rank_data WHERE general_id = %i', + $generalId, + ), + 'nonZeroRankCount' => (int)$db->queryFirstField( + 'SELECT count(*) FROM rank_data WHERE general_id = %i AND value != 0', + $generalId, + ), + ]; + } + } + $response = [ + 'schemaVersion' => 1, + 'engine' => 'ref', + 'action' => $actionName, + 'before' => $before, + 'beforeDetails' => $beforeDetails, + 'after' => $after, + 'afterDetails' => $afterDetails, + ]; + if ($actionName === 'CreateManyNPC') { + $response['createdGenerals'] = $createdGenerals; + } echo json_encode( - [ - 'schemaVersion' => 1, - 'engine' => 'ref', - 'action' => $actionName, - 'before' => $before, - 'beforeDetails' => $beforeDetails, - 'after' => $after, - 'afterDetails' => $afterDetails, - ], + $response, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION, ), PHP_EOL; } catch (\Throwable $throwable) {