a4f8620a71
## 新增模块 (16个) ### P0 精度修复 - ashtakavarga: calc_prastara_av() + calc_sodhita_av() - kakshya.py: Kakshya评分系统 (8区间×3.75°) - shadbala.py: Sputa Drishti + Yuddha Bala ### P1 核心升级 - bhava_bala.py: 宫位三元力量 (jyotishganit MIT) - pancha_mahapurusha.py: PMC完整检测含4层失效条件 - sade_sati.py: Sade Sati+Kantaka Shani - sudarshana_chakra.py: 三参考点盘+收敛分析 - tajika.py: Sahams 7→36 + Tajika Yogas 10种 - birth_time_rectifier.py: 生时矫正 ### P2 覆盖扩展 - kp_system.py: KP Sublord+ABCD Significator (diliprk/VedicAstro MIT) - synastry.py: 16因子合盘36分制 (dashaflow MIT) - muhurtha_election.py: 6活动选举 (dashaflow MIT) - career_analysis.py: 结构化事业引擎 - relationship_analysis.py: 结构化感情引擎 - conditional_dashas.py: Dwisaptati+Shattrimsa+Dwadashottari - divisional_charts_extended: D81/D108/D144 - remedies.py: 5类补救系统 ## 修改文件 jaimini/dasha_calculator/shadbala/SKILL.md/COVERAGE_AUDIT等12个 ## 开源复用: 4个MIT项目
247 lines
8.6 KiB
Python
247 lines
8.6 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Bhava Bala(宫位力量)计算模块
|
||
基于jyotishganit (MIT License) 核心算法适配
|
||
|
||
三组件:
|
||
1. Bhava Adhipathi Bala - 宫位主星的Shadbala总分
|
||
2. Bhava Dig Bala - 基于星座性质的方向力量
|
||
3. Bhava Drik Bala - 基于Sputa Drishti的行星对宫位中点相位
|
||
"""
|
||
|
||
from typing import Dict, List
|
||
|
||
SIGNS = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo',
|
||
'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
|
||
|
||
SIGN_LORDS = {
|
||
'Aries': 'Mars', 'Taurus': 'Venus', 'Gemini': 'Mercury', 'Cancer': 'Moon',
|
||
'Leo': 'Sun', 'Virgo': 'Mercury', 'Libra': 'Venus', 'Scorpio': 'Mars',
|
||
'Sagittarius': 'Jupiter', 'Capricorn': 'Saturn', 'Aquarius': 'Saturn', 'Pisces': 'Jupiter'
|
||
}
|
||
|
||
# 星座性质分类(BPHS标准)
|
||
# nara=人类, chatushpada=四足, jalachara=水栖, keeta=虫类, vanaspati=植物
|
||
SIGN_NATURE = {
|
||
'Aries': 'chatushpada', 'Taurus': 'chatushpada',
|
||
'Gemini': 'nara', 'Cancer': 'jalachara',
|
||
'Leo': 'chatushpada', 'Virgo': 'nara',
|
||
'Libra': 'nara', 'Scorpio': 'keeta',
|
||
'Sagittarius': 'nara', 'Capricorn': 'jalachara',
|
||
'Aquarius': 'nara', 'Pisces': 'jalachara',
|
||
}
|
||
|
||
# 宫位力量基于星座性质(BPHS标准,单位Virupas)
|
||
# 索引0-11对应第1-12宫
|
||
BHAVA_STRENGTH_FROM_SIGN_NATURE = {
|
||
'nara': [30, 20, 10, 20, 10, 20, 30, 20, 10, 20, 10, 20],
|
||
'chatushpada': [30, 20, 10, 20, 10, 20, 30, 20, 10, 20, 10, 20],
|
||
'jalachara': [20, 30, 10, 30, 10, 30, 20, 30, 10, 30, 10, 30],
|
||
'keeta': [10, 20, 30, 20, 30, 20, 10, 20, 30, 20, 30, 20],
|
||
'vanaspati': [20, 10, 20, 10, 20, 30, 20, 10, 20, 10, 20, 30],
|
||
}
|
||
|
||
# Sputa Drishti值表(基于角距离的连续相位力量)
|
||
def _get_sputa_drishti(angle_diff: float) -> float:
|
||
"""基于jxotishganit MIT算法,将精确角距离转换为Sputa Drishti值(0-60)"""
|
||
ad = angle_diff % 360
|
||
if ad > 180:
|
||
ad = 360 - ad
|
||
|
||
if ad <= 1.0: return 60.0
|
||
if ad <= 3.0: return 57.0
|
||
if ad <= 7.0: return 51.0
|
||
if ad <= 10.0: return 45.0
|
||
if ad <= 15.0: return 40.5
|
||
if ad <= 20.0: return 30.0
|
||
if ad <= 25.0: return 22.5
|
||
if ad <= 30.0: return 15.0
|
||
if ad <= 40.0: return 12.0
|
||
if ad <= 50.0: return 9.0
|
||
if ad <= 60.0: return 6.0
|
||
if ad <= 75.0: return 4.5
|
||
if ad <= 90.0: return 3.0
|
||
if ad <= 120.0: return 2.25
|
||
if ad <= 150.0: return 1.5
|
||
return 0.0
|
||
|
||
|
||
def calc_bhava_adhipathi_bala(house_signs: List[str], planet_shadbala: Dict) -> List[float]:
|
||
"""
|
||
Bhava Adhipathi Bala:宫位主星的Shadbala总分作为宫位力量基础。
|
||
|
||
Args:
|
||
house_signs: 12宫位的星座名称列表
|
||
planet_shadbala: 行星Shadbala总分 dict(Virupas)
|
||
|
||
Returns:
|
||
12个宫位的adhipathi bala值
|
||
"""
|
||
bala = []
|
||
for sign_name in house_signs:
|
||
lord = SIGN_LORDS.get(sign_name, '')
|
||
bala.append(planet_shadbala.get(lord, 0))
|
||
return bala
|
||
|
||
|
||
def calc_bhava_dig_bala(house_signs: List[str], house_degrees: List[float]) -> List[float]:
|
||
"""
|
||
Bhava Dig Bala:基于星座性质的宫位方向力量。
|
||
|
||
Args:
|
||
house_signs: 12宫位的星座名称列表
|
||
house_degrees: 12宫位的宫头度数列表
|
||
|
||
Returns:
|
||
12个宫位的dig bala值
|
||
"""
|
||
bala = []
|
||
for hno, sign_name in enumerate(house_signs):
|
||
nature_key = sign_name
|
||
deg = house_degrees[hno] if hno < len(house_degrees) else 15.0
|
||
|
||
# Sagittarius和Capricorn的双重性质处理
|
||
if sign_name == 'Sagittarius':
|
||
nature_key = 'Sagittarius_first_half' if deg < 15.0 else 'Sagittarius_second_half'
|
||
elif sign_name == 'Capricorn':
|
||
nature_key = 'Capricorn_first_half' if deg < 15.0 else 'Capricorn_second_half'
|
||
|
||
# 处理双性星座
|
||
if 'first_half' in nature_key:
|
||
# Sagittarius前半=nara, Capricorn前半=jalachara
|
||
real_nature = 'nara' if 'Sagittarius' in nature_key else 'jalachara'
|
||
elif 'second_half' in nature_key:
|
||
real_nature = 'chatushpada' if 'Sagittarius' in nature_key else 'jalachara'
|
||
else:
|
||
real_nature = SIGN_NATURE.get(sign_name, 'nara')
|
||
|
||
# 查找对应值
|
||
strengths = BHAVA_STRENGTH_FROM_SIGN_NATURE.get(real_nature, BHAVA_STRENGTH_FROM_SIGN_NATURE['nara'])
|
||
bala.append(float(strengths[hno] if hno < len(strengths) else 20))
|
||
|
||
return bala
|
||
|
||
|
||
def calc_bhava_drik_bala(house_signs: List[str], house_degrees: List[float],
|
||
asc_sign: str, asc_degree: float,
|
||
planet_positions: Dict, planet_shadbala: Dict) -> List[float]:
|
||
"""
|
||
Bhava Drik Bala:所有行星对宫位中点(Bhava Madhya)的Sputa Drishti相位。
|
||
|
||
基于jyotishganit MIT算法:计算行星到宫位中点的精确角距离,
|
||
使用Sputa Drishti将吉星相位减凶星相位后除以4。
|
||
|
||
Args:
|
||
house_signs: 12宫位的星座名称
|
||
house_degrees: 12宫位的宫头度数
|
||
asc_sign: 上升星座名称
|
||
asc_degree: 上升度数(0-30)
|
||
planet_positions: 行星位置 dict {planet: {'sign': str, 'degree': float}}
|
||
planet_shadbala: 行星Shadbala dict
|
||
|
||
Returns:
|
||
12个宫位的drik bala值
|
||
"""
|
||
BENEFICS = ['Jupiter', 'Venus', 'Mercury']
|
||
MALEFICS = ['Saturn', 'Mars', 'Sun']
|
||
|
||
asc_sign_idx = SIGNS.index(asc_sign) if asc_sign in SIGNS else 0
|
||
asc_long = asc_sign_idx * 30 + asc_degree
|
||
|
||
bala = []
|
||
for house_idx in range(12):
|
||
# 计算宫位中点(Equal House系统中,宫头 + 15°)
|
||
house_cusp = (asc_long + house_idx * 30) % 360
|
||
house_midpoint = (house_cusp + 15) % 360
|
||
|
||
benefic_sputa = 0.0
|
||
malefic_sputa = 0.0
|
||
|
||
for planet_name, planet_data in planet_positions.items():
|
||
if planet_name not in ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn']:
|
||
continue
|
||
|
||
p_sign = planet_data.get('sign', '')
|
||
p_deg = planet_data.get('degree', 0)
|
||
if p_sign not in SIGNS:
|
||
continue
|
||
|
||
p_sign_idx = SIGNS.index(p_sign)
|
||
p_long = p_sign_idx * 30 + (p_deg % 30)
|
||
|
||
# 角距离
|
||
diff = (p_long - house_midpoint + 180) % 360 - 180 # -180 to +180
|
||
dist_deg = abs(diff)
|
||
|
||
# Sputa Drishti值
|
||
sputa = _get_sputa_drishti(dist_deg)
|
||
|
||
if planet_name in BENEFICS:
|
||
benefic_sputa += sputa
|
||
elif planet_name in MALEFICS:
|
||
malefic_sputa += sputa
|
||
|
||
drishtipinda = benefic_sputa - malefic_sputa
|
||
house_drikbala = min(drishtipinda / 4.0, 20.0)
|
||
bala.append(round(house_drikbala, 3))
|
||
|
||
return bala
|
||
|
||
|
||
def calc_bhava_bala(house_signs: List[str], house_degrees: List[float],
|
||
asc_sign: str, asc_degree: float,
|
||
planet_positions: Dict, planet_shadbala: Dict) -> Dict:
|
||
"""
|
||
计算完整Bhava Bala(宫位三元力量)。
|
||
|
||
Args:
|
||
house_signs: 12宫位的星座名称
|
||
house_degrees: 12宫位的宫头度数
|
||
asc_sign: 上升星座名称
|
||
asc_degree: 上升度数
|
||
planet_positions: 行星位置
|
||
planet_shadbala: 行星Shadbala总分
|
||
|
||
Returns:
|
||
完整的Bhava Bala计算结果
|
||
"""
|
||
adhipathi = calc_bhava_adhipathi_bala(house_signs, planet_shadbala)
|
||
dig_bala = calc_bhava_dig_bala(house_signs, house_degrees)
|
||
drik_bala = calc_bhava_drik_bala(house_signs, house_degrees, asc_sign, asc_degree,
|
||
planet_positions, planet_shadbala)
|
||
|
||
houses = []
|
||
for i in range(12):
|
||
total = adhipathi[i] + dig_bala[i] + drik_bala[i]
|
||
if total >= 60:
|
||
level = "极强"
|
||
elif total >= 50:
|
||
level = "强"
|
||
elif total >= 40:
|
||
level = "中强"
|
||
elif total >= 30:
|
||
level = "中等"
|
||
elif total >= 20:
|
||
level = "弱"
|
||
else:
|
||
level = "极弱"
|
||
|
||
houses.append({
|
||
'house': i + 1,
|
||
'sign': house_signs[i] if i < len(house_signs) else SIGNS[i],
|
||
'adhipathi_bala': round(adhipathi[i], 2),
|
||
'dig_bala': round(dig_bala[i], 2),
|
||
'drik_bala': round(drik_bala[i], 2),
|
||
'total': round(total, 2),
|
||
'level': level,
|
||
})
|
||
|
||
return {
|
||
'method': 'Bhava Bala三元力量(基于jyotishganit MIT算法)',
|
||
'version': '1.0',
|
||
'houses': houses,
|
||
'strongest_house': max(houses, key=lambda h: h['total'])['house'],
|
||
'weakest_house': min(houses, key=lambda h: h['total'])['house'],
|
||
}
|