ziweidoushu / src /core-engine /dynamic-core.ts
luoly2026
Deploy: Fresh initial commit for Hugging Face
631a7d3
Raw
History Blame Contribute Delete
6.87 kB
import { AstrolabeData, DynamicChainStep, MutagenKey, PalaceData, TimeLayerData, TimeLayerScope } from './types';
// 十干四化表 (事实字典)
export const SIHUA_DICT: Record<string, { 禄: string; 权: string; 科: string; 忌: string }> = {
'甲': { 禄: '廉贞', 权: '破军', 科: '武曲', 忌: '太阳' },
'乙': { 禄: '天机', 权: '天梁', 科: '紫微', 忌: '太阴' },
'丙': { 禄: '天同', 权: '天机', 科: '文昌', 忌: '廉贞' },
'丁': { 禄: '太阴', 权: '天同', 科: '天机', 忌: '巨门' },
'戊': { 禄: '贪狼', 权: '太阴', 科: '右弼', 忌: '天机' },
'己': { 禄: '武曲', 权: '贪狼', 科: '天梁', 忌: '文曲' },
'庚': { 禄: '太阳', 权: '武曲', 科: '太阴', 忌: '天同' },
'辛': { 禄: '巨门', 权: '太阳', 科: '文曲', 忌: '文昌' },
'壬': { 禄: '天梁', 权: '紫微', 科: '左辅', 忌: '武曲' },
'癸': { 禄: '破军', 权: '巨门', 科: '太阴', 忌: '贪狼' },
};
// 飞星事实结构
export interface FlyingFact {
scope: TimeLayerScope;
sourceStem: string;
fromPalaceIndex: number;
fromPalaceName: string;
toPalaceIndex: number;
toPalaceName: string;
mutagen: MutagenKey;
star: string;
isSelfMutagen: boolean; // 是否为自化
depth: number;
}
/**
* 动态核心层:只负责计算星曜飞布事实,不涉及命理解读
*/
export class DynamicCore {
private timeLayerData: TimeLayerData;
private astrolabe: AstrolabeData;
constructor(timeLayerData: TimeLayerData) {
this.timeLayerData = timeLayerData;
this.astrolabe = timeLayerData.original;
}
// 1. 获取生年四化落点事实
public getShengNianSihuaFacts(): Record<'禄'|'权'|'科'|'忌', PalaceData | null> {
const facts: Record<'禄'|'权'|'科'|'忌', PalaceData | null> = { 禄: null, 权: null, 科: null, 忌: null };
if (!this.astrolabe || !this.astrolabe.palaces) return facts;
this.astrolabe.palaces.forEach(palace => {
[...(palace.majorStars || []), ...(palace.minorStars || [])].forEach(star => {
if (star.mutagen) {
facts[star.mutagen as '禄'|'权'|'科'|'忌'] = palace;
}
});
});
return facts;
}
public getScopeMutagenFacts(scope: TimeLayerScope): FlyingFact[] {
if (scope === 'original') {
return this.getOriginalMutagenFacts();
}
const scopeData = this.timeLayerData[scope];
if (!scopeData) {
return [];
}
const fromPalace = this.findPalaceByName(scopeData.targetPalaceName);
if (!fromPalace) {
return [];
}
return (['禄', '权', '科', '忌'] as const)
.map((mutagen) => this.buildFact(scope, fromPalace, scopeData.heavenlyStem, mutagen, 0))
.filter((fact): fact is FlyingFact => !!fact);
}
public traceMutagenChain(
scope: TimeLayerScope,
mutagen: MutagenKey = '忌',
maxDepth = 3
): DynamicChainStep[] {
const firstFact = this.getScopeMutagenFacts(scope).find((fact) => fact.mutagen === mutagen);
if (!firstFact) {
return [];
}
const chain: FlyingFact[] = [firstFact];
const visitedPalaces = new Set<string>([firstFact.fromPalaceName, firstFact.toPalaceName]);
let currentPalace = this.findPalaceByName(firstFact.toPalaceName);
for (let depth = 1; depth < maxDepth; depth += 1) {
if (!currentPalace) {
break;
}
const nextFact = this.buildFact(scope, currentPalace, currentPalace.heavenlyStem, mutagen, depth);
if (!nextFact) {
break;
}
chain.push(nextFact);
if (nextFact.isSelfMutagen || visitedPalaces.has(nextFact.toPalaceName)) {
break;
}
visitedPalaces.add(nextFact.toPalaceName);
currentPalace = this.findPalaceByName(nextFact.toPalaceName);
}
return chain.map((fact) => ({
scope: fact.scope,
sourceStem: fact.sourceStem,
fromPalaceName: fact.fromPalaceName,
toPalaceName: fact.toPalaceName,
mutagen: fact.mutagen,
star: fact.star,
isSelfMutagen: fact.isSelfMutagen,
}));
}
public getZiHuaFacts(): FlyingFact[] {
if (!this.astrolabe || !this.astrolabe.palaces) {
return [];
}
return this.astrolabe.palaces.flatMap((palace) =>
this.getFlyingFactsFromPalace(palace.index).filter((fact) => fact.isSelfMutagen)
);
}
// 2. 计算指定宫位的飞出事实 (含自化)
public getFlyingFactsFromPalace(fromIndex: number): FlyingFact[] {
const facts: FlyingFact[] = [];
if (!this.astrolabe || !this.astrolabe.palaces) return facts;
const fromPalace = this.astrolabe.palaces.find(p => p.index === fromIndex);
if (!fromPalace) return facts;
(['禄', '权', '科', '忌'] as const).forEach(mutagen => {
const fact = this.buildFact('original', fromPalace, fromPalace.heavenlyStem, mutagen, 0);
if (fact) {
facts.push(fact);
}
});
return facts;
}
private getOriginalMutagenFacts(): FlyingFact[] {
const shengNianGan = this.astrolabe.chineseDate.split(' ')[0][0];
const fromPalace = this.astrolabe.palaces.find((palace) => palace.heavenlyStem === shengNianGan);
if (!fromPalace) {
return [];
}
return (['禄', '权', '科', '忌'] as const)
.map((mutagen) => this.buildFact('original', fromPalace, shengNianGan, mutagen, 0))
.filter((fact): fact is FlyingFact => !!fact);
}
private buildFact(
scope: TimeLayerScope,
fromPalace: PalaceData,
sourceStem: string,
mutagen: MutagenKey,
depth: number
): FlyingFact | undefined {
const sihuaMap = SIHUA_DICT[sourceStem];
if (!sihuaMap) {
return undefined;
}
const targetStar = sihuaMap[mutagen];
const toPalace = this.findPalaceByStar(targetStar);
if (!toPalace) {
return undefined;
}
return {
scope,
sourceStem,
fromPalaceIndex: fromPalace.index,
fromPalaceName: this.cleanPalaceName(fromPalace.name),
toPalaceIndex: toPalace.index,
toPalaceName: this.cleanPalaceName(toPalace.name),
mutagen,
star: targetStar,
isSelfMutagen: fromPalace.index === toPalace.index,
depth,
};
}
// 3. 寻找某颗星所在的宫位
public findPalaceByStar(starName: string): PalaceData | undefined {
if (!this.astrolabe || !this.astrolabe.palaces) return undefined;
return this.astrolabe.palaces.find(p =>
[...(p.majorStars || []), ...(p.minorStars || [])].some(s => s.name === starName)
);
}
public findPalaceByName(palaceName: string): PalaceData | undefined {
if (!this.astrolabe || !this.astrolabe.palaces) {
return undefined;
}
return this.astrolabe.palaces.find((palace) => this.cleanPalaceName(palace.name) === this.cleanPalaceName(palaceName));
}
private cleanPalaceName(name: string) {
return name.split('(')[0];
}
}