Validate sortie flow display fields

This commit is contained in:
2026-07-05 16:29:36 +09:00
parent 5aa80480f3
commit 14597ab17c

View File

@@ -12,9 +12,11 @@ const routedBattleSteps = extractObjectStringEntries(campaignRoutingSource, 'bat
const battleStepRules = extractCampaignBattleSteps(campaignStateSource);
const sortieFlowKeys = extractSortieFlowKeys(campaignFlowSource, battleScenarioIds);
const sortieFlowBodies = extractSortieFlowBodies(campaignFlowSource, battleScenarioIds);
const sortieFlowAfterBattleIds = extractSortieFlowAfterBattleIds(campaignFlowSource, battleScenarioIds);
const sortieFlowCampaignSteps = extractSortieFlowCampaignSteps(campaignFlowSource);
const sortieFlowNextBattleIds = extractSortieFlowNextBattleIds(campaignFlowSource, battleScenarioIds);
const campaignRewardUnlockBattleIds = extractCampaignRewardUnlockBattleIds(battlesSource, battleScenarioIds);
const sortieFlowDisplayFields = ['eyebrow', 'title', 'description', 'rewardHint'];
const failures = [];
@@ -42,6 +44,19 @@ for (const [flowKey, nextBattleId] of sortieFlowNextBattleIds.entries()) {
assert(battleIds.has(nextBattleId), `Sortie flow ${flowKey} references unknown next battle id: ${nextBattleId}`);
}
for (const flowKey of sortieFlowKeys) {
const flowBody = sortieFlowBodies.get(flowKey) ?? '';
const afterBattleId = sortieFlowAfterBattleIds.get(flowKey);
assert(afterBattleId, `Sortie flow ${flowKey} has no afterBattleId`);
if (afterBattleId) {
assert(battleIds.has(afterBattleId), `Sortie flow ${flowKey} references unknown afterBattleId: ${afterBattleId}`);
}
assert(/\bpages\s*:/.test(flowBody), `Sortie flow ${flowKey} must provide story pages`);
for (const fieldName of sortieFlowDisplayFields) {
assert(hasVisibleSortieFlowField(flowBody, fieldName), `Sortie flow ${flowKey} must provide a visible ${fieldName}`);
}
}
for (const flowKey of sortieFlowKeys) {
const nextBattleId = sortieFlowNextBattleIds.get(flowKey);
const campaignStep = sortieFlowCampaignSteps.get(flowKey);
@@ -204,6 +219,19 @@ function extractSortieFlowNextBattleIds(source, scenarioIds) {
return entries;
}
function extractSortieFlowAfterBattleIds(source, scenarioIds) {
const entries = new Map();
const scenarioEntries = extractSortieFlowProperty(source, /afterBattleId:\s*(\w+BattleScenario)\.id/);
const literalEntries = extractSortieFlowProperty(source, /afterBattleId:\s*'([^']+)'/);
for (const [flowKey, variableName] of scenarioEntries.entries()) {
entries.set(flowKey, scenarioIds.get(variableName) ?? variableName);
}
for (const [flowKey, battleId] of literalEntries.entries()) {
entries.set(flowKey, battleId);
}
return entries;
}
function extractCampaignRewardUnlockBattleIds(source, scenarioIds) {
const entries = new Map();
const declarationPattern = /export const (\w+BattleScenario)\b[\s\S]*?^\};/gm;
@@ -234,6 +262,17 @@ function extractSortieFlowProperty(source, propertyPattern) {
return entries;
}
function hasVisibleSortieFlowField(flowBody, fieldName) {
const fieldPattern = new RegExp(
`\\b${fieldName}\\s*:\\s*(?:'([^']*)'|\`([^\`]*)\`|"([^"]*)"|([A-Za-z]\\w*(?:\\.[A-Za-z]\\w*)*))`
);
const match = fieldPattern.exec(flowBody);
if (!match) {
return false;
}
return (match[1] ?? match[2] ?? match[3] ?? match[4] ?? '').trim().length > 0;
}
function extractConstObject(source, objectName) {
const startPattern = new RegExp(`const\\s+${objectName}\\b[^=]*=\\s*\\{`);
const startMatch = startPattern.exec(source);