feat: preview resonance pursuit pairs in formation

This commit is contained in:
2026-07-11 12:50:34 +09:00
parent 9025d74398
commit 307040ef00
4 changed files with 714 additions and 67 deletions

View File

@@ -9,6 +9,7 @@ const server = await createServer({
try {
const {
compareSortieSynergy,
evaluateSortiePursuitPairs,
evaluateSortieSynergy,
firstPursuitRolePreviewSummaries,
firstPursuitSynergyBattleId,
@@ -121,6 +122,70 @@ try {
);
assert(JSON.stringify({ members, bonds }) === frozenInputs, 'Expected synergy evaluation not to mutate its inputs.');
const pursuitMembers = [
{ id: 'selected-a', name: 'Selected A', role: 'front', terrainScore: 100 },
{ id: 'selected-b', name: 'Selected B', role: 'flank', terrainScore: 100 },
{ id: 'candidate-70', name: 'Candidate 70', role: 'support', terrainScore: 100 },
{ id: 'candidate-50', name: 'Candidate 50', role: 'support', terrainScore: 100 },
{ id: 'candidate-49', name: 'Candidate 49', role: 'support', terrainScore: 100 }
];
const pursuitBonds = [
{ id: 'active-70-zeta', title: 'Active Tie', unitIds: ['selected-a', 'selected-b'], level: 70 },
{ id: 'active-70-alpha', title: 'Active Tie', unitIds: ['selected-b', 'selected-a'], level: 70 },
{ id: 'active-50', title: 'Active 50', unitIds: ['selected-a', 'selected-b'], level: 50 },
{ id: 'opportunity-70-zeta', title: 'Zeta Opportunity', unitIds: ['selected-a', 'candidate-70'], level: 70 },
{ id: 'opportunity-70-alpha', title: 'Alpha Opportunity', unitIds: ['candidate-70', 'selected-a'], level: 70 },
{ id: 'opportunity-50-duplicate', title: 'Opportunity 50 Duplicate', unitIds: ['selected-a', 'candidate-70'], level: 50 },
{ id: 'opportunity-50', title: 'Opportunity 50', unitIds: ['selected-b', 'candidate-50'], level: 50 },
{ id: 'opportunity-49', title: 'Opportunity 49', unitIds: ['selected-a', 'candidate-49'], level: 49 }
];
const frozenPursuitInputs = JSON.stringify({ pursuitMembers, pursuitBonds });
const pursuitPairs = evaluateSortiePursuitPairs({
members: pursuitMembers,
bonds: pursuitBonds,
selectedUnitIds: ['selected-a', 'selected-b', 'selected-a']
});
assert(
pursuitPairs.activePairs.map((bond) => `${bond.id}:${bond.chainRate}`).join(',') === 'active-70-alpha:18',
`Expected a selected pair to keep its highest-level bond and resolve level ties by title/id while normalizing duplicate selections: ${JSON.stringify(pursuitPairs.activePairs)}`
);
assert(
pursuitPairs.selectableOpportunities.map((bond) => `${bond.id}:${bond.chainRate}`).join(',') === 'opportunity-70-alpha:18,opportunity-50:8',
`Expected opportunities to keep one strongest unordered pair, resolve ties deterministically, expose Lv70/Lv50 rates, and hide Lv49: ${JSON.stringify(pursuitPairs.selectableOpportunities)}`
);
assert(
pursuitPairs.selectableOpportunities[0]?.selectedPartnerId === 'selected-a' &&
pursuitPairs.selectableOpportunities[0]?.selectedPartnerName === 'Selected A' &&
pursuitPairs.selectableOpportunities[0]?.candidateUnitId === 'candidate-70' &&
pursuitPairs.selectableOpportunities[0]?.candidateUnitName === 'Candidate 70',
`Expected pursuit opportunities to identify the selected partner and selectable candidate: ${JSON.stringify(pursuitPairs.selectableOpportunities[0])}`
);
const unavailablePursuitPairs = evaluateSortiePursuitPairs({
members: pursuitMembers,
bonds: pursuitBonds,
selectedUnitIds: ['selected-a', 'selected-b'],
selectableUnitIds: ['selected-a', 'selected-b', 'candidate-50', 'candidate-49']
});
assert(
unavailablePursuitPairs.selectableOpportunities.length === 1 &&
unavailablePursuitPairs.selectableOpportunities[0]?.candidateUnitId === 'candidate-50',
`Expected unavailable candidates and already-selected ids to stay out of pursuit opportunities: ${JSON.stringify(unavailablePursuitPairs.selectableOpportunities)}`
);
const promotedPursuitPairs = evaluateSortiePursuitPairs({
members: pursuitMembers,
bonds: pursuitBonds,
selectedUnitIds: ['selected-a', 'selected-b', 'candidate-70']
});
assert(
promotedPursuitPairs.activePairs.some((bond) => bond.id === 'opportunity-70-alpha' && bond.chainRate === 18) &&
promotedPursuitPairs.selectableOpportunities.every((bond) => bond.candidateUnitId !== 'candidate-70'),
`Expected a selected candidate to move from opportunity to active pair: ${JSON.stringify(promotedPursuitPairs)}`
);
assert(
JSON.stringify({ pursuitMembers, pursuitBonds }) === frozenPursuitInputs,
'Expected pursuit-pair evaluation not to mutate its inputs.'
);
const orderPerformance = {
selectedUnitIds: ['front-unit', 'flank-unit', 'support-unit'],
formationAssignments: {