Filter invalid campaign reward recruits

This commit is contained in:
2026-07-05 14:29:52 +09:00
parent 16cbcf2c9a
commit 0950f458a8
2 changed files with 27 additions and 8 deletions

View File

@@ -650,6 +650,7 @@ try {
recruits: [ recruits: [
{ unitId: ' guan-yu ', name: ' Guan Yu ' }, { unitId: ' guan-yu ', name: ' Guan Yu ' },
{ unitId: 'guan-yu', name: 'Duplicate Guan Yu' }, { unitId: 'guan-yu', name: 'Duplicate Guan Yu' },
{ unitId: 'ghost-recruit', name: 'Ghost Recruit' },
{ unitId: '', name: 'Broken' }, { unitId: '', name: 'Broken' },
...Array.from({ length: 140 }, (_, index) => ({ unitId: `recruit-${index}`, name: `Recruit ${index}` })) ...Array.from({ length: 140 }, (_, index) => ({ unitId: `recruit-${index}`, name: `Recruit ${index}` }))
], ],
@@ -691,7 +692,7 @@ try {
malformedReport.firstBattleReport.campaignRewards?.supplies[0] === 'Bean' && malformedReport.firstBattleReport.campaignRewards?.supplies[0] === 'Bean' &&
malformedReport.firstBattleReport.campaignRewards?.equipment.length === 1 && malformedReport.firstBattleReport.campaignRewards?.equipment.length === 1 &&
malformedReport.firstBattleReport.campaignRewards?.reputation.length === 1 && malformedReport.firstBattleReport.campaignRewards?.reputation.length === 1 &&
malformedReport.firstBattleReport.campaignRewards?.recruits.length === 128 && malformedReport.firstBattleReport.campaignRewards?.recruits.length === 1 &&
malformedReport.firstBattleReport.campaignRewards?.recruits[0].unitId === 'guan-yu' && malformedReport.firstBattleReport.campaignRewards?.recruits[0].unitId === 'guan-yu' &&
malformedReport.firstBattleReport.campaignRewards?.recruits[0].name === 'Guan Yu' && malformedReport.firstBattleReport.campaignRewards?.recruits[0].name === 'Guan Yu' &&
malformedReport.firstBattleReport.campaignRewards?.recruits.filter((recruit) => recruit.unitId === 'guan-yu').length === 1 && malformedReport.firstBattleReport.campaignRewards?.recruits.filter((recruit) => recruit.unitId === 'guan-yu').length === 1 &&
@@ -757,7 +758,11 @@ try {
supplies: { corrupted: true }, supplies: { corrupted: true },
equipment: ['Iron Sword'], equipment: ['Iron Sword'],
reputation: 'Fame', reputation: 'Fame',
recruits: [{ unitId: 'test-recruit', name: 'Test Recruit' }, { broken: true }], recruits: [
{ unitId: 'test-recruit', name: 'Test Recruit' },
{ unitId: ' guan-yu ', name: ' Guan Yu ' },
{ broken: true }
],
unlocks: [ unlocks: [
{ battleId: 'ghost-battle', title: 'Ghost Battle' }, { battleId: 'ghost-battle', title: 'Ghost Battle' },
{ battleId: 'second-battle-yellow-turban-pursuit', title: 'Next Pursuit' } { battleId: 'second-battle-yellow-turban-pursuit', title: 'Next Pursuit' }
@@ -883,6 +888,7 @@ try {
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.itemRewards.length === 1 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.itemRewards.length === 1 &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.equipment[0] === 'Iron Sword' && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.equipment[0] === 'Iron Sword' &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.recruits.length === 1 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.recruits.length === 1 &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.recruits[0].unitId === 'guan-yu' &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.unlocks.length === 1 && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.unlocks.length === 1 &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.unlocks[0].battleId === 'second-battle-yellow-turban-pursuit' && malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.unlocks[0].battleId === 'second-battle-yellow-turban-pursuit' &&
malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.note === undefined, malformedHistory.battleHistory['first-battle-zhuo-commandery']?.campaignRewards?.note === undefined,

View File

@@ -1084,7 +1084,7 @@ function normalizeCampaignBattleSettlement(value: unknown): CampaignBattleSettle
outcome: settlement.outcome, outcome: settlement.outcome,
rewardGold: normalizeNonNegativeInteger(settlement.rewardGold), rewardGold: normalizeNonNegativeInteger(settlement.rewardGold),
itemRewards: uniqueStrings(settlement.itemRewards), itemRewards: uniqueStrings(settlement.itemRewards),
campaignRewards: cloneCampaignRewardSnapshot(settlement.campaignRewards), campaignRewards: cloneCampaignRewardSnapshot(settlement.campaignRewards, battleId),
objectives: normalizeLimitedArray(settlement.objectives, normalizeBattleObjectiveSnapshot, maxCampaignBattleObjectiveEntries), objectives: normalizeLimitedArray(settlement.objectives, normalizeBattleObjectiveSnapshot, maxCampaignBattleObjectiveEntries),
units: normalizeLimitedArray(settlement.units, normalizeCampaignUnitProgressSnapshot, maxCampaignBattleUnitEntries), units: normalizeLimitedArray(settlement.units, normalizeCampaignUnitProgressSnapshot, maxCampaignBattleUnitEntries),
bonds: normalizeLimitedArray(settlement.bonds, normalizeCampaignBondProgressSnapshot, maxCampaignBattleBondEntries), bonds: normalizeLimitedArray(settlement.bonds, normalizeCampaignBondProgressSnapshot, maxCampaignBattleBondEntries),
@@ -1291,7 +1291,8 @@ function normalizeFirstBattleReport(report: unknown): FirstBattleReport | undefi
mvp: normalizeCampMvpSnapshot(report.mvp), mvp: normalizeCampMvpSnapshot(report.mvp),
itemRewards: uniqueStrings(report.itemRewards), itemRewards: uniqueStrings(report.itemRewards),
campaignRewards: cloneCampaignRewardSnapshot( campaignRewards: cloneCampaignRewardSnapshot(
isPlainObject(report.campaignRewards) ? report.campaignRewards as CampaignRewardSnapshot : undefined isPlainObject(report.campaignRewards) ? report.campaignRewards as CampaignRewardSnapshot : undefined,
battleId
), ),
completedCampDialogues: uniqueStrings(report.completedCampDialogues), completedCampDialogues: uniqueStrings(report.completedCampDialogues),
completedCampVisits: uniqueStrings(report.completedCampVisits), completedCampVisits: uniqueStrings(report.completedCampVisits),
@@ -1506,7 +1507,7 @@ function createBattleSettlement(report: FirstBattleReport, reserveTraining: Camp
outcome: report.outcome, outcome: report.outcome,
rewardGold: report.rewardGold, rewardGold: report.rewardGold,
itemRewards: [...report.itemRewards], itemRewards: [...report.itemRewards],
campaignRewards: cloneCampaignRewardSnapshot(report.campaignRewards), campaignRewards: cloneCampaignRewardSnapshot(report.campaignRewards, report.battleId),
objectives: report.objectives.map((objective) => ({ ...objective })), objectives: report.objectives.map((objective) => ({ ...objective })),
units: report.units units: report.units
.filter((unit) => unit.faction === 'ally') .filter((unit) => unit.faction === 'ally')
@@ -1655,12 +1656,12 @@ function cloneReport(report: FirstBattleReport): FirstBattleReport {
cloned.completedCampDialogues = uniqueStrings(cloned.completedCampDialogues); cloned.completedCampDialogues = uniqueStrings(cloned.completedCampDialogues);
cloned.completedCampVisits = uniqueStrings(cloned.completedCampVisits); cloned.completedCampVisits = uniqueStrings(cloned.completedCampVisits);
if (cloned.campaignRewards) { if (cloned.campaignRewards) {
cloned.campaignRewards = cloneCampaignRewardSnapshot(cloned.campaignRewards); cloned.campaignRewards = cloneCampaignRewardSnapshot(cloned.campaignRewards, cloned.battleId);
} }
return cloned; return cloned;
} }
function cloneCampaignRewardSnapshot(rewards?: CampaignRewardSnapshot): CampaignRewardSnapshot | undefined { function cloneCampaignRewardSnapshot(rewards?: CampaignRewardSnapshot, battleId?: string): CampaignRewardSnapshot | undefined {
if (!rewards) { if (!rewards) {
return undefined; return undefined;
} }
@@ -1678,7 +1679,7 @@ function cloneCampaignRewardSnapshot(rewards?: CampaignRewardSnapshot): Campaign
unitId: normalizeKeyString(recruit.unitId), unitId: normalizeKeyString(recruit.unitId),
name: normalizeDisplayString(recruit.name) name: normalizeDisplayString(recruit.name)
})) }))
.filter((recruit) => recruit.unitId && recruit.name), .filter((recruit) => recruit.unitId && recruit.name && isKnownCampaignRewardRecruit(recruit.unitId, battleId)),
(recruit) => recruit.unitId (recruit) => recruit.unitId
) )
.slice(0, maxCampaignStringListEntries), .slice(0, maxCampaignStringListEntries),
@@ -1697,6 +1698,18 @@ function cloneCampaignRewardSnapshot(rewards?: CampaignRewardSnapshot): Campaign
}; };
} }
function isKnownCampaignRewardRecruit(unitId: string, battleId?: string) {
if (campaignRecruitUnitById.has(unitId)) {
return true;
}
if (!battleId || !(battleId in battleScenarios)) {
return false;
}
return battleScenarios[battleId as BattleScenarioId].units.some((unit) => unit.faction === 'ally' && unit.id === unitId);
}
function cloneUnit(unit: UnitData): UnitData { function cloneUnit(unit: UnitData): UnitData {
return JSON.parse(JSON.stringify(unit)) as UnitData; return JSON.parse(JSON.stringify(unit)) as UnitData;
} }