test(compare): trace monthly pre-update boundary

This commit is contained in:
2026-07-25 21:36:26 +00:00
parent 312d20269c
commit 5a51ad5699
2 changed files with 98 additions and 3 deletions
@@ -0,0 +1,49 @@
{
"action": "PreUpdateMonthly",
"environment": {
"year": 200,
"month": 12,
"startyear": 190
},
"setup": {
"syncEnvironment": true,
"resetGenerals": true,
"deleteOtherGenerals": true,
"keepGeneralIds": [1, 2],
"general": [
{"id": 1, "values": {"makelimit": 2}},
{"id": 2, "values": {"makelimit": 0}}
],
"generalAccessLog": [
{"generalId": 1, "refreshScoreTotal": 101},
{"generalId": 2, "refreshScoreTotal": 1}
],
"nation": [
{
"id": 1,
"values": {
"rate": 35,
"rate_tmp": 10,
"strategic_cmd_limit": 2,
"surlimit": 1,
"spy": "{\"1\":1,\"2\":2}"
}
}
],
"city": [
{"id": 1, "values": {"state": 31, "term": 1, "conflict": {"1": 10}}},
{"id": 2, "values": {"state": 32, "term": 2, "conflict": {"1": 20}}},
{"id": 3, "values": {"state": 33, "term": 0, "conflict": {"1": 30}}},
{"id": 4, "values": {"state": 34, "term": 3, "conflict": {"1": 40}}},
{"id": 5, "values": {"state": 41, "term": 1, "conflict": {"1": 50}}},
{"id": 6, "values": {"state": 42, "term": 2, "conflict": {"1": 60}}},
{"id": 7, "values": {"state": 43, "term": 3, "conflict": {"1": 70}}}
]
},
"observe": {
"generalIds": [1, 2],
"nationIds": [1],
"cityIds": [1, 2, 3, 4, 5, 6, 7],
"accessGeneralIds": [1, 2]
}
}
+49 -3
View File
@@ -34,6 +34,7 @@ function comparisonMonthlyPatch(string $table, int $id, array $values): void
'allowed' => [ 'allowed' => [
'name', 'color', 'capital', 'gennum', 'gold', 'rice', 'tech', 'name', 'color', 'capital', 'gennum', 'gold', 'rice', 'tech',
'power', 'level', 'type', 'rate_tmp', 'scout', 'aux', 'power', 'level', 'type', 'rate_tmp', 'scout', 'aux',
'rate', 'strategic_cmd_limit', 'surlimit', 'spy',
], ],
], ],
'general' => [ 'general' => [
@@ -45,7 +46,7 @@ function comparisonMonthlyPatch(string $table, int $id, array $values): void
'leadership', 'strength', 'intel', 'experience', 'dedication', 'leadership', 'strength', 'intel', 'experience', 'dedication',
'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'personal', 'special', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'personal', 'special',
'specage', 'special2', 'specage2', 'betray', 'age', 'specage', 'special2', 'specage2', 'betray', 'age',
'bornyear', 'deadyear', 'turntime', 'bornyear', 'deadyear', 'turntime', 'makelimit',
], ],
], ],
]; ];
@@ -108,6 +109,7 @@ function comparisonMonthlyDetails(array $observe, int $worldHistoryAfterId): arr
'specialWar' => 'special2', 'specialWar' => 'special2',
'specAge2' => 'specage2', 'specAge2' => 'specage2',
'betray' => 'betray', 'betray' => 'betray',
'makeLimit' => 'makelimit',
'horse' => 'horse', 'horse' => 'horse',
'weapon' => 'weapon', 'weapon' => 'weapon',
'book' => 'book', 'book' => 'book',
@@ -129,6 +131,7 @@ function comparisonMonthlyDetails(array $observe, int $worldHistoryAfterId): arr
[ [
'id' => 'city', 'id' => 'city',
'nationId' => 'nation', 'nationId' => 'nation',
'state' => 'state',
'supplyState' => 'supply', 'supplyState' => 'supply',
'frontState' => 'front', 'frontState' => 'front',
'officerSet' => 'officer_set', 'officerSet' => 'officer_set',
@@ -162,9 +165,14 @@ function comparisonMonthlyDetails(array $observe, int $worldHistoryAfterId): arr
'gold' => 'gold', 'gold' => 'gold',
'rice' => 'rice', 'rice' => 'rice',
'rate' => 'rate_tmp', 'rate' => 'rate_tmp',
'baseRate' => 'rate',
'typeCode' => 'type', 'typeCode' => 'type',
'scout' => 'scout', 'scout' => 'scout',
'strategicCommandLimit' => 'strategic_cmd_limit',
'surrenderLimit' => 'surlimit',
'spy' => 'spy',
], ],
['spy'],
), ),
comparisonRowsById('nation', 'nation', comparisonIntegerList($observe['nationIds'] ?? [], 'nationIds')), comparisonRowsById('nation', 'nation', comparisonIntegerList($observe['nationIds'] ?? [], 'nationIds')),
); );
@@ -213,6 +221,14 @@ function comparisonMonthlyDetails(array $observe, int $worldHistoryAfterId): arr
$rankGeneralIds, $rankGeneralIds,
$rankTypes, $rankTypes,
)); ));
$generalAccessLogs = [];
$accessGeneralIds = comparisonIntegerList($observe['accessGeneralIds'] ?? [], 'accessGeneralIds');
if ($accessGeneralIds) {
$generalAccessLogs = iterator_to_array($db->query(
'SELECT general_id AS generalId, refresh_score_total AS refreshScoreTotal FROM general_access_log WHERE general_id IN %li ORDER BY general_id',
$accessGeneralIds,
));
}
return [ return [
'generals' => $generals, 'generals' => $generals,
'cities' => $cities, 'cities' => $cities,
@@ -220,6 +236,7 @@ function comparisonMonthlyDetails(array $observe, int $worldHistoryAfterId): arr
'worldHistory' => $worldHistory, 'worldHistory' => $worldHistory,
'inheritancePoints' => $inheritancePoints, 'inheritancePoints' => $inheritancePoints,
'rankData' => $rankData, 'rankData' => $rankData,
'generalAccessLogs' => $generalAccessLogs,
]; ];
} }
@@ -255,6 +272,7 @@ function comparisonMonthlyEventTraceMain(): void
'AddGlobalBetray', 'AddGlobalBetray',
'LostUniqueItem', 'LostUniqueItem',
'MergeInheritPointRank', 'MergeInheritPointRank',
'PreUpdateMonthly',
]; ];
if (!in_array($actionName, $supportedActions, true)) { if (!in_array($actionName, $supportedActions, true)) {
throw new \InvalidArgumentException('unsupported monthly action'); throw new \InvalidArgumentException('unsupported monthly action');
@@ -407,6 +425,21 @@ function comparisonMonthlyEventTraceMain(): void
'value' => $row['value'], 'value' => $row['value'],
]); ]);
} }
foreach ($setup['generalAccessLog'] ?? [] as $row) {
if (
!is_array($row)
|| !is_int($row['generalId'] ?? null)
|| !is_int($row['refreshScoreTotal'] ?? null)
) {
throw new \InvalidArgumentException('invalid setup.generalAccessLog row');
}
DB::db()->insertUpdate('general_access_log', [
'general_id' => $row['generalId'],
'refresh_score_total' => $row['refreshScoreTotal'],
], [
'refresh_score_total' => $row['refreshScoreTotal'],
]);
}
if (($setup['resetDiplomacy'] ?? false) === true) { if (($setup['resetDiplomacy'] ?? false) === true) {
DB::db()->query('DELETE FROM diplomacy'); DB::db()->query('DELETE FROM diplomacy');
} }
@@ -497,7 +530,9 @@ function comparisonMonthlyEventTraceMain(): void
} }
$actionClass = "\\sammo\\Event\\Action\\{$actionName}"; $actionClass = "\\sammo\\Event\\Action\\{$actionName}";
if ($actionName === 'ProcessSemiAnnual') { if ($actionName === 'PreUpdateMonthly') {
$action = null;
} elseif ($actionName === 'ProcessSemiAnnual') {
$resource = $request['resource'] ?? null; $resource = $request['resource'] ?? null;
if (!is_string($resource)) { if (!is_string($resource)) {
throw new \InvalidArgumentException('ProcessSemiAnnual requires resource'); throw new \InvalidArgumentException('ProcessSemiAnnual requires resource');
@@ -581,7 +616,13 @@ function comparisonMonthlyEventTraceMain(): void
'fiction' => $fiction, 'fiction' => $fiction,
]; ];
} }
$action->run($actionEnvironment); if ($actionName === 'PreUpdateMonthly') {
if (!preUpdateMonthly()) {
throw new \RuntimeException('preUpdateMonthly failed');
}
} else {
$action->run($actionEnvironment);
}
unset($action); unset($action);
gc_collect_cycles(); gc_collect_cycles();
@@ -713,6 +754,11 @@ function comparisonMonthlyEventTraceMain(): void
'lastNPCTroopLeaderID', 'lastNPCTroopLeaderID',
]); ]);
} }
if ($actionName === 'PreUpdateMonthly') {
$response['gameEnvironment'] = KVStorage::getStorage(DB::db(), 'game_env')->getValues([
'develcost',
]);
}
if (in_array($actionName, ['OpenNationBetting', 'FinishNationBetting'], true)) { if (in_array($actionName, ['OpenNationBetting', 'FinishNationBetting'], true)) {
$bettingStorage = KVStorage::getStorage(DB::db(), 'betting'); $bettingStorage = KVStorage::getStorage(DB::db(), 'betting');
$response['betting'] = $bettingStorage->getAll(); $response['betting'] = $bettingStorage->getAll();