Simplify custom world result editing controls
This commit is contained in:
209
src/services/customWorldReferenceSignals.test.ts
Normal file
209
src/services/customWorldReferenceSignals.test.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user