ziweidoushu / src /core-engine /static-analyzer.ts
luoly2026
Deploy: Fresh initial commit for Hugging Face
631a7d3
Raw
History Blame Contribute Delete
11.4 kB
import { AstrolabeData, PalaceData, StaticReport, StarData, RuleEvidence } from './types';
// 基础吉煞星分类
const JI_XING = ['左辅', '右弼', '文昌', '文曲', '天魁', '天钺', '禄存', '天马'];
const SHA_XING = ['擎羊', '陀罗', '火星', '铃星', '地空', '地劫'];
export class StaticAnalyzer {
private astrolabe: AstrolabeData;
private version = 'static-v2.0.0';
constructor(astrolabe: AstrolabeData) {
this.astrolabe = astrolabe;
}
public analyze(): StaticReport {
return {
starsStatus: this.analyzeStarsStatus(),
patterns: this.analyzePatterns(),
topics: {
career: this.analyzeTopic('官禄宫', '事业'),
wealth: this.analyzeTopic('财帛宫', '财富'),
marriage: this.analyzeTopic('夫妻宫', '婚姻'),
health: this.analyzeTopic('疾厄宫', '健康'),
property: this.analyzeTopic('田宅宫', '资产'),
},
interactions: this.analyzeInteractions(),
bodyMindLink: this.analyzeBodyMindLink(),
};
}
// 1. 星曜状态统计(全盘)
private analyzeStarsStatus() {
let miaoWangCount = 0;
let pingXianCount = 0;
let jiXingCount = 0;
let shaXingCount = 0;
this.astrolabe.palaces.forEach((palace) => {
palace.majorStars.forEach((star) => {
if (['庙', '旺'].includes(star.brightness || '')) miaoWangCount++;
if (['平', '陷', '不'].includes(star.brightness || '')) pingXianCount++;
});
palace.minorStars.forEach((star) => {
if (JI_XING.includes(star.name)) jiXingCount++;
if (SHA_XING.includes(star.name)) shaXingCount++;
});
});
return { miaoWangCount, pingXianCount, jiXingCount, shaXingCount };
}
// 2. 深度格局识别 (带证据链)
private analyzePatterns(): RuleEvidence[] {
const patterns: RuleEvidence[] = [];
const mingGong = this.getPalaceByName('命宫');
if (!mingGong) return patterns;
const sanFangStars = this.getSanFangSiZhengStars(mingGong);
const starNames = sanFangStars.map(s => s.name);
const mingGongStars = mingGong.majorStars.map(s => s.name);
// 机月同梁
if (this.containsAll(starNames, ['天机', '太阴', '天同', '天梁'])) {
patterns.push({
ruleId: 'ZW_STATIC_PATTERN_JIYUETONGLIANG_v1',
title: '机月同梁格',
type: 'static',
description: '心思细腻,善于谋划,适合在大企业或政府机关做幕僚、参谋,不利于自己出头做老板。',
boardEvidence: ['命宫三方四正凑齐天机、太阴、天同、天梁'],
conflicts: this.containsAny(starNames, SHA_XING) ? ['见煞星,心思易生变,多思多虑'] : [],
scoreImpact: 15,
tags: ['事业', '性格'],
version: this.version
});
}
// 杀破狼
if (this.containsAny(mingGongStars, ['七杀', '破军', '贪狼'])) {
patterns.push({
ruleId: 'ZW_STATIC_PATTERN_SHAPOLANG_v1',
title: '杀破狼格',
type: 'static',
description: '主变动、开创,一生起伏较大,不甘人后,适合军警、武职或开创性极强的行业。',
boardEvidence: [`命宫主星见${mingGongStars.filter(s => ['七杀', '破军', '贪狼'].includes(s)).join('、')}`],
conflicts: this.containsAll(mingGongStars, ['火星']) ? ['逢火星,主横发横破,需见好就收'] : [],
scoreImpact: 10,
tags: ['事业', '性格'],
version: this.version
});
}
// 紫府同宫
if (this.containsAll(mingGongStars, ['紫微', '天府'])) {
patterns.push({
ruleId: 'ZW_STATIC_PATTERN_ZIFUTONGGONG_v1',
title: '紫府同宫格',
type: 'static',
description: '为人清高保守,好面子。主孤高,容易曲高和寡。',
boardEvidence: ['命宫同见紫微、天府两大主星'],
conflicts: [],
scoreImpact: 15,
tags: ['性格'],
version: this.version
});
}
// 铃贪/火贪
if (this.containsAll(starNames, ['贪狼', '火星'])) {
patterns.push({
ruleId: 'ZW_STATIC_PATTERN_HUOTAN_v1',
title: '火贪格',
type: 'static',
description: '主横发爆发。发家之后需守成置产,切勿持续冒险。',
boardEvidence: ['命宫三方四正见贪狼与火星交会'],
conflicts: this.containsAny(starNames, ['地空', '地劫']) ? ['遇空劫,爆发力大减'] : [],
scoreImpact: 20,
tags: ['财富', '事业'],
version: this.version
});
} else if (this.containsAll(starNames, ['贪狼', '铃星'])) {
patterns.push({
ruleId: 'ZW_STATIC_PATTERN_LINGTAN_v1',
title: '铃贪格',
type: 'static',
description: '主暗发,闷声发大财。需保持低调,不可炫耀。',
boardEvidence: ['命宫三方四正见贪狼与铃星交会'],
conflicts: this.containsAny(starNames, ['地空', '地劫']) ? ['遇空劫,横发变虚花'] : [],
scoreImpact: 20,
tags: ['财富'],
version: this.version
});
}
return patterns;
}
// 3. 专题宫位深度拆解
private analyzeTopic(palaceName: string, tag: string): RuleEvidence[] {
const evidences: RuleEvidence[] = [];
const palace = this.getPalaceByName(palaceName);
if (!palace) return evidences;
const stars = this.getSanFangSiZhengStars(palace);
const starNames = stars.map(s => s.name);
const jiCount = stars.filter(s => JI_XING.includes(s.name)).length;
const shaCount = stars.filter(s => SHA_XING.includes(s.name)).length;
if (jiCount >= 3) {
evidences.push({
ruleId: `ZW_STATIC_TOPIC_JI_${tag.toUpperCase()}_v1`,
title: `${tag}得力 (三方吉星云集)`,
type: 'static',
description: `在${tag}领域能获得极大外界助力,事半功倍。`,
boardEvidence: [`${palaceName}三方四正汇聚${jiCount}颗吉星`],
scoreImpact: 10,
tags: [tag],
version: this.version
});
}
if (shaCount >= 3) {
evidences.push({
ruleId: `ZW_STATIC_TOPIC_SHA_${tag.toUpperCase()}_v1`,
title: `${tag}波折 (三方煞星交冲)`,
type: 'static',
description: `在${tag}领域阻碍颇多,需付出数倍努力方能有成。`,
boardEvidence: [`${palaceName}三方四正逢${shaCount}颗煞星冲破`],
scoreImpact: -15,
tags: [tag],
version: this.version
});
}
// 特定星曜组合 (举例)
if (tag === '财富' && this.containsAll(starNames, ['武曲', '贪狼'])) {
evidences.push({
ruleId: `ZW_STATIC_TOPIC_WU_TAN_CAI_v1`,
title: `武贪照财帛`,
type: 'static',
description: `武曲贪狼临财,主晚发,三十岁后财运渐入佳境。`,
boardEvidence: [`财帛宫三方见武曲、贪狼`],
scoreImpact: 10,
tags: [tag],
version: this.version
});
}
return evidences;
}
// 4. 夹拱对拱特征
private analyzeInteractions(): RuleEvidence[] {
const interactions: RuleEvidence[] = [];
const mingGong = this.getPalaceByName('命宫');
if (!mingGong) return interactions;
const prevIndex = (mingGong.index + 11) % 12;
const nextIndex = (mingGong.index + 1) % 12;
const prevPalace = this.astrolabe.palaces.find(p => p.index === prevIndex);
const nextPalace = this.astrolabe.palaces.find(p => p.index === nextIndex);
if (prevPalace && nextPalace) {
const prevStars = [...prevPalace.majorStars, ...prevPalace.minorStars].map(s => s.name);
const nextStars = [...nextPalace.majorStars, ...nextPalace.minorStars].map(s => s.name);
// 双禄夹命
if (
(prevStars.includes('禄存') && nextStars.some(s => this.hasMutagen(nextPalace, '禄'))) ||
(nextStars.includes('禄存') && prevStars.some(s => this.hasMutagen(prevPalace, '禄')))
) {
interactions.push({
ruleId: 'ZW_STATIC_JIA_SHUANGLU_v1',
title: '双禄夹命',
type: 'static',
description: '生来带有极好的财运与资源背景,左右逢源。',
boardEvidence: [`${prevPalace.name}${nextPalace.name}见禄存与化禄夹命`],
scoreImpact: 20,
tags: ['财富', '事业'],
version: this.version
});
}
// 羊陀夹命
if ((prevStars.includes('擎羊') && nextStars.includes('陀罗')) || (prevStars.includes('陀罗') && nextStars.includes('擎羊'))) {
interactions.push({
ruleId: 'ZW_STATIC_JIA_YANGTUO_v1',
title: '羊陀夹命',
type: 'static',
description: '命局易受环境或他人掣肘,发展常感受限。',
boardEvidence: [`${prevPalace.name}${nextPalace.name}见擎羊与陀罗夹命`],
scoreImpact: -10,
tags: ['事业', '性格'],
version: this.version
});
}
}
return interactions;
}
// 5. 身命联动
private analyzeBodyMindLink(): RuleEvidence[] {
const evidences: RuleEvidence[] = [];
const shenGong = this.astrolabe.palaces.find(p => p.name.includes('身宫'));
if (shenGong) {
const isMingShenSame = shenGong.name.includes('命宫');
if (isMingShenSame) {
evidences.push({
ruleId: 'ZW_STATIC_LINK_MINGSHEN_SAME_v1',
title: '命身同宫',
type: 'static',
description: '先天禀赋与后天追求高度一致,性格执着,不易受外界改变。',
boardEvidence: ['身宫与命宫同度'],
scoreImpact: 0,
tags: ['性格'],
version: this.version
});
} else {
const baseName = shenGong.name.replace('(身宫)', '').trim();
evidences.push({
ruleId: `ZW_STATIC_LINK_SHEN_${baseName}_v1`,
title: `身入${baseName}`,
type: 'static',
description: `后天(三十岁后)的发展重心与价值观强烈倾向于${baseName}相关的领域。`,
boardEvidence: [`身宫落在${baseName}`],
scoreImpact: 0,
tags: ['性格', '事业'],
version: this.version
});
}
}
return evidences;
}
// Helper 方法
private getPalaceByName(name: string): PalaceData | undefined {
return this.astrolabe.palaces.find(p => p.name.startsWith(name));
}
private getSanFangSiZhengStars(palace: PalaceData): StarData[] {
const idx = palace.index;
const indices = [
idx,
(idx + 4) % 12, // 三合1
(idx + 8) % 12, // 三合2
(idx + 6) % 12, // 对宫
];
const stars: StarData[] = [];
indices.forEach(i => {
const p = this.astrolabe.palaces.find(p => p.index === i);
if (p) {
stars.push(...p.majorStars, ...p.minorStars);
}
});
return stars;
}
private containsAll(arr: string[], targets: string[]): boolean {
return targets.every(t => arr.includes(t));
}
private containsAny(arr: string[], targets: string[]): boolean {
return targets.some(t => arr.includes(t));
}
private hasMutagen(palace: PalaceData, mutagen: string): boolean {
return [...palace.majorStars, ...palace.minorStars].some(s => s.mutagen === mutagen);
}
}