장수 55종과 수뇌 35종의 상태, 로그, 메시지, 예약 턴 비교를 닫습니다. 실제 시나리오 프로필과 대표 PostgreSQL 수명주기, 즉시 외교와 출병 회귀를 추가하고 발견된 Ref 로그 및 생성 장수 저장 차이를 교정합니다.
282 lines
10 KiB
TypeScript
282 lines
10 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { loadScenarioDefinitionById } from '../src/scenario/scenarioLoader.js';
|
|
import { loadScenarioTurnCommandProfile } from '../src/turn/turnCommandProfile.js';
|
|
|
|
type CommandGroupManifest = ReadonlyArray<{
|
|
category: string;
|
|
commands: readonly string[];
|
|
}>;
|
|
|
|
const defaultGeneralProfileManifest = [
|
|
'che_거병',
|
|
'che_임관',
|
|
'che_장수대상임관',
|
|
'che_랜덤임관',
|
|
'che_귀환',
|
|
'che_건국',
|
|
'che_훈련',
|
|
'che_단련',
|
|
'che_숙련전환',
|
|
'che_사기진작',
|
|
'che_요양',
|
|
'che_견문',
|
|
'che_은퇴',
|
|
'che_내정특기초기화',
|
|
'che_전투특기초기화',
|
|
'che_장비매매',
|
|
'che_출병',
|
|
'che_주민선정',
|
|
'che_정착장려',
|
|
'che_농지개간',
|
|
'che_상업투자',
|
|
'che_기술연구',
|
|
'che_치안강화',
|
|
'che_수비강화',
|
|
'che_성벽보수',
|
|
'che_선동',
|
|
'che_탈취',
|
|
'che_파괴',
|
|
'che_화계',
|
|
'che_집합',
|
|
'che_인재탐색',
|
|
'che_등용',
|
|
'che_징병',
|
|
'che_모병',
|
|
'che_소집해제',
|
|
'che_첩보',
|
|
'che_군량매매',
|
|
'che_물자조달',
|
|
'che_증여',
|
|
'che_헌납',
|
|
'che_이동',
|
|
'che_강행',
|
|
'che_하야',
|
|
'che_선양',
|
|
'che_해산',
|
|
'휴식',
|
|
] as const;
|
|
|
|
const generalPersonalCommands = [
|
|
'휴식',
|
|
'che_요양',
|
|
'che_단련',
|
|
'che_숙련전환',
|
|
'che_견문',
|
|
'che_은퇴',
|
|
'che_장비매매',
|
|
'che_군량매매',
|
|
'che_내정특기초기화',
|
|
'che_전투특기초기화',
|
|
] as const;
|
|
const generalDomesticCommands = [
|
|
'che_농지개간',
|
|
'che_상업투자',
|
|
'che_기술연구',
|
|
'che_수비강화',
|
|
'che_성벽보수',
|
|
'che_치안강화',
|
|
'che_정착장려',
|
|
'che_주민선정',
|
|
'che_물자조달',
|
|
] as const;
|
|
const generalMilitaryCommands = [
|
|
'che_징병',
|
|
'che_모병',
|
|
'che_훈련',
|
|
'che_사기진작',
|
|
'che_출병',
|
|
'che_집합',
|
|
'che_소집해제',
|
|
'che_첩보',
|
|
] as const;
|
|
const generalPersonnelCommands = ['che_이동', 'che_강행', 'che_인재탐색', 'che_귀환', 'che_랜덤임관'] as const;
|
|
const generalSchemeCommands = ['che_선동', 'che_탈취', 'che_파괴', 'che_화계'] as const;
|
|
const nationDiplomacyCommands = [
|
|
'che_물자원조',
|
|
'che_불가침제의',
|
|
'che_선전포고',
|
|
'che_종전제의',
|
|
'che_불가침파기제의',
|
|
] as const;
|
|
|
|
const scenarioProfileManifest: Record<
|
|
number,
|
|
{ generalGroups: CommandGroupManifest | null; nationGroups: CommandGroupManifest }
|
|
> = {
|
|
904: {
|
|
generalGroups: [
|
|
{ category: '개인', commands: generalPersonalCommands },
|
|
{ category: '내정', commands: generalDomesticCommands },
|
|
{ category: '군사', commands: generalMilitaryCommands },
|
|
{ category: '인사', commands: generalPersonnelCommands },
|
|
{ category: '계략', commands: generalSchemeCommands },
|
|
{ category: '국가', commands: ['che_증여', 'che_헌납', 'che_하야'] },
|
|
],
|
|
nationGroups: [
|
|
{ category: '휴식', commands: ['휴식'] },
|
|
{ category: '인사', commands: ['che_발령', 'che_포상', 'che_몰수'] },
|
|
{ category: '특수', commands: ['che_초토화', 'che_천도', 'che_증축', 'che_감축'] },
|
|
{
|
|
category: '전략',
|
|
commands: [
|
|
'che_필사즉생',
|
|
'che_백성동원',
|
|
'che_수몰',
|
|
'che_허보',
|
|
'che_의병모집',
|
|
'che_이호경식',
|
|
'che_급습',
|
|
],
|
|
},
|
|
{ category: '기타', commands: ['che_피장파장', 'che_국기변경', 'che_국호변경'] },
|
|
],
|
|
},
|
|
905: {
|
|
generalGroups: [
|
|
{ category: '개인', commands: generalPersonalCommands },
|
|
{ category: '내정', commands: generalDomesticCommands },
|
|
{ category: '군사', commands: generalMilitaryCommands },
|
|
{ category: '인사', commands: generalPersonnelCommands },
|
|
{ category: '계략', commands: generalSchemeCommands },
|
|
{
|
|
category: '국가',
|
|
commands: ['che_증여', 'che_헌납', 'che_하야', 'che_거병', 'che_무작위건국', 'che_선양', 'che_해산'],
|
|
},
|
|
],
|
|
nationGroups: [
|
|
{ category: '휴식', commands: ['휴식'] },
|
|
{ category: '인사', commands: ['che_발령', 'che_포상', 'che_몰수'] },
|
|
{ category: '외교', commands: nationDiplomacyCommands },
|
|
{ category: '특수', commands: ['che_초토화', 'che_천도', 'che_증축', 'che_감축'] },
|
|
{
|
|
category: '전략',
|
|
commands: [
|
|
'che_필사즉생',
|
|
'che_백성동원',
|
|
'che_수몰',
|
|
'che_허보',
|
|
'che_의병모집',
|
|
'che_이호경식',
|
|
'che_급습',
|
|
'che_피장파장',
|
|
],
|
|
},
|
|
{ category: '기타', commands: ['che_국기변경', 'che_국호변경', 'che_무작위수도이전'] },
|
|
],
|
|
},
|
|
910: {
|
|
generalGroups: [
|
|
{ category: '개인', commands: generalPersonalCommands },
|
|
{ category: '내정', commands: generalDomesticCommands },
|
|
{
|
|
category: '군사',
|
|
commands: [
|
|
'che_징병',
|
|
'che_모병',
|
|
'che_훈련',
|
|
'che_사기진작',
|
|
'cr_맹훈련',
|
|
'che_출병',
|
|
'che_집합',
|
|
'che_소집해제',
|
|
'che_첩보',
|
|
],
|
|
},
|
|
{ category: '인사', commands: generalPersonnelCommands },
|
|
{ category: '계략', commands: generalSchemeCommands },
|
|
{
|
|
category: '국가',
|
|
commands: ['che_증여', 'che_헌납', 'che_하야', 'che_거병', 'cr_건국', 'che_선양', 'che_해산'],
|
|
},
|
|
],
|
|
nationGroups: [
|
|
{ category: '휴식', commands: ['휴식'] },
|
|
{ category: '인사', commands: ['che_발령', 'che_포상', 'che_몰수'] },
|
|
{ category: '외교', commands: nationDiplomacyCommands },
|
|
{ category: '특수', commands: ['che_초토화', 'che_천도', 'cr_인구이동'] },
|
|
{
|
|
category: '전략',
|
|
commands: [
|
|
'che_필사즉생',
|
|
'che_백성동원',
|
|
'che_수몰',
|
|
'che_허보',
|
|
'che_의병모집',
|
|
'che_이호경식',
|
|
'che_급습',
|
|
],
|
|
},
|
|
{ category: '기타', commands: ['che_피장파장', 'che_국기변경', 'che_국호변경'] },
|
|
],
|
|
},
|
|
912: {
|
|
generalGroups: null,
|
|
nationGroups: [
|
|
{ category: '휴식', commands: ['휴식'] },
|
|
{ category: '인사', commands: ['che_발령', 'che_포상', 'che_몰수', 'che_부대탈퇴지시'] },
|
|
{ category: '외교', commands: nationDiplomacyCommands },
|
|
{ category: '특수', commands: ['che_초토화', 'che_천도', 'che_증축', 'che_감축'] },
|
|
{
|
|
category: '전략',
|
|
commands: [
|
|
'che_필사즉생',
|
|
'che_백성동원',
|
|
'che_수몰',
|
|
'che_허보',
|
|
'che_의병모집',
|
|
'che_이호경식',
|
|
'che_급습',
|
|
'che_피장파장',
|
|
],
|
|
},
|
|
{ category: '기타', commands: ['che_국기변경', 'che_국호변경'] },
|
|
{
|
|
category: '연구',
|
|
commands: [
|
|
'event_대검병연구',
|
|
'event_극병연구',
|
|
'event_화시병연구',
|
|
'event_원융노병연구',
|
|
'event_산저병연구',
|
|
'event_음귀병연구',
|
|
'event_무희연구',
|
|
'event_상병연구',
|
|
'event_화륜차연구',
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
const loadScenarioProfile = async (scenarioId: number) => {
|
|
const scenario = await loadScenarioDefinitionById(scenarioId);
|
|
return loadScenarioTurnCommandProfile({ scenarioConst: scenario.config.const });
|
|
};
|
|
|
|
describe('scenario command profile resources', () => {
|
|
it('fails closed when the configured base profile file is missing', async () => {
|
|
await expect(
|
|
loadScenarioTurnCommandProfile({ filePath: '/tmp/core2026-command-profile-does-not-exist.json' })
|
|
).rejects.toMatchObject({ code: 'ENOENT' });
|
|
});
|
|
|
|
it.each(Object.entries(scenarioProfileManifest))(
|
|
'preserves scenario %s general/chief group order and the exact flattened product profile',
|
|
async (scenarioId, manifest) => {
|
|
const result = await loadScenarioProfile(Number(scenarioId));
|
|
const expectedGeneral = manifest.generalGroups
|
|
? manifest.generalGroups.flatMap((group) => group.commands)
|
|
: defaultGeneralProfileManifest;
|
|
const expectedNation = manifest.nationGroups.flatMap((group) => group.commands);
|
|
|
|
expect(result.generalGroups).toEqual(manifest.generalGroups);
|
|
expect(result.nationGroups).toEqual(manifest.nationGroups);
|
|
expect(result.profile.general).toEqual(expectedGeneral);
|
|
expect(result.profile.nation).toEqual(expectedNation);
|
|
expect(new Set(result.profile.general).size).toBe(result.profile.general.length);
|
|
expect(new Set(result.profile.nation).size).toBe(result.profile.nation.length);
|
|
}
|
|
);
|
|
});
|