Spaces:
Sleeping
Sleeping
| 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); | |
| } | |
| } | |