feat: add signature officer tactics
This commit is contained in:
@@ -15,6 +15,12 @@ try {
|
||||
} = await server.ssrLoadModule('/src/game/data/sortieRecommendations.ts');
|
||||
const { sortieFormationRoles } = await server.ssrLoadModule('/src/game/data/sortieDeployment.ts');
|
||||
const { sortieOrderIds } = await server.ssrLoadModule('/src/game/data/sortieOrders.ts');
|
||||
const { getUnitStrategyCoverage, usableCatalog } = await server.ssrLoadModule('/src/game/data/battleUsables.ts');
|
||||
const signatureStrategyByOwner = new Map(
|
||||
Object.values(usableCatalog)
|
||||
.filter((usable) => usable.signatureOwnerId)
|
||||
.map((usable) => [usable.signatureOwnerId, usable.name])
|
||||
);
|
||||
|
||||
assert(
|
||||
JSON.stringify(sortieRecommendationPlanIds) === JSON.stringify(['order', 'resonance', 'terrain-strategy']),
|
||||
@@ -58,6 +64,8 @@ try {
|
||||
orderId,
|
||||
context,
|
||||
formationRoles,
|
||||
getUnitStrategyCoverage,
|
||||
signatureStrategyByOwner,
|
||||
expectedCount: scenario.sortie.sortieLimit
|
||||
});
|
||||
evaluatedPlanCount += 1;
|
||||
@@ -155,7 +163,16 @@ function terrainScoreForUnit(unit, scenario, terrainRules, unitClasses) {
|
||||
: 100;
|
||||
}
|
||||
|
||||
function validateApplicablePlan({ plan, battleId, orderId, context, formationRoles, expectedCount }) {
|
||||
function validateApplicablePlan({
|
||||
plan,
|
||||
battleId,
|
||||
orderId,
|
||||
context,
|
||||
formationRoles,
|
||||
getUnitStrategyCoverage,
|
||||
signatureStrategyByOwner,
|
||||
expectedCount
|
||||
}) {
|
||||
const candidateById = new Map(
|
||||
context.candidates
|
||||
.filter((candidate) => candidate.available !== false && candidate.unit.faction === 'ally' && candidate.unit.hp > 0)
|
||||
@@ -205,6 +222,30 @@ function validateApplicablePlan({ plan, battleId, orderId, context, formationRol
|
||||
Object.values(plan.unitReasons).every(isNonEmptyText),
|
||||
`${battleId}/${orderId}/${plan.id}: expected one reason for every selected unit: ${JSON.stringify(plan.unitReasons)}`
|
||||
);
|
||||
if (signatureStrategyByOwner) {
|
||||
plan.selectedUnitIds.forEach((unitId) => {
|
||||
const signatureName = signatureStrategyByOwner.get(unitId);
|
||||
if (signatureName) {
|
||||
assert(
|
||||
plan.unitReasons[unitId].includes(`고유 ${signatureName}`),
|
||||
`${battleId}/${orderId}/${plan.id}: signature strategy must appear in ${unitId}'s recommendation reason: ${plan.unitReasons[unitId]}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (getUnitStrategyCoverage) {
|
||||
const expectedStrategyCoverage = getUnitStrategyCoverage(plan.selectedUnitIds);
|
||||
assert(
|
||||
plan.metrics.strategyCoverageCount === expectedStrategyCoverage.count &&
|
||||
plan.metrics.strategyCoverageTotal === expectedStrategyCoverage.total &&
|
||||
JSON.stringify(plan.metrics.coveredStrategyLabels) === JSON.stringify(expectedStrategyCoverage.covered.map((definition) => definition.label)) &&
|
||||
JSON.stringify(plan.metrics.missingStrategyLabels) === JSON.stringify(expectedStrategyCoverage.missing.map((definition) => definition.label)),
|
||||
`${battleId}/${orderId}/${plan.id}: recommendation metrics must match tag-based strategy coverage: ${JSON.stringify({
|
||||
actual: plan.metrics,
|
||||
expected: expectedStrategyCoverage
|
||||
})}`
|
||||
);
|
||||
}
|
||||
validateMetrics(plan.metrics, orderId, `${battleId}/${orderId}/${plan.id}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user