Ignore malformed campaign reward labels

This commit is contained in:
2026-07-05 10:59:04 +09:00
parent d827239813
commit 1943363111
2 changed files with 27 additions and 6 deletions

View File

@@ -125,6 +125,15 @@ try {
visitResynced.firstBattleReport?.completedCampVisits.includes('repeat-visit'),
`Expected report-only camp visit completion to resync without duplicate rewards: ${JSON.stringify(visitResynced)}`
);
applyCampVisitReward('dirty-reward-visit', { itemRewards: ['', ' ', 'Bean -2', 'Bean +0', 'Bean x2'] });
const dirtyRewardVisit = getCampaignState();
assert(
dirtyRewardVisit.inventory.Bean === 7 &&
dirtyRewardVisit.inventory[''] === undefined &&
dirtyRewardVisit.inventory['Bean -'] === undefined &&
dirtyRewardVisit.completedCampVisits.includes('dirty-reward-visit'),
`Expected malformed reward labels to be ignored while valid rewards apply: ${JSON.stringify(dirtyRewardVisit)}`
);
const repeatBondId = firstScenario.bonds[0].id;
applyCampBondExp('repeat-dialogue', repeatBondId, 10);
const repeatedDialogueOnce = getCampaignState();

View File

@@ -1399,7 +1399,12 @@ function createBattleSettlement(report: FirstBattleReport, reserveTraining: Camp
function applyRewardDelta(inventory: Record<string, number>, rewards: string[], direction: 1 | -1) {
return rewards.reduce<Record<string, number>>((nextInventory, reward) => {
const { label, amount } = parseRewardLabel(reward);
const parsed = parseRewardLabel(reward);
if (!parsed) {
return nextInventory;
}
const { label, amount } = parsed;
const nextAmount = Math.max(0, (nextInventory[label] ?? 0) + amount * direction);
const cap = direction === 1 ? campaignInventoryCaps[label] : undefined;
nextInventory[label] = cap ? Math.min(nextAmount, cap) : nextAmount;
@@ -1488,16 +1493,23 @@ function advanceReserveEquipment(unit: UnitData, amount: number) {
function parseRewardLabel(reward: string) {
const normalized = reward.replace(/\s+/g, ' ').trim();
const match = normalized.match(/^(.*?)(?:\s*[+xX]?\s*(\d+))$/);
if (!normalized) {
return undefined;
}
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)
};
const amount = Number(match[3] ?? 1) * (match[2] === '-' ? -1 : 1);
const label = match[1].trim();
if (!label || !Number.isSafeInteger(amount) || amount <= 0) {
return undefined;
}
return { label, amount };
}
function cloneCampaignState(state: CampaignState): CampaignState {