feat(upstream): merge a6f47abd engine, MCP, and orchestrator
Three-way-merge calculation modules and pl9-export into the product fork while keeping commercial API routes, Raman ayanamsa, and the consultation contract as a keypath superset. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+118
-19
@@ -300,6 +300,12 @@ _PLANET_DIGNITY_KNRAO = {
|
||||
# Aquarius (sign 10): 传统主Saturn vs 共主Rahu — PyJHora用stronger_planet动态判定
|
||||
# Scorpio (sign 7): 传统主Mars vs 共主Ketu — PyJHora用stronger_planet动态判定
|
||||
_CHARA_DASHA_CO_LORD_SIGNS = {10, 7} # Aquarius, Scorpio 有共主争议
|
||||
CHARA_DASHA_PROFILES = {
|
||||
"kn_rao",
|
||||
"goel_lagna_start",
|
||||
"goel_gendered",
|
||||
"goel_shastri_method2",
|
||||
}
|
||||
|
||||
|
||||
def _jaimini_planet_dignity_level(planet: str, sign_idx: int) -> int:
|
||||
@@ -439,7 +445,12 @@ def _get_sign_lord_house(longitudes: Dict[str, float], sign_idx: int) -> int:
|
||||
return _get_planet_house(longitudes, lord)
|
||||
|
||||
|
||||
def _chara_dasha_duration_knrao(longitudes: Dict[str, float], sign_idx: int) -> int:
|
||||
def _chara_dasha_duration_profile(
|
||||
longitudes: Dict[str, float],
|
||||
sign_idx: int,
|
||||
*,
|
||||
profile: str = "kn_rao",
|
||||
) -> int:
|
||||
"""
|
||||
KN Rao Chara Dasha 大运时长计算 v6.1.12。
|
||||
|
||||
@@ -453,7 +464,31 @@ def _chara_dasha_duration_knrao(longitudes: Dict[str, float], sign_idx: int) ->
|
||||
若宫主在所在宫位 ⟹ Exalted(+1);Debilitated(-1)
|
||||
Mercury在Virgo/Gemini是own sign非exalted,不+1
|
||||
"""
|
||||
# 动态宫主判定:Aquarius→Saturn/Rahu比较,Scorpio→Mars/Ketu比较
|
||||
if profile not in CHARA_DASHA_PROFILES:
|
||||
raise ValueError(f"unsupported Chara Dasha profile: {profile}")
|
||||
|
||||
if profile == "goel_lagna_start":
|
||||
lord = SIGN_LORDS[SIGNS[sign_idx]]
|
||||
lord_house = _get_planet_house(longitudes, lord)
|
||||
if lord_house == sign_idx:
|
||||
return 12
|
||||
return _count_rasis_forward(sign_idx, lord_house)
|
||||
|
||||
if profile == "goel_gendered":
|
||||
lord = SIGN_LORDS[SIGNS[sign_idx]]
|
||||
lord_house = _get_planet_house(longitudes, lord)
|
||||
if lord_house == sign_idx:
|
||||
return 12
|
||||
if (lord_house - sign_idx) % 12 == 6:
|
||||
return 10
|
||||
if sign_idx % 2 == 0:
|
||||
count = _count_rasis_forward(lord_house, sign_idx)
|
||||
else:
|
||||
count = _count_rasis_backward(lord_house, sign_idx)
|
||||
return max(1, count - 1)
|
||||
|
||||
# KN Rao keeps Scorpio/Aquarius dual-lord separation; start/order rules are
|
||||
# handled by the progression helper.
|
||||
lord = _resolve_chara_dasha_lord(longitudes, sign_idx)
|
||||
|
||||
lord_house = _get_planet_house(longitudes, lord)
|
||||
@@ -469,7 +504,9 @@ def _chara_dasha_duration_knrao(longitudes: Dict[str, float], sign_idx: int) ->
|
||||
if years <= 0:
|
||||
years = 12
|
||||
|
||||
# 尊贵调整(对齐PyJHora house_strengths_of_planets表)
|
||||
# This remains the historical PyJHora-aligned local KN Rao profile. The
|
||||
# source ledger keeps the no-extra-year K.N. Rao textual boundary visible
|
||||
# for later formula reconciliation.
|
||||
dignities = _PLANET_DIGNITY_KNRAO.get(lord, {})
|
||||
if dignities:
|
||||
if lord_house in dignities.get('exalted', set()):
|
||||
@@ -480,7 +517,23 @@ def _chara_dasha_duration_knrao(longitudes: Dict[str, float], sign_idx: int) ->
|
||||
return years
|
||||
|
||||
|
||||
def _chara_progression_knrao(asc_sign_idx: int, longitudes: Dict[str, float]) -> list:
|
||||
def _chara_dasha_duration_knrao(longitudes: Dict[str, float], sign_idx: int) -> int:
|
||||
return _chara_dasha_duration_profile(longitudes, sign_idx, profile="kn_rao")
|
||||
|
||||
|
||||
def _fourth_from_lagna_prakriti(asc_sign_idx: int) -> int:
|
||||
if asc_sign_idx % 2 == 0:
|
||||
return (asc_sign_idx + 3) % 12
|
||||
return (asc_sign_idx - 3) % 12
|
||||
|
||||
|
||||
def _chara_progression_profile(
|
||||
asc_sign_idx: int,
|
||||
longitudes: Dict[str, float],
|
||||
*,
|
||||
profile: str = "kn_rao",
|
||||
gender: str | None = None,
|
||||
) -> list:
|
||||
"""
|
||||
KN Rao Chara Dasha 星座序列生成。
|
||||
|
||||
@@ -489,11 +542,19 @@ def _chara_progression_knrao(asc_sign_idx: int, longitudes: Dict[str, float]) ->
|
||||
2. 检查第9宫:若为偶数脚 → 逆向,否则正向
|
||||
3. 生成12个星座的顺序
|
||||
"""
|
||||
if profile not in CHARA_DASHA_PROFILES:
|
||||
raise ValueError(f"unsupported Chara Dasha profile: {profile}")
|
||||
start_idx = asc_sign_idx
|
||||
if profile == "goel_gendered" and (gender or "").lower().startswith("f"):
|
||||
start_idx = _fourth_from_lagna_prakriti(asc_sign_idx)
|
||||
ninth_idx = (asc_sign_idx + 8) % 12
|
||||
if _sign_is_even_footed(ninth_idx):
|
||||
return [(asc_sign_idx + 12 - i) % 12 for i in range(12)]
|
||||
else:
|
||||
return [(asc_sign_idx + i) % 12 for i in range(12)]
|
||||
return [(start_idx + 12 - i) % 12 for i in range(12)]
|
||||
return [(start_idx + i) % 12 for i in range(12)]
|
||||
|
||||
|
||||
def _chara_progression_knrao(asc_sign_idx: int, longitudes: Dict[str, float]) -> list:
|
||||
return _chara_progression_profile(asc_sign_idx, longitudes, profile="kn_rao")
|
||||
|
||||
|
||||
def _jd_to_date_tuple(jd: float):
|
||||
@@ -522,7 +583,9 @@ def _jd_to_date_tuple(jd: float):
|
||||
def calc_chara_dasha(asc_sign_idx: int,
|
||||
planet_longitudes: Dict[str, float],
|
||||
birth_year: int, birth_month: int,
|
||||
birth_day: int = 1) -> Dict:
|
||||
birth_day: int = 1,
|
||||
profile: str = "kn_rao",
|
||||
gender: str | None = None) -> Dict:
|
||||
"""
|
||||
Chara Dasha计算(v6.1.11重写:KN Rao Method)
|
||||
|
||||
@@ -534,13 +597,21 @@ def calc_chara_dasha(asc_sign_idx: int,
|
||||
- 时长:基于宫主所在宫位而非行星计数
|
||||
- 尊贵:Exalted +1年 / Debilitated -1年
|
||||
"""
|
||||
progression = _chara_progression_knrao(asc_sign_idx, planet_longitudes)
|
||||
progression = _chara_progression_profile(
|
||||
asc_sign_idx,
|
||||
planet_longitudes,
|
||||
profile=profile,
|
||||
gender=gender,
|
||||
)
|
||||
|
||||
dasha_sequence = []
|
||||
for i, sign_idx in enumerate(progression):
|
||||
sign_name = SIGNS[sign_idx]
|
||||
lord = _resolve_chara_dasha_lord(planet_longitudes, sign_idx)
|
||||
duration = _chara_dasha_duration_knrao(planet_longitudes, sign_idx)
|
||||
if profile == "goel_lagna_start":
|
||||
lord = SIGN_LORDS[sign_name]
|
||||
else:
|
||||
lord = _resolve_chara_dasha_lord(planet_longitudes, sign_idx)
|
||||
duration = _chara_dasha_duration_profile(planet_longitudes, sign_idx, profile=profile)
|
||||
|
||||
# 宮主所在宫位
|
||||
lord_house = _get_planet_house(planet_longitudes, lord)
|
||||
@@ -549,7 +620,9 @@ def calc_chara_dasha(asc_sign_idx: int,
|
||||
# 尊贵状态
|
||||
dignities = _PLANET_DIGNITY_KNRAO.get(lord, {})
|
||||
dignity_status = 'none'
|
||||
if dignities:
|
||||
if profile == "goel_lagna_start":
|
||||
dignity_status = 'not_applied'
|
||||
elif dignities:
|
||||
exalted_set = dignities.get('exalted', set())
|
||||
debil_set = dignities.get('debilitated', set())
|
||||
if lord_house in exalted_set:
|
||||
@@ -571,7 +644,10 @@ def calc_chara_dasha(asc_sign_idx: int,
|
||||
total_years = sum(d['duration_years'] for d in dasha_sequence)
|
||||
|
||||
return {
|
||||
'method': 'Chara Dasha (KN Rao Method, v6.1.11, PyJHora-aligned)',
|
||||
'method': f'Chara Dasha ({profile})',
|
||||
'variant_profile': profile,
|
||||
'variant_profile_status': 'profiled',
|
||||
'gender': gender,
|
||||
'ascendant': SIGNS[asc_sign_idx],
|
||||
'ascendant_idx': asc_sign_idx,
|
||||
'progression_source': '9th_house_direction',
|
||||
@@ -584,22 +660,45 @@ def calc_chara_dasha(asc_sign_idx: int,
|
||||
def calc_chara_dasha_with_antardasha(asc_sign_idx: int,
|
||||
planet_longitudes: Dict[str, float],
|
||||
birth_year: int, birth_month: int,
|
||||
birth_day: int = 1) -> Dict:
|
||||
birth_day: int = 1,
|
||||
profile: str = "kn_rao",
|
||||
gender: str | None = None) -> Dict:
|
||||
"""
|
||||
Chara Dasha 完整3层计算(MD → AD → PD)
|
||||
|
||||
使用KN Rao方法(v6.1.11重写)。
|
||||
Antardasha:等分法(parent/12),序列为Maha序列偏移1位。
|
||||
"""
|
||||
base = calc_chara_dasha(asc_sign_idx, planet_longitudes, birth_year, birth_month, birth_day)
|
||||
progression = _chara_progression_knrao(asc_sign_idx, planet_longitudes)
|
||||
|
||||
# Antardasha序列:Mahadasha序列偏移1(PyJHora method=2)
|
||||
antar_sequence = progression[1:] + progression[:1]
|
||||
base = calc_chara_dasha(
|
||||
asc_sign_idx,
|
||||
planet_longitudes,
|
||||
birth_year,
|
||||
birth_month,
|
||||
birth_day,
|
||||
profile=profile,
|
||||
gender=gender,
|
||||
)
|
||||
progression = _chara_progression_profile(
|
||||
asc_sign_idx,
|
||||
planet_longitudes,
|
||||
profile=profile,
|
||||
gender=gender,
|
||||
)
|
||||
|
||||
for md in base['dasha_sequence']:
|
||||
md_sign_idx = md['sign_idx']
|
||||
md_duration_years = md['duration_years']
|
||||
if profile == "goel_shastri_method2":
|
||||
# Goel's Method 2 worked example gives the first sub-period to the
|
||||
# mahadasha sign and then follows that sign's own direct/indirect order.
|
||||
ninth_from_md = (md_sign_idx + 8) % 12
|
||||
if _sign_is_even_footed(ninth_from_md):
|
||||
antar_sequence = [(md_sign_idx + 12 - i) % 12 for i in range(12)]
|
||||
else:
|
||||
antar_sequence = [(md_sign_idx + i) % 12 for i in range(12)]
|
||||
else:
|
||||
# Antardasha序列:Mahadasha序列偏移1(PyJHora method=2)
|
||||
antar_sequence = progression[1:] + progression[:1]
|
||||
|
||||
antardasha_list = []
|
||||
for j, ad_sign_idx in enumerate(antar_sequence):
|
||||
|
||||
Reference in New Issue
Block a user