Validate camp reward data
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"measure:performance": "node scripts/measure-performance.mjs",
|
||||
"verify:battle-data": "node scripts/verify-battle-scenario-data.mjs",
|
||||
"verify:campaign-data": "node scripts/verify-campaign-flow-data.mjs",
|
||||
"verify:camp-rewards": "node scripts/verify-camp-reward-data.mjs",
|
||||
"verify:story-assets": "node scripts/verify-story-asset-data.mjs",
|
||||
"verify:story-images": "node scripts/verify-story-image-asset-data.mjs",
|
||||
"verify:visual-assets": "node scripts/verify-visual-asset-data.mjs",
|
||||
|
||||
74
scripts/verify-camp-reward-data.mjs
Normal file
74
scripts/verify-camp-reward-data.mjs
Normal file
@@ -0,0 +1,74 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
const sourcePath = 'src/game/scenes/CampScene.ts';
|
||||
const source = readFileSync(sourcePath, 'utf8');
|
||||
const errors = [];
|
||||
|
||||
const itemRewardArrays = collectItemRewardArrays(source);
|
||||
itemRewardArrays.forEach(({ body, index, offset }) => validateItemRewards(body, index, offset));
|
||||
validateNumericProperties('gold', { min: 1, max: 20000 });
|
||||
validateNumericProperties('bondExp', { min: 0, max: 200 });
|
||||
validateNumericProperties('rewardExp', { min: 1, max: 200 });
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Camp reward data verification failed:\n${errors.map((error) => `- ${error}`).join('\n')}`);
|
||||
}
|
||||
|
||||
console.log(`Verified ${itemRewardArrays.length} camp item reward lists and camp reward numeric fields.`);
|
||||
|
||||
function collectItemRewardArrays(text) {
|
||||
return [...text.matchAll(/itemRewards:\s*\[([\s\S]*?)\]/g)].map((match, index) => ({
|
||||
body: match[1],
|
||||
index,
|
||||
offset: match.index ?? 0
|
||||
}));
|
||||
}
|
||||
|
||||
function validateItemRewards(body, index, offset) {
|
||||
const entries = [...body.matchAll(/'((?:\\'|[^'])*)'/g)].map((match) => match[1].replace(/\\'/g, "'"));
|
||||
if (entries.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const labels = new Set();
|
||||
entries.forEach((reward, rewardIndex) => {
|
||||
const parsed = parseRewardLabel(reward);
|
||||
if (!parsed.label) {
|
||||
errors.push(`${sourcePath}:${lineNumber(offset)} itemRewards[${index}][${rewardIndex}] has an empty parsed label`);
|
||||
}
|
||||
if (!Number.isInteger(parsed.amount) || parsed.amount < 1) {
|
||||
errors.push(`${sourcePath}:${lineNumber(offset)} itemRewards[${index}][${rewardIndex}] has invalid amount ${parsed.amount}`);
|
||||
}
|
||||
if (labels.has(parsed.label)) {
|
||||
errors.push(`${sourcePath}:${lineNumber(offset)} itemRewards[${index}] has duplicate label "${parsed.label}"`);
|
||||
}
|
||||
labels.add(parsed.label);
|
||||
});
|
||||
}
|
||||
|
||||
function validateNumericProperties(propertyName, { min, max }) {
|
||||
const pattern = new RegExp(`${propertyName}:\\s*(-?\\d+)`, 'g');
|
||||
for (const match of source.matchAll(pattern)) {
|
||||
const value = Number(match[1]);
|
||||
if (!Number.isInteger(value) || value < min || value > max) {
|
||||
errors.push(`${sourcePath}:${lineNumber(match.index ?? 0)} ${propertyName} has out-of-range value ${value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseRewardLabel(reward) {
|
||||
const normalized = String(reward).replace(/\s+/g, ' ').trim();
|
||||
const match = normalized.match(/^(.*?)(?:\s*[+xX]?\s*(\d+))$/);
|
||||
if (!match) {
|
||||
return { label: normalized, amount: 1 };
|
||||
}
|
||||
|
||||
return {
|
||||
label: match[1].trim() || normalized,
|
||||
amount: Number(match[2] ?? 1)
|
||||
};
|
||||
}
|
||||
|
||||
function lineNumber(offset) {
|
||||
return source.slice(0, offset).split(/\r?\n/).length;
|
||||
}
|
||||
@@ -11,6 +11,7 @@ let browser;
|
||||
try {
|
||||
runCommand('node', ['scripts/verify-campaign-flow-data.mjs']);
|
||||
runCommand('node', ['scripts/verify-battle-scenario-data.mjs']);
|
||||
runCommand('node', ['scripts/verify-camp-reward-data.mjs']);
|
||||
runCommand('node', ['scripts/verify-story-asset-data.mjs']);
|
||||
runCommand('node', ['scripts/verify-story-image-asset-data.mjs']);
|
||||
runCommand('node', ['scripts/verify-visual-asset-data.mjs']);
|
||||
|
||||
Reference in New Issue
Block a user