feat: 사령부 명령 필요 턴을 표시한다
Ref처럼 여러 턴이 필요한 국가 명령의 소요 턴을 명령명 아래에 표시한다. 실행 getPreReqTurn을 기준으로 삼고 천도는 거리 기반 공식을 노출한다.
This commit is contained in:
@@ -39,6 +39,7 @@ type AvailabilityStatus = 'available' | 'blocked' | 'needsInput' | 'unknown';
|
||||
export interface TurnCommandAvailability {
|
||||
key: string;
|
||||
name: string;
|
||||
turnDurationText?: string;
|
||||
reqArg: boolean;
|
||||
possible: boolean;
|
||||
status: AvailabilityStatus;
|
||||
@@ -699,16 +700,34 @@ const buildEntries = (
|
||||
return entries;
|
||||
};
|
||||
|
||||
const buildGroups = (entries: CommandEntry[], ctx: ConstraintContext, view: StateView): TurnCommandGroup[] => {
|
||||
const getTurnDurationText = (definition: GeneralActionDefinition): string | undefined => {
|
||||
const hint = definition.getTurnDurationHint?.();
|
||||
if (hint) return hint;
|
||||
|
||||
const getPreReqTurn = definition.getPreReqTurn;
|
||||
// 인자를 선언한 구현은 천도처럼 대상에 따라 달라지므로 임의 context로 실행하지 않는다.
|
||||
if (!getPreReqTurn || getPreReqTurn.length > 0) return undefined;
|
||||
const preReqTurn = Math.max(0, Math.floor(getPreReqTurn.call(definition, undefined as never, {})));
|
||||
return preReqTurn > 0 ? `${preReqTurn + 1}턴` : undefined;
|
||||
};
|
||||
|
||||
const buildGroups = (
|
||||
entries: CommandEntry[],
|
||||
ctx: ConstraintContext,
|
||||
view: StateView,
|
||||
includeTurnDuration = false
|
||||
): TurnCommandGroup[] => {
|
||||
const groups = new Map<string, TurnCommandAvailability[]>();
|
||||
|
||||
for (const entry of entries) {
|
||||
const availability = entry.evaluate
|
||||
? entry.evaluate(ctx, view)
|
||||
: evaluateDefinition(entry.definition, ctx, view, entry.reqArg, entry.availabilityArgs);
|
||||
const turnDurationText = includeTurnDuration ? getTurnDurationText(entry.definition) : undefined;
|
||||
const value: TurnCommandAvailability = {
|
||||
key: entry.definition.key,
|
||||
name: entry.definition.name,
|
||||
...(turnDurationText ? { turnDurationText } : {}),
|
||||
reqArg: entry.reqArg,
|
||||
inputFields: entry.inputFields,
|
||||
...availability,
|
||||
@@ -806,7 +825,12 @@ export const buildTurnCommandTable = async (options: {
|
||||
ctx,
|
||||
view
|
||||
),
|
||||
nation: buildGroups(projectCommandGroups(nationEntries, nationGroups ?? REF_NATION_COMMAND_GROUPS), ctx, view),
|
||||
nation: buildGroups(
|
||||
projectCommandGroups(nationEntries, nationGroups ?? REF_NATION_COMMAND_GROUPS),
|
||||
ctx,
|
||||
view,
|
||||
true
|
||||
),
|
||||
inputOptions: options.inputOptions ?? {
|
||||
cities: [],
|
||||
nations: [],
|
||||
|
||||
@@ -190,6 +190,27 @@ describe('buildTurnCommandTable', () => {
|
||||
전략: ['필사즉생', '백성동원', '수몰', '허보', '의병모집', '이호경식', '급습', '피장파장'],
|
||||
기타: ['국기변경', '국호변경'],
|
||||
});
|
||||
expect(
|
||||
Object.fromEntries(
|
||||
table.nation
|
||||
.flatMap(({ values }) => values)
|
||||
.filter(({ turnDurationText }) => turnDurationText)
|
||||
.map(({ key, turnDurationText }) => [key, turnDurationText])
|
||||
)
|
||||
).toEqual({
|
||||
che_초토화: '3턴',
|
||||
che_천도: '1+거리×2턴',
|
||||
che_증축: '6턴',
|
||||
che_감축: '6턴',
|
||||
che_필사즉생: '3턴',
|
||||
che_수몰: '3턴',
|
||||
che_허보: '2턴',
|
||||
che_의병모집: '3턴',
|
||||
che_피장파장: '2턴',
|
||||
});
|
||||
expect(table.general.flatMap(({ values }) => values)).not.toContainEqual(
|
||||
expect.objectContaining({ turnDurationText: expect.any(String) })
|
||||
);
|
||||
});
|
||||
|
||||
it('projects scenario-specific command categories instead of the default profile', async () => {
|
||||
@@ -225,6 +246,14 @@ describe('buildTurnCommandTable', () => {
|
||||
'event_대검병연구',
|
||||
'event_화륜차연구',
|
||||
]);
|
||||
expect(
|
||||
Object.fromEntries(
|
||||
table.nation.flatMap(({ values }) => values.map(({ key, turnDurationText }) => [key, turnDurationText]))
|
||||
)
|
||||
).toMatchObject({
|
||||
event_대검병연구: '12턴',
|
||||
event_화륜차연구: '24턴',
|
||||
});
|
||||
});
|
||||
|
||||
it('projects the real 904/905/910/912 world command profiles into the API table', async () => {
|
||||
|
||||
Reference in New Issue
Block a user