import { describe, expect, it } from 'vitest'; import { type CustomWorldProfile, WorldType } from '../types'; import { collectCreatureArchetypeSignals, collectSceneBucketSignalKeywords, resolveCreatureArchetypeForSource, resolveRoleTemplateCharacterIdFromReferenceProfile, resolveSceneBucketForLandmark, } from './customWorldReferenceSignals'; function buildReferenceProfileHarness() { return { id: 'reference-harness', settingText: '围绕裂界港区、断桥前线与工业旧站展开的世界。', name: '裂桥港区', subtitle: '前线潮压', summary: '断桥、港区和旧站之间的战线不断回响。', tone: '高压、潮湿、迟滞', playerGoal: '查清断桥封锁与旧站事故背后的真相', templateWorldType: WorldType.WUXIA, majorFactions: [], coreConflicts: [], attributeSchema: { id: 'schema:test', worldId: 'custom:test', schemaVersion: 1, generatedFrom: { worldType: WorldType.CUSTOM, worldName: '裂桥港区', settingSummary: '断桥前线', tone: '高压', conflictCore: '旧站事故', }, slots: [], }, playableNpcs: [], storyNpcs: [], items: [], landmarks: [], ownedSettingLayers: { semanticAnchor: { genreSignals: ['裂界边境'], conflictForms: ['追查失线'], institutionTypes: ['前哨'], tabooTypes: ['封桥令'], carrierTypes: ['界核'], forceSystemTypes: ['裂界'], atmosphereTags: ['高压'], }, ruleProfile: { attributeSchema: { id: 'schema:test', worldId: 'custom:test', schemaVersion: 1, generatedFrom: { worldType: WorldType.CUSTOM, worldName: '裂桥港区', settingSummary: '断桥前线', tone: '高压', conflictCore: '旧站事故', }, slots: [], }, resourceLabels: { hp: '界命', mp: '裂能', maxHp: '界命上限', maxMp: '裂能上限', damage: '界势', guard: '稳界', range: '界距', cooldown: '复界', manaCost: '裂能消耗', currency: '边贸券', }, economyProfile: { initialCurrency: 160, }, }, expressionProfile: { themePack: { id: 'theme:test', displayName: '裂桥前线', toneRange: ['高压'], institutionLexicon: ['前哨'], tabooLexicon: ['封桥令'], artifactClasses: ['界核'], actorArchetypes: ['边巡者'], conflictForms: ['追查失线'], clueForms: ['裂痕'], namingPatterns: ['前哨+旧痕+器类'], revealStyles: ['证词错位'], }, presentationTone: ['高压'], namingDirectives: ['前哨+旧痕+器类'], clueDirectives: ['裂痕'], revealDirectives: ['证词错位'], }, referenceProfile: { roleArchetypes: [ { id: 'role-1', label: '远程压制型', combatFocus: '依靠弓与远程火力持续压制。', narrativeFunction: '为队伍提供远程压制与侦查。', sourceRoleIds: [], sourceTemplateCharacterIds: [], tags: ['远程', '射击'], }, ], sceneBuckets: [ { id: 'scene-1', label: '工业热区', moodTags: ['高压'], keywords: ['旧站', '工坊'], referenceLandmarkIds: ['landmark-industrial'], }, { id: 'scene-2', label: '临水渡口区', moodTags: ['潮湿'], keywords: ['港区', '渡桥'], referenceLandmarkIds: ['landmark-harbor'], }, ], creatureArchetypes: [ { id: 'creature-1', label: '机关守卫体', threatStyle: '围绕节点和装置进行守线压制。', keywords: ['机关', '守卫', '旧站'], }, { id: 'creature-2', label: '远程威胁者', threatStyle: '依靠远程投射和凝视压制走位。', keywords: ['远程', '压制', '索敌'], }, ], }, compatibilityProfile: { legacyTemplateWorldType: WorldType.WUXIA, migrationVersion: 'test', }, }, themePack: null, storyGraph: null, creatorIntent: null, anchorPack: null, lockState: null, generationMode: 'full', generationStatus: 'complete', } satisfies CustomWorldProfile; } describe('customWorldReferenceSignals', () => { it('resolves scene buckets by explicit landmark ownership', () => { const profile = buildReferenceProfileHarness(); const bucket = resolveSceneBucketForLandmark(profile, { id: 'landmark-industrial', name: '旧站锅炉层', description: '轨道和锅炉残响仍卡在热区深处。', }); expect(bucket?.label).toBe('工业热区'); expect(collectSceneBucketSignalKeywords(bucket!).includes('工坊')).toBe(true); }); it('resolves creature archetypes and exposes combat/habitat signal tags', () => { const profile = buildReferenceProfileHarness(); const archetype = resolveCreatureArchetypeForSource(profile, { name: '旧站守卫傀', role: '节点守卫', description: '围绕工坊旧站守线,遇敌后会启动压制炮座。', combatStyle: '守住节点后用远程火力封锁通路。', tags: ['机关', '旧站', '守卫'], }); const signals = collectCreatureArchetypeSignals(archetype!); expect(archetype?.label).toBe('机关守卫体'); expect(signals.combatTags).toContain('守御'); expect(signals.habitatTags).toContain('工场'); }); it('maps role archetypes back to suitable preset character templates', () => { const profile = buildReferenceProfileHarness(); const templateCharacterId = resolveRoleTemplateCharacterIdFromReferenceProfile( profile, { id: 'story-role-1', name: '雾港狙巡手', title: '岸线压制者', role: '远程巡手', description: '负责在港区高点做远程掩护与索敌压制。', personality: '冷静,开火前总先确认潮向。', combatStyle: '高点远程压制,必要时转为游击拉扯。', tags: ['远程', '射击', '港区'], }, ); expect(templateCharacterId).toBe('archer-hero'); }); });