/** * Jyotish Deep Analysis Engine v1.0 * 核心计算:Raman功能吉凶 · PACDARES · 宫位互影响 · 分盘交叉验证 · Vargottama · 频率分析 */ import { SIGNS, SIGNS_CN, SIGN_LORDS, PLANET_CN, PLANET_SYMBOLS, EXALTATION, DEBILITATION, PLANET_ASPECTS } from './jyotish-engine.js'; import { VARGA_DEFS } from './jyotish-advanced.js'; // ============================================================================ // 一、B.V. Raman 功能吉凶星表 // ============================================================================ export const RAMAN_TABLES = { Aries: { best:['Jupiter'], good:['Mars','Sun'], bad:['Saturn','Mercury','Venus'], worst:['Mercury'], neutral:[], yk:null, maraka:['Saturn','Mercury'] }, Taurus: { best:['Saturn'], good:['Mercury','Mars','Sun'], bad:['Jupiter','Venus','Moon'], worst:[], neutral:['Venus'], yk:null, maraka:['Mercury','Jupiter'] }, Gemini: { best:['Venus'], good:[], bad:['Mars'], worst:[], neutral:['Moon','Mercury'], yk:null, maraka:['Moon','Jupiter'] }, Cancer: { best:['Mars'], good:['Jupiter'], bad:['Saturn','Mercury'], worst:[], neutral:['Venus'], yk:'Mars', maraka:['Sun','Saturn'] }, Leo: { best:['Mars'], good:['Sun','Jupiter'], bad:['Venus','Saturn'], worst:[], neutral:['Moon'], yk:'Mars', maraka:['Mercury','Venus'] }, Virgo: { best:['Venus'], good:[], bad:['Mars','Jupiter','Moon'], worst:['Mars'], neutral:['Mercury'], yk:null, maraka:['Venus','Mars'] }, Libra: { best:['Saturn'], good:['Mercury','Venus'], bad:['Jupiter','Sun','Mars'], worst:['Jupiter'], neutral:['Moon'], yk:'Saturn', maraka:['Mars','Jupiter'] }, Scorpio: { best:['Jupiter'], good:['Moon','Sun','Mars'], bad:['Venus','Mercury'], worst:['Venus'], neutral:[], yk:null, maraka:['Jupiter','Venus'] }, Sagittarius: { best:['Mars','Sun'], good:[], bad:['Venus','Saturn','Mercury'], worst:[], neutral:['Jupiter','Moon'], yk:null, maraka:['Saturn','Mercury'] }, Capricorn: { best:['Venus'], good:['Mercury','Saturn'], bad:['Mars','Jupiter','Moon'], worst:['Mars'], neutral:['Sun'], yk:'Venus', maraka:['Saturn','Moon'] }, Aquarius: { best:['Venus'], good:['Sun','Mars'], bad:['Jupiter','Moon'], worst:[], neutral:['Mercury'], yk:'Venus', maraka:['Mercury','Sun'] }, Pisces: { best:['Moon','Mars'], good:[], bad:['Saturn','Sun','Venus','Mercury'], worst:[], neutral:['Jupiter'], yk:null, maraka:['Venus','Mars'] }, }; export const HOUSE_DOMAINS = { 1: {name:'自我·身体·人格',themes:['身体健康','人格特质','人生方向']}, 2: {name:'财富·语言·家庭',themes:['财富积累','语言能力','家庭背景']}, 3: {name:'沟通·兄弟·勇气',themes:['沟通表达','兄弟姐妹','勇气行动']}, 4: {name:'家庭·房产·母亲',themes:['母亲','房产土地','内心安全感']}, 5: {name:'创造·子女·恋爱',themes:['子女','恋爱','创造力','投资']}, 6: {name:'职场·健康·服务',themes:['职场冲突','疾病健康','敌人对手']}, 7: {name:'婚姻·伴侣·合作',themes:['婚姻关系','商业合作','伴侣特质']}, 8: {name:'转化·遗产·神秘',themes:['死亡转化','遗产继承','他人资源']}, 9: {name:'宗教·哲学·导师',themes:['长途旅行','导师上师','父亲']}, 10: {name:'事业·社会·权威',themes:['事业职业','社会地位','职业成就']}, 11: {name:'收入·朋友·愿望',themes:['收入财富','朋友社交','愿望实现']}, 12: {name:'灵性·损失·解脱',themes:['灵性修行','隐藏事物','外国事务']}, }; // ============================================================================ // 二、工具函数 // ============================================================================ const P_NAMES = ['Sun','Moon','Mars','Mercury','Jupiter','Venus','Saturn','Rahu','Ketu']; export function getFunctionalNature(p, asc) { const t = RAMAN_TABLES[asc]; if(!t) return 'neutral'; if(t.yk===p) return 'yogakaraka'; if(t.best.includes(p)) return 'best_benefic'; if(t.good.includes(p)) return 'benefic'; if(t.neutral.includes(p)) return 'neutral'; if(t.worst.includes(p)) return 'worst'; if(t.bad.includes(p)) return 'malefic'; return 'neutral'; } export function getHousesRuled(p, asc) { const ai=SIGNS.indexOf(asc); const h=[]; for(let i=1;i<=12;i++) if(SIGN_LORDS[SIGNS[(ai+i-1)%12]]===p) h.push(i); return h; } export function getHouseType(h) { if([1,4,7,10].includes(h)) return 'Kendra角宫'; if([5,9].includes(h)) return 'Trikona三方'; if([3,6,10,11].includes(h)) return 'Upachaya成长'; if([6,8,12].includes(h)) return 'Dusthana凶宫'; return '普通'; } function vargaSI(degIS, si, d) { const sw=30/d, seg=Math.floor(degIS/sw); switch(d){ case 1:return si; case 2:return(si%2===0)?(degIS<15?4:3):(degIS<15?3:4); case 3:return(si+seg*4)%12; case 4:return(si+seg)%12; case 7:return(si%2===0)?seg%12:(seg+6)%12; case 9:return[0,3,6,9].includes(si)?(si+seg)%12:[1,4,7,10].includes(si)?(si+8+seg)%12:(si+4+seg)%12; case 10:return(si%2===0?(9+seg):seg)%12; case 12:return(si+seg)%12; case 16:return seg%12; case 20:return(si+seg)%12; case 24:return(4+seg)%12; case 30:return si%2===0?(seg<5?0:seg<10?5:seg<18?2:seg<25?6:8):(seg<5?4:seg<10?11:seg<18?8:seg<25?1:6); case 40:return(si%2===0?seg:seg+3)%12; case 45:return((si%3===0?0:si%3===1?4:8)+seg)%12; case 60:return seg%12; default:return(si+seg)%12; } } function planetStatus(pn, sign) { if(EXALTATION[pn]===sign) return '入旺'; if(DEBILITATION[pn]===sign) return '落陷'; if(SIGN_LORDS[sign]===pn) return '入庙'; return '中性'; } // ============================================================================ // 三、PACDARES 八维分析 // ============================================================================ export function computePACDARES(planets, asc) { const ai=SIGNS.indexOf(asc), t=RAMAN_TABLES[asc]; const r={P:[],A:[],C:[],D:[],Ar:[],R:[],E:[],S:[]}; // P: Position for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error)continue; r.P.push({planet:pn,pcn:PLANET_CN[pn],sign:p.sign,scn:p.sign_cn,house:p.house,deg:p.degree_in_sign?.toFixed(2),status:p.status,retro:p.retrograde,fn:getFunctionalNature(pn,asc),hr:getHousesRuled(pn,asc),ht:p.house?getHouseType(p.house):'',combust:p.combust||false}); } // A: Aspect received for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error||p.house==null)continue; const recv=[]; for(const f of P_NAMES){if(f===pn)continue;const fp=planets[f];if(!fp||fp.error||fp.house==null)continue; for(const off of(PLANET_ASPECTS[f]||[7])){ if(((fp.house-1+off)%12)+1===p.house){ const fn=getFunctionalNature(f,asc); recv.push({from:f,fcn:PLANET_CN[f],type:off===7?'对冲':(off===5||off===9)?'三分':off===4?'四分':off===8?'八分':`${off}宫`,fn,impact:['best_benefic','benefic','yogakaraka'].includes(fn)?'吉':['malefic','worst'].includes(fn)?'凶':'中'}); } } } if(recv.length)r.A.push({planet:pn,pcn:PLANET_CN[pn],house:p.house,received:recv}); } // C: Conjunction for(let i=0;iSIGN_LORDS[SIGNS[(ai+h-1)%12]])); const wl=[...wL]; for(let i=0;iplanets[pn]&&!planets[pn].error&&planets[pn].house===h2)&&!P_NAMES.some(pn=>planets[pn]&&!planets[pn].error&&planets[pn].house===h12)) r.Ar.push({type:'Kemadruma',pcn:'月亮',house:moon.house,desc:'月亮2/12宫无星 — 情绪孤独'}); } for(const h of[6,8,12]){const lord=SIGN_LORDS[SIGNS[(ai+h-1)%12]];const lp=planets[lord];if(!lp||lp.error||![6,8,12].includes(lp.house))continue; r.Ar.push({type:'凶宫主落凶宫',pcn:PLANET_CN[lord],house:lp.house,desc:`H${h}主落H${lp.house}`}); } // R: Raja Yoga const kL=new Set([1,4,7,10].map(h=>SIGN_LORDS[SIGNS[(ai+h-1)%12]])); const tL=new Set([1,5,9].map(h=>SIGN_LORDS[SIGNS[(ai+h-1)%12]])); for(const k of kL)for(const tt of tL){if(k===tt)continue;const pk=planets[k],pt=planets[tt];if(!pk||!pt||pk.error||pt.error||pk.house!==pt.house)continue; r.R.push({type:'Raja Yoga',lcn:`${PLANET_CN[k]}+${PLANET_CN[tt]}`,house:pk.house,str:[1,4,7,10].includes(pk.house)?'极强':[5,9].includes(pk.house)?'强':'中'}); } if(t?.yk){const yp=planets[t.yk];if(yp&&!yp.error)r.R.push({type:'Yogakaraka',lcn:PLANET_CN[t.yk],house:yp.house,str:yp.status==='入庙'||yp.status==='入旺'?'极强':'中强'});} // E: Exchange for(let h1=1;h1<=12;h1++){const l1=SIGN_LORDS[SIGNS[(ai+h1-1)%12]];const lp1=planets[l1];if(!lp1||lp1.error||!lp1.house)continue; const h2=lp1.house;const l2=SIGN_LORDS[SIGNS[(ai+h2-1)%12]];if(l2===l1)continue;const lp2=planets[l2];if(!lp2||lp2.error||lp2.house!==h1||h1>=h2)continue; r.E.push({type:'Parivartana',houses:[h1,h2],lcn:`${PLANET_CN[l1]}+${PLANET_CN[l2]}`,desc:`H${h1}主(${PLANET_CN[l1]})在H${h2}↔H${h2}主(${PLANET_CN[l2]})在H${h1}`, nature:[6,8,12].includes(h1)&&[6,8,12].includes(h2)?'Vipareeta':[6,8,12].includes(h1)||[6,8,12].includes(h2)?'混合':'吉'}); } // S: Special for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error)continue; if(p.retrograde)r.S.push({type:'逆行',pcn:PLANET_CN[pn],desc:`${PLANET_CN[pn]}逆行 — 能量内化`}); if(p.combust)r.S.push({type:'燃烧',pcn:PLANET_CN[pn],desc:`${PLANET_CN[pn]}燃烧(${p.combust_degree}°)`}); if(p.status==='落陷')r.S.push({type:'落陷',pcn:PLANET_CN[pn],desc:`${PLANET_CN[pn]}落陷在${p.sign_cn}`}); if(p.status==='入旺')r.S.push({type:'入旺',pcn:PLANET_CN[pn],desc:`${PLANET_CN[pn]}入旺在${p.sign_cn}`}); } return r; } // ============================================================================ // 四、宫位互影响矩阵 // ============================================================================ export function computeHouseInfluence(planets, asc) { const ai=SIGNS.indexOf(asc), matrix=[]; for(let h=1;h<=12;h++){ const si=(ai+h-1)%12,sign=SIGNS[si],lord=SIGN_LORDS[sign]; const items=[]; // 宫内 for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error||p.house!==h)continue; const fn=getFunctionalNature(pn,asc); const sc=fn==='yogakaraka'?3:fn==='best_benefic'?2:fn==='benefic'?1:fn==='neutral'?0:fn==='malefic'?-1:fn==='worst'?-2:0; items.push({src:`${PLANET_CN[pn]}(宫内)`,fn,sc,detail:PLANET_CN[pn]+fn}); } // 相位 for(const f of P_NAMES){const fp=planets[f];if(!fp||fp.error||fp.house==null)continue; for(const off of(PLANET_ASPECTS[f]||[7])){ if(((fp.house-1+off)%12)+1===h){const fn=getFunctionalNature(f,asc); const sc=fn==='yogakaraka'?2:fn==='best_benefic'?1.5:fn==='benefic'?1:fn==='neutral'?0:fn==='malefic'?-1:fn==='worst'?-1.5:0; items.push({src:`${PLANET_CN[f]}(${off}宫相位)`,fn,sc,detail:PLANET_CN[f]});break;} } } // 宫主 const lp=planets[lord];if(lp&&!lp.error&&lp.house){ const sc=[1,4,5,7,9,10,11].includes(lp.house)?1:-0.5; items.push({src:`宫主星${PLANET_CN[lord]}(H${lp.house})`,fn:getFunctionalNature(lord,asc),sc,detail:`${PLANET_CN[lord]}${lp.status}在H${lp.house}`}); } const total=Math.round(items.reduce((s,i)=>s+i.sc,0)*10)/10; matrix.push({house:h,sign,scn:SIGNS_CN[sign],lord,lcn:PLANET_CN[lord]||lord,items,total, verdict:total>=2?'强力':total>=0.5?'吉':total>=-0.5?'中':total>=-2?'弱':'受克'}); } return matrix; } // ============================================================================ // 五、Vargottama 检测 // ============================================================================ export function detectVargottama(planets) { const r=[]; for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error)continue; const psi=SIGNS.indexOf(p.sign),d9si=vargaSI(p.degree_in_sign,psi,9); if(p.sign===SIGNS[d9si])r.push({planet:pn,pcn:PLANET_CN[pn],d1:p.sign_cn,d9:SIGNS_CN[SIGNS[d9si]]}); } return r; } // ============================================================================ // 六、行星频率分析 // ============================================================================ export function computeFrequency(planets) { const r={}; for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error)continue; const psi=SIGNS.indexOf(p.sign),freq={}; for(const v of VARGA_DEFS){const vsi=v.d===1?psi:vargaSI(p.degree_in_sign,psi,v.d);freq[SIGNS[vsi]]=(freq[SIGNS[vsi]]||0)+1;} const sorted=Object.entries(freq).sort((a,b)=>b[1]-a[1]); const top=sorted[0],total=VARGA_DEFS.length,pct=Math.round(top[1]/total*100); r[pn]={planet:pn,pcn:PLANET_CN[pn],topSign:top[0],topScn:SIGNS_CN[top[0]],count:top[1],pct, level:pct>=50?'极高频':pct>=40?'高频':pct>=30?'中高频':pct>=20?'中等':'低频', dist:sorted.slice(0,3).map(([s,c])=>({s,scn:SIGNS_CN[s],c,p:Math.round(c/total*100)}))}; } return r; } // ============================================================================ // 七、D1 × D9 × D10 三角验证 // ============================================================================ export function computeTriangle(planets) { const r=[]; for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error)continue; const psi=SIGNS.indexOf(p.sign); const d9si=vargaSI(p.degree_in_sign,psi,9),d10si=vargaSI(p.degree_in_sign,psi,10); const d9s=SIGNS[d9si],d10s=SIGNS[d10si]; const d1st=p.status,d9st=planetStatus(pn,d9s),d10st=planetStatus(pn,d10s); let v='一致'; if(['入庙','入旺'].includes(d1st)&&['落陷'].includes(d9st))v='D1强D9弱(承诺未兑现)'; else if(['落陷'].includes(d1st)&&['入庙','入旺'].includes(d9st))v='D1弱D9强(绝地反击)'; else if(['入庙','入旺'].includes(d1st)&&['入庙','入旺'].includes(d9st))v='双重强势'; else if(['落陷'].includes(d1st)&&['落陷'].includes(d9st))v='双重弱势'; const vg=p.sign===d9s; r.push({planet:pn,pcn:PLANET_CN[pn],d1sign:p.sign_cn,d1st,d9sign:SIGNS_CN[d9s],d9st,d10sign:SIGNS_CN[d10s],d10st,verdict:v,vargottama:vg}); } return r; } // ============================================================================ // 八、Raman 宫位六步法(综合评估每宫吉凶) // ============================================================================ export function computeRamanHouseScore(planets, asc) { const ai=SIGNS.indexOf(asc), scores=[]; for(let h=1;h<=12;h++){ const si=(ai+h-1)%12,sign=SIGNS[si],lord=SIGN_LORDS[sign]; let pos=0,neg=0,details=[]; // Step1: 宫内行星 for(const pn of P_NAMES){const p=planets[pn];if(!p||p.error||p.house!==h)continue; const fn=getFunctionalNature(pn,asc); if(['best_benefic','benefic','yogakaraka'].includes(fn)){pos+=2;details.push(`✓${PLANET_CN[pn]}(吉)在宫内`);} else if(['malefic','worst'].includes(fn)){neg+=2;details.push(`✗${PLANET_CN[pn]}(凶)在宫内`);} else{pos+=0.5;details.push(`~${PLANET_CN[pn]}(中性)在宫内`);} } // Step2: 相位 for(const f of P_NAMES){const fp=planets[f];if(!fp||fp.error||fp.house==null)continue; for(const off of(PLANET_ASPECTS[f]||[7])){ if(((fp.house-1+off)%12)+1===h){ const fn=getFunctionalNature(f,asc); if(['best_benefic','benefic','yogakaraka'].includes(fn)){pos+=1;details.push(`✓${PLANET_CN[f]}吉相位`);} else if(['malefic','worst'].includes(fn)){neg+=1;details.push(`✗${PLANET_CN[f]}凶相位`);} break; } } } // Step3: 宫主星 const lp=planets[lord]; if(lp&&!lp.error&&lp.house){ if([1,4,5,7,9,10,11].includes(lp.house)){pos+=1.5;details.push(`✓宫主${PLANET_CN[lord]}在H${lp.house}(${lp.status})`);} else if([6,8,12].includes(lp.house)){neg+=1.5;details.push(`✗宫主${PLANET_CN[lord]}在H${lp.house}(凶宫)`);} else{details.push(`~宫主${PLANET_CN[lord]}在H${lp.house}`);} if(lp.status==='入庙'||lp.status==='入旺'){pos+=1;details.push(`✓宫主${lp.status}`);} if(lp.status==='落陷'){neg+=1;details.push(`✗宫主落陷`);} } const net=Math.round((pos-neg)*10)/10; scores.push({house:h,sign,scn:SIGNS_CN[sign],lord,lcn:PLANET_CN[lord]||lord,pos,neg,net,details, grade:net>=3?'A':net>=1?'B':net>=-1?'C':net>=-3?'D':'F'}); } return scores; } // ============================================================================ // 七、Trikona-Kendra 三方四正映射分析 // ============================================================================ const SIGNS_LIST = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo','Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces']; const LORD_OF = {Aries:'Mars',Taurus:'Venus',Gemini:'Mercury',Cancer:'Moon',Leo:'Sun',Virgo:'Mercury',Libra:'Venus',Scorpio:'Mars',Sagittarius:'Jupiter',Capricorn:'Saturn',Aquarius:'Saturn',Pisces:'Jupiter'}; function lordOfHouse(ascSign, h) { const ai = SIGNS_LIST.indexOf(ascSign); const signIdx = (ai + h - 1) % 12; return LORD_OF[SIGNS_LIST[signIdx]]; } function signOfHouse(ascSign, h) { const ai = SIGNS_LIST.indexOf(ascSign); return SIGNS_LIST[(ai + h - 1) % 12]; } /** * 计算三方四正映射分析 * Trikona(1-5-9) 和 Kendra(1-4-7-10) 宫主星间的互落关系 */ export function computeTrikonaKendra(planets, ascSign) { const trikonaHouses = [1, 5, 9]; const kendraHouses = [1, 4, 7, 10]; const allKeyHouses = [1, 4, 5, 7, 9, 10]; // 计算每个关键宫的主星及其落宫 const houseLords = {}; for (const h of allKeyHouses) { const lord = lordOfHouse(ascSign, h); const lp = planets[lord]; houseLords[h] = { house: h, lord, lord_cn: PLANET_CN[lord], sign: signOfHouse(ascSign, h), sign_cn: SIGNS_CN[signOfHouse(ascSign, h)], lordInHouse: lp && !lp.error ? lp.house : null, lordStatus: lp && !lp.error ? lp.status : null, lordRetro: lp && !lp.error ? lp.retrograde : false, }; } // 三方映射:1→5→9 的主星互落 const trikonaConnections = []; for (let i = 0; i < trikonaHouses.length; i++) { for (let j = i + 1; j < trikonaHouses.length; j++) { const h1 = trikonaHouses[i], h2 = trikonaHouses[j]; const l1 = houseLords[h1], l2 = houseLords[h2]; // 同宫 if (l1.lordInHouse === h2 && l2.lordInHouse === h1) { trikonaConnections.push({ type: 'mutual', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)↔${l2.lord_cn}(${h2}主) 互换`, quality: 'excellent' }); } else if (l1.lordInHouse === h2) { trikonaConnections.push({ type: 'one-way', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)落入${h2}宫`, quality: 'good' }); } else if (l2.lordInHouse === h1) { trikonaConnections.push({ type: 'one-way', from: h2, to: h1, desc: `${l2.lord_cn}(${h2}主)落入${h1}宫`, quality: 'good' }); } // 同宫(两主星在同一宫) if (l1.lordInHouse && l1.lordInHouse === l2.lordInHouse) { trikonaConnections.push({ type: 'conjunction', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)+${l2.lord_cn}(${h2}主)同在H${l1.lordInHouse}`, quality: 'strong' }); } } } // 四正映射:1-4-7-10 的主星互落 const kendraConnections = []; for (let i = 0; i < kendraHouses.length; i++) { for (let j = i + 1; j < kendraHouses.length; j++) { const h1 = kendraHouses[i], h2 = kendraHouses[j]; const l1 = houseLords[h1], l2 = houseLords[h2]; if (l1.lordInHouse === h2 && l2.lordInHouse === h1) { kendraConnections.push({ type: 'mutual', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)↔${l2.lord_cn}(${h2}主) 互换`, quality: 'excellent' }); } else if (l1.lordInHouse === h2) { kendraConnections.push({ type: 'one-way', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)落入${h2}宫`, quality: 'good' }); } else if (l2.lordInHouse === h1) { kendraConnections.push({ type: 'one-way', from: h2, to: h1, desc: `${l2.lord_cn}(${h2}主)落入${h1}宫`, quality: 'good' }); } if (l1.lordInHouse && l1.lordInHouse === l2.lordInHouse) { kendraConnections.push({ type: 'conjunction', from: h1, to: h2, desc: `${l1.lord_cn}(${h1}主)+${l2.lord_cn}(${h2}主)同在H${l1.lordInHouse}`, quality: 'strong' }); } } } // 三方×四正交叉连接 const crossConnections = []; for (const th of trikonaHouses) { for (const kh of kendraHouses) { if (th === kh) continue; // 跳过1宫(同属两组) const tl = houseLords[th], kl = houseLords[kh]; // 三方主落入四正 if (tl.lordInHouse === kh) { crossConnections.push({ type: 'trikona-to-kendra', from: th, to: kh, desc: `${tl.lord_cn}(${th}主/三方)→H${kh}(四正)`, quality: 'raja' }); } // 四正主落入三方 if (kl.lordInHouse === th) { crossConnections.push({ type: 'kendra-to-trikona', from: kh, to: th, desc: `${kl.lord_cn}(${kh}主/四正)→H${th}(三方)`, quality: 'raja' }); } // 互换 = 大 Raja Yoga if (tl.lordInHouse === kh && kl.lordInHouse === th) { crossConnections.push({ type: 'mutual-raja', from: th, to: kh, desc: `★ ${tl.lord_cn}(${th}主)↔${kl.lord_cn}(${kh}主) 互换 = Raja Yoga`, quality: 'maha-raja' }); } } } // 整体评估 const totalPositive = trikonaConnections.filter(c => c.quality !== 'poor').length + kendraConnections.filter(c => c.quality !== 'poor').length + crossConnections.length; const hasMahaRaja = crossConnections.some(c => c.quality === 'maha-raja'); const hasRaja = crossConnections.some(c => c.quality === 'raja' || c.quality === 'maha-raja'); let overallRating = '普通'; if (hasMahaRaja) overallRating = '卓越 — 大帝王格局'; else if (hasRaja && totalPositive >= 4) overallRating = '优秀 — 强力 Raja Yoga'; else if (totalPositive >= 4) overallRating = '良好 — 多重三方四正连接'; else if (totalPositive >= 2) overallRating = '中等 — 有一定三方四正连接'; else if (totalPositive >= 1) overallRating = '一般 — 少量连接'; return { houseLords, trikonaConnections, kendraConnections, crossConnections, overallRating, hasMahaRaja, hasRaja, }; }