feat: surface officer strategies in sortie planning

This commit is contained in:
2026-07-12 12:28:51 +09:00
parent 3daad2861b
commit cb66deef9d
5 changed files with 395 additions and 162 deletions

View File

@@ -3862,6 +3862,26 @@ try {
midFormationPortraitState?.sortiePortraitRoster?.length === 23 && missingMidFormationPortraits.length === 0,
`Expected all 23 campaign officers to use loaded lightweight portrait cards: ${JSON.stringify(missingMidFormationPortraits)}`
);
const midPortraitsMissingStrategyCopy = midFormationPortraitState?.sortiePortraitRoster?.filter(
(unit) => !Array.isArray(unit.strategyNames) || unit.strategyNames.length === 0 || !unit.strategyLine?.startsWith('전법 ')
) ?? [];
assert(
midPortraitsMissingStrategyCopy.length === 0 &&
sameJsonValue(midFormationPortraitState?.sortiePortraitRoster?.find((unit) => unit.id === 'guan-yu')?.strategyNames, ['화계']) &&
sameJsonValue(midFormationPortraitState?.sortiePortraitRoster?.find((unit) => unit.id === 'zhang-fei')?.strategyNames, ['고함']),
`Expected every sortie portrait card to expose its battle strategies: ${JSON.stringify(midPortraitsMissingStrategyCopy)}`
);
assert(
midFormationPortraitState?.sortieStrategyCoverage?.count === 4 &&
midFormationPortraitState.sortieStrategyCoverage.total === 4 &&
midFormationPortraitState.sortieStrategyCoverage.missing.length === 0 &&
sameJsonValue(midFormationPortraitState.sortieStrategyCoverage.covered.map((definition) => definition.label), ['회복', '강화', '화공', '제어']) &&
midFormationPortraitState?.sortieFocusedUnit?.strategyLine?.startsWith('전법 '),
`Expected the selected formation and focused officer to expose complete strategy coverage: ${JSON.stringify({
coverage: midFormationPortraitState?.sortieStrategyCoverage,
focused: midFormationPortraitState?.sortieFocusedUnit
})}`
);
const midCoreSelectorToggle = midFormationPortraitState?.sortiePursuitPreview;
assert(
@@ -4042,15 +4062,25 @@ try {
swapPreview?.comparison?.lostRoles?.includes('flank') &&
swapPreview?.comparison?.activeBondDelta === 0 &&
swapPreview?.comparison?.gainedBonds?.length > 0 &&
swapPreview?.comparison?.lostBonds?.length > 0,
swapPreview?.comparison?.lostBonds?.length > 0 &&
swapPreview?.strategyCoverage?.current?.count === 4 &&
swapPreview?.strategyCoverage?.projected?.count === 4 &&
swapPreview?.strategyCoverage?.current?.total === 4 &&
swapPreview?.strategyCoverage?.projected?.total === 4 &&
swapPreview?.strategyCoverage?.delta === 0 &&
swapPreview?.strategyCoverage?.trend === 'even' &&
swapPreview?.strategyCoverage?.gained?.length === 0 &&
swapPreview?.strategyCoverage?.lost?.length === 0,
`Expected a meaningful non-destructive Ma Dai to Guan Yu swap preview: ${JSON.stringify(swapPreview)}`
);
assert(
midFormationSwapPreviewProbe.panel.title === '가상 교체 · 마대 → 관우' &&
midFormationSwapPreviewProbe.panel.headline?.includes('OUT 마대') &&
midFormationSwapPreviewProbe.panel.headline?.includes('IN 관우') &&
midFormationSwapPreviewProbe.panel.impact?.includes('전법 4/4→4/4') &&
midFormationSwapPreviewProbe.panel.impact?.includes('추격') &&
midFormationSwapPreviewProbe.panel.impact?.includes('공백 돌파') &&
midFormationSwapPreviewProbe.panel.detail?.includes('전법 유지') &&
midFormationSwapPreviewProbe.panel.detail?.includes('추격 해제') &&
midFormationSwapPreviewProbe.panel.detail?.includes('8%') &&
midFormationSwapPreviewProbe.panel.detail?.includes('실제 편성 미변경'),