565 lines
20 KiB
Python
565 lines
20 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
高级星宿分析模块 v2.0
|
||
Nakshatra深度分析系统
|
||
|
||
支持:
|
||
- Tara Bala(星宿力量匹配 — Navatara 9星宿循环)
|
||
- Chandra Bala(月座力量 — 12宫循环)
|
||
- Sub-Lord体系(KP占星)
|
||
- 精确Vimshottari起始点计算
|
||
- Nakshatra兼容性分析
|
||
- Navatara(9星宿组)分类
|
||
- 综合星宿力量报告
|
||
"""
|
||
from typing import Dict, List, Tuple, Optional
|
||
import math
|
||
from datetime import datetime, timedelta
|
||
|
||
NAK_LIST = [
|
||
("Ashwini","Ketu",7),("Bharani","Venus",20),("Krittika","Sun",6),
|
||
("Rohini","Moon",10),("Mrigashira","Mars",7),("Ardra","Rahu",18),
|
||
("Punarvasu","Jupiter",16),("Pushya","Saturn",19),("Ashlesha","Mercury",17),
|
||
("Magha","Ketu",7),("Purva Phalguni","Venus",20),("Uttara Phalguni","Sun",6),
|
||
("Hasta","Moon",10),("Chitra","Mars",7),("Swati","Rahu",18),
|
||
("Vishakha","Jupiter",16),("Anuradha","Saturn",19),("Jyeshtha","Mercury",17),
|
||
("Mula","Ketu",7),("Purva Ashadha","Venus",20),("Uttara Ashadha","Sun",6),
|
||
("Shravana","Moon",10),("Dhanishta","Mars",7),("Shatabhisha","Rahu",18),
|
||
("Purva Bhadrapada","Jupiter",16),("Uttara Bhadrapada","Saturn",19),("Revati","Mercury",17),
|
||
]
|
||
NAK_NAMES = [n[0] for n in NAK_LIST]
|
||
NAK_LORDS = [n[1] for n in NAK_LIST]
|
||
NAK_YEARS = [n[2] for n in NAK_LIST]
|
||
|
||
# Navatara分组(从月亮星宿开始的9个星宿循环)
|
||
TARA_NAMES = ['Janma(生命)','Sampat(财富)','Vipat(危险)','Kshema(安全)',
|
||
'Pratyak(障碍)','Sadhana(成就)','Vadha(毁灭)','Mitra(友好)','ParamaMitra(至友)']
|
||
TARA_CN = {0:'生命Tara',1:'财富Tara',2:'危险Tara',3:'安全Tara',
|
||
4:'障碍Tara',5:'成就Tara',6:'毁灭Tara',7:'友好Tara',8:'至友Tara'}
|
||
|
||
# Nakshatra元素和属性
|
||
NAK_GANA = { # 气质类型
|
||
0:'Dev(神圣)',1:'Manushya(人类)',2:'Rakshasa(罗刹)',
|
||
3:'Dev',4:'Dev',5:'Manushya',6:'Dev',7:'Dev',8:'Rakshasa',
|
||
9:'Rakshasa',10:'Manushya',11:'Manushya',12:'Dev',13:'Rakshasa',14:'Dev',
|
||
15:'Rakshasa',16:'Dev',17:'Rakshasa',18:'Rakshasa',19:'Manushya',20:'Manushya',
|
||
21:'Dev',22:'Rakshasa',23:'Rakshasa',24:'Manushya',25:'Manushya',26:'Dev',
|
||
}
|
||
NAK_ELEMENT = {
|
||
0:'火',1:'土',2:'火',3:'土',4:'土',5:'风',6:'风',7:'水',8:'水',
|
||
9:'火',10:'土',11:'火',12:'土',13:'火',14:'风',15:'火',16:'水',17:'风',
|
||
18:'火',19:'水',20:'土',21:'土',22:'风',23:'风',24:'水',25:'火',26:'水',
|
||
}
|
||
|
||
|
||
def find_nakshatra(longitude: float) -> Dict:
|
||
"""从恒星黄道经度精确计算Nakshatra"""
|
||
nak_span = 360.0 / 27 # 每个星宿13.333...°
|
||
nak_idx = int(longitude / nak_span) % 27
|
||
nak_start = nak_idx * nak_span
|
||
deg_in_nak = longitude - nak_start
|
||
pada_span = nak_span / 4 # 每个Pada 3.333...°
|
||
pada = int(deg_in_nak / pada_span) + 1
|
||
deg_in_pada = deg_in_nak - (pada - 1) * pada_span
|
||
|
||
return {
|
||
'nakshatra': NAK_NAMES[nak_idx],
|
||
'nakshatra_idx': nak_idx,
|
||
'nakshatra_lord': NAK_LORDS[nak_idx],
|
||
'dasha_years': NAK_YEARS[nak_idx],
|
||
'pada': pada,
|
||
'degree_in_nakshatra': round(deg_in_nak, 4),
|
||
'degree_in_pada': round(deg_in_pada, 4),
|
||
'gana': NAK_GANA.get(nak_idx, ''),
|
||
'element': NAK_ELEMENT.get(nak_idx, ''),
|
||
}
|
||
|
||
|
||
def calc_tara_bala(moon_nak_idx: int, target_nak_idx: int) -> Dict:
|
||
"""
|
||
Tara Bala计算:月亮星宿到目标星宿的9星宿循环关系
|
||
|
||
用于判断某个行星/事件星宿与月亮星宿的关系
|
||
0=Janma(中性), 1=Sampat(吉), 2=Vipat(凶), 3=Kshema(吉),
|
||
4=Pratyak(凶), 5=Sadhana(吉), 6=Vadha(凶), 7=Mitra(吉), 8=ParamaMitra(大吉)
|
||
"""
|
||
distance = (target_nak_idx - moon_nak_idx) % 9
|
||
tara_name = TARA_NAMES[distance]
|
||
tara_cn = TARA_CN[distance]
|
||
|
||
is_auspicious = distance in (1, 3, 5, 7, 8)
|
||
is_dangerous = distance in (2, 4, 6)
|
||
|
||
return {
|
||
'tara_index': distance,
|
||
'tara_name': tara_name,
|
||
'tara_cn': tara_cn,
|
||
'is_auspicious': is_auspicious,
|
||
'is_dangerous': is_dangerous,
|
||
'quality': 'auspicious' if is_auspicious else 'dangerous' if is_dangerous else 'neutral',
|
||
'interpretation': _tara_interp(distance),
|
||
}
|
||
|
||
|
||
def calc_all_tara_balas(moon_nak_idx: int, planet_lons: Dict[str, float]) -> Dict:
|
||
"""计算所有行星相对于月亮的Tara Bala"""
|
||
results = {}
|
||
for pname, lon in planet_lons.items():
|
||
p_nak = find_nakshatra(lon)
|
||
tara = calc_tara_bala(moon_nak_idx, p_nak['nakshatra_idx'])
|
||
results[pname] = {
|
||
'nakshatra': p_nak['nakshatra'],
|
||
'tara': tara,
|
||
}
|
||
return results
|
||
|
||
|
||
def calc_vimshottari_start(moon_longitude: float) -> Dict:
|
||
"""
|
||
精确计算Vimshottari Dasha的起始点
|
||
|
||
返回月亮所在星宿的守护星、已用度数比例、剩余年数
|
||
"""
|
||
nak = find_nakshatra(moon_longitude)
|
||
nak_idx = nak['nakshatra_idx']
|
||
nak_lord = NAK_LORDS[nak_idx]
|
||
total_years = NAK_YEARS[nak_idx]
|
||
|
||
# 已用比例
|
||
nak_span = 360.0 / 27
|
||
nak_start = nak_idx * nak_span
|
||
deg_in_nak = moon_longitude - nak_start
|
||
used_ratio = deg_in_nak / nak_span
|
||
remaining_ratio = 1 - used_ratio
|
||
|
||
# 第一个Mahadasha的剩余年数
|
||
first_mahadasha_remaining = total_years * remaining_ratio
|
||
first_mahadasha_elapsed = total_years * used_ratio
|
||
|
||
return {
|
||
'moon_nakshatra': nak['nakshatra'],
|
||
'moon_nakshatra_lord': nak_lord,
|
||
'moon_pada': nak['pada'],
|
||
'total_dasha_years': total_years,
|
||
'used_ratio': round(used_ratio, 6),
|
||
'remaining_ratio': round(remaining_ratio, 6),
|
||
'first_mahadasha_remaining_years': round(first_mahadasha_remaining, 4),
|
||
'first_mahadasha_elapsed_years': round(first_mahadasha_elapsed, 4),
|
||
'first_mahadasha_lord': nak_lord,
|
||
}
|
||
|
||
|
||
def calc_sub_lord(longitude: float, division: int = 9) -> Dict:
|
||
"""
|
||
Sub-Lord计算(KP占星体系)
|
||
将星宿进一步细分为Sub-Lord和Sub-Sub-Lord
|
||
|
||
参数:
|
||
longitude: 恒星黄道经度
|
||
division: 细分层级(9=Sub-Lord, 81=Sub-Sub-Lord)
|
||
"""
|
||
# 主星宿
|
||
nak = find_nakshatra(longitude)
|
||
nak_span = 360.0 / 27
|
||
|
||
# Sub-Lord: 当前版本为简化版,直接按9等分。
|
||
# 完整 KP 体系应按 Vimshottari 年数比例不等分,后续需单独对标。
|
||
nak_lord = NAK_LORDS[nak['nakshatra_idx']]
|
||
deg_in_nak = nak['degree_in_nakshatra']
|
||
|
||
# 简化版:直接按9等分
|
||
sub_span = nak_span / 9
|
||
sub_idx = int(deg_in_nak / sub_span) % 9
|
||
|
||
# Sub-Lord是第sub_idx个行星(从星宿守护星开始的大运顺序)
|
||
DASHA_ORDER = ["Ketu","Venus","Sun","Moon","Mars","Rahu","Jupiter","Saturn","Mercury"]
|
||
nak_lord_idx = DASHA_ORDER.index(NAK_LORDS[nak['nakshatra_idx']])
|
||
sub_lord = DASHA_ORDER[(nak_lord_idx + sub_idx) % 9]
|
||
|
||
return {
|
||
'nakshatra': nak['nakshatra'],
|
||
'nakshatra_lord': nak_lord,
|
||
'sub_lord': sub_lord,
|
||
'sub_index': sub_idx,
|
||
'pada': nak['pada'],
|
||
'degree_in_nakshatra': round(deg_in_nak, 4),
|
||
}
|
||
|
||
|
||
def nakshatra_compatibility(nak1_idx: int, nak2_idx: int) -> Dict:
|
||
"""
|
||
Nakshatra兼容性分析(Koota系统中的星宿匹配部分)
|
||
基于Tara Bala和Nakshatra元素匹配
|
||
"""
|
||
# Tara匹配
|
||
tara = calc_tara_bala(nak1_idx, nak2_idx)
|
||
tara_score = 3 if tara['is_auspicious'] else 0 if tara['is_dangerous'] else 1.5
|
||
|
||
# 元素匹配
|
||
el1 = NAK_ELEMENT.get(nak1_idx, '')
|
||
el2 = NAK_ELEMENT.get(nak2_idx, '')
|
||
el_compatible = el1 == el2 or (el1 in ('火','风') and el2 in ('火','风')) or (el1 in ('土','水') and el2 in ('土','水'))
|
||
|
||
# Gana匹配
|
||
g1 = NAK_GANA.get(nak1_idx, '')
|
||
g2 = NAK_GANA.get(nak2_idx, '')
|
||
same_gana = bool(g1 and g2 and (g1 == g2 or ('Dev' in g1 and 'Dev' in g2) or ('Manushya' in g1 and 'Manushya' in g2) or ('Rakshasa' in g1 and 'Rakshasa' in g2)))
|
||
gana_score = 6 if same_gana else 3 if ('Dev' in g1 and 'Manushya' in g2) or ('Manushya' in g1 and 'Dev' in g2) else 0
|
||
|
||
return {
|
||
'nak1': NAK_NAMES[nak1_idx],
|
||
'nak2': NAK_NAMES[nak2_idx],
|
||
'tara_bala': tara,
|
||
'tara_score': tara_score,
|
||
'element_match': {'e1': el1, 'e2': el2, 'compatible': el_compatible},
|
||
'gana_match': {'g1': g1, 'g2': g2, 'score': gana_score},
|
||
'overall': 'compatible' if tara_score >= 1.5 and el_compatible else 'challenging' if tara['is_dangerous'] else 'moderate',
|
||
}
|
||
|
||
|
||
def _tara_interp(idx):
|
||
interps = {
|
||
0: '生命Tara—中性,代表自我,不吉不凶',
|
||
1: '财富Tara—吉,带来物质和精神增长',
|
||
2: '危险Tara—凶,需要谨慎,可能带来损失',
|
||
3: '安全Tara—吉,提供保护和稳定',
|
||
4: '障碍Tara—凶,可能面临困难和延误',
|
||
5: '成就Tara—吉,有利于实现目标',
|
||
6: '毁灭Tara—凶,最大凶Tara,需特别注意',
|
||
7: '友好Tara—吉,提供支持和帮助',
|
||
8: '至友Tara—大吉,最强吉Tara',
|
||
}
|
||
return interps.get(idx, '')
|
||
|
||
|
||
# ============================================================================
|
||
# Chandra Bala(月座力量)— v2.0 新增
|
||
# ============================================================================
|
||
|
||
# 12宫 Chandra Bala 名称(从月亮星座起算)
|
||
CHANDRA_NAMES = [
|
||
'Janma(生命)', 'Sampat(财富)', 'Vipat(危险)', 'Kshema(安全)',
|
||
'Pratyak(障碍)', 'Sadhana(成就)', 'Vadha(毁灭)', 'Mitra(友好)',
|
||
'ParamaMitra(至友)', 'Karma(业力)', 'Labha(收益)', 'Vyaya(消耗)',
|
||
]
|
||
CHANDRA_CN = {
|
||
0: '生命位', 1: '财富位', 2: '危险位', 3: '安全位',
|
||
4: '障碍位', 5: '成就位', 6: '毁灭位', 7: '友好位',
|
||
8: '至友位', 9: '业力位', 10: '收益位', 11: '消耗位',
|
||
}
|
||
|
||
|
||
def calc_chandra_bala(natal_moon_sign_idx: int, transit_moon_sign_idx: int) -> Dict:
|
||
"""
|
||
Chandra Bala(月座力量)计算 — v2.0 新增
|
||
|
||
基于月亮所在宫位(Rashi/Sign)的相对位置评估力量。
|
||
从本命月亮星座起算到当前(过境)月亮星座的12宫循环。
|
||
|
||
与 Tara Bala(星宿/Nakshatra 层面)互补,提供 Rashi/Sign 层面的力量评估。
|
||
常用于 Muhurta 择时和 Transit 过境分析。
|
||
|
||
参数:
|
||
natal_moon_sign_idx: 本命月亮星座索引 (0=Aries ~ 11=Pisces)
|
||
transit_moon_sign_idx: 过境月亮星座索引 (0=Aries ~ 11=Pisces)
|
||
|
||
返回:
|
||
dict: {
|
||
'rashi_from_moon': 0-11,
|
||
'chandra_name': 'Janma/Sampat/...',
|
||
'chandra_cn': '生命位/财富位/...',
|
||
'is_auspicious': bool,
|
||
'is_dangerous': bool,
|
||
'quality': 'auspicious'/'dangerous'/'neutral',
|
||
'interpretation': str,
|
||
}
|
||
"""
|
||
# 从本命月亮星座到过境月亮星座的步数(0-based, 12宫循环)
|
||
distance = (transit_moon_sign_idx - natal_moon_sign_idx) % 12
|
||
|
||
name = CHANDRA_NAMES[distance]
|
||
cn = CHANDRA_CN[distance]
|
||
|
||
# 吉位:Sampat(1), Kshema(3), Sadhana(5), Mitra(7), ParamaMitra(8), Labha(10)
|
||
# 凶位:Vipat(2), Pratyak(4), Vadha(6), Karma(9)
|
||
# 中性:Janma(0), Vyaya(11)
|
||
is_auspicious = distance in (1, 3, 5, 7, 8, 10)
|
||
is_dangerous = distance in (2, 4, 6, 9)
|
||
|
||
if is_auspicious:
|
||
quality = 'auspicious'
|
||
elif is_dangerous:
|
||
quality = 'dangerous'
|
||
else:
|
||
quality = 'neutral'
|
||
|
||
return {
|
||
'rashi_from_moon': distance,
|
||
'chandra_name': name,
|
||
'chandra_cn': cn,
|
||
'is_auspicious': is_auspicious,
|
||
'is_dangerous': is_dangerous,
|
||
'quality': quality,
|
||
'interpretation': _chandra_interp(distance),
|
||
}
|
||
|
||
|
||
def _chandra_interp(idx: int) -> str:
|
||
"""Chandra Bala 解释"""
|
||
interps = {
|
||
0: '生命位—代表身体和自我状态,中性',
|
||
1: '财富位—吉,有利于财务和资源获取',
|
||
2: '危险位—凶,可能遭遇损失和挑战',
|
||
3: '安全位—吉,提供保护和稳定感',
|
||
4: '障碍位—凶,面临困难和拖延',
|
||
5: '成就位—吉,有利于达成目标和获得成功',
|
||
6: '毁灭位—凶,需警惕冲突和破坏',
|
||
7: '友好位—吉,获得他人的支持和帮助',
|
||
8: '至友位—大吉,最强吉位,全面有利',
|
||
9: '业力位—凶,涉及过往业力的清算',
|
||
10: '收益位—吉,有利于收入和事业增长',
|
||
11: '消耗位—中性偏凶,可能消耗能量和资源',
|
||
}
|
||
return interps.get(idx, '')
|
||
|
||
|
||
def calc_tara_chandra_combined(
|
||
natal_moon_nak_idx: int,
|
||
natal_moon_sign_idx: int,
|
||
planet_lons: Dict[str, float],
|
||
transit_moon_lon: Optional[float] = None,
|
||
transit_moon_sign_idx: Optional[int] = None,
|
||
) -> Dict:
|
||
"""
|
||
Tara Bala + Chandra Bala 双维度综合行星力量分析 — v2.0 新增
|
||
|
||
同时评估:
|
||
1. Tara Bala(Star层面):月亮星宿到行星星宿的9星宿循环
|
||
2. Chandra Bala(Sign层面):月亮星座到行星星座的12宫循环
|
||
|
||
双吉 = 最强力,双凶 = 最弱力,一吉一凶 = 混合力量
|
||
|
||
参数:
|
||
natal_moon_nak_idx: 本命月亮星宿索引 (0-26)
|
||
natal_moon_sign_idx: 本命月亮星座索引 (0-11)
|
||
planet_lons: {行星名: 恒星黄道经度}
|
||
transit_moon_lon: 过境月亮经度(可选,用于过境分析)
|
||
transit_moon_sign_idx: 过境月亮星座索引(可选,用于过境分析)
|
||
|
||
返回:
|
||
dict: {planet: {tara, chandra, combined_score, interpretation}}
|
||
"""
|
||
results = {}
|
||
|
||
for pname, lon in planet_lons.items():
|
||
# Tara Bala(Nakshatra层面)
|
||
p_nak = find_nakshatra(lon)
|
||
tara = calc_tara_bala(natal_moon_nak_idx, p_nak['nakshatra_idx'])
|
||
|
||
# Chandra Bala(Rashi层面)
|
||
p_sign_idx = int(lon / 30) % 12
|
||
chandra = calc_chandra_bala(natal_moon_sign_idx, p_sign_idx)
|
||
|
||
# 综合评分
|
||
combined_score = _combined_score(tara, chandra)
|
||
|
||
results[pname] = {
|
||
'nakshatra': p_nak['nakshatra'],
|
||
'sign_idx': p_sign_idx,
|
||
'tara': tara,
|
||
'chandra': chandra,
|
||
'combined_score': combined_score,
|
||
'assessment': _combined_assessment(combined_score),
|
||
}
|
||
|
||
return results
|
||
|
||
|
||
def _combined_score(tara: Dict, chandra: Dict) -> str:
|
||
"""综合 Tara + Chandra 评分"""
|
||
t_good = tara['is_auspicious']
|
||
c_good = chandra['is_auspicious']
|
||
t_bad = tara['is_dangerous']
|
||
c_bad = chandra['is_dangerous']
|
||
|
||
if t_good and c_good:
|
||
return 'double_auspicious'
|
||
elif t_bad and c_bad:
|
||
return 'double_dangerous'
|
||
elif t_good and c_bad:
|
||
return 'tara_good_chandra_bad'
|
||
elif t_bad and c_good:
|
||
return 'tara_bad_chandra_good'
|
||
else:
|
||
# 至少有一方中性
|
||
if t_good or c_good:
|
||
return 'mixed_favorable'
|
||
elif t_bad or c_bad:
|
||
return 'mixed_unfavorable'
|
||
else:
|
||
return 'neutral'
|
||
|
||
|
||
def _combined_assessment(score: str) -> str:
|
||
"""综合评估说明"""
|
||
assessments = {
|
||
'double_auspicious': '双吉—Star与Sign层面均有利,最强力支持',
|
||
'double_dangerous': '双凶—Star与Sign层面均不利,需格外谨慎',
|
||
'tara_good_chandra_bad': '星吉宫凶—Nakshatra有利但Rashi层面受阻,可能好事多磨',
|
||
'tara_bad_chandra_good': '星凶宫吉—Nakshatra不利但Rashi层面有保护,或许有惊无险',
|
||
'mixed_favorable': '偏吉—至少一方有利,方向积极',
|
||
'mixed_unfavorable': '偏凶—至少一方不利,需注意',
|
||
'neutral': '中性—无明确吉凶指向',
|
||
}
|
||
return assessments.get(score, '')
|
||
|
||
|
||
def calc_nakshatra_transits_natal(
|
||
planet_lons: Dict[str, float],
|
||
) -> Dict:
|
||
"""
|
||
计算所有行星在星盘中的 Nakshatra 分布 — v2.0 新增
|
||
|
||
用于快速查看每个行星落在哪个星宿、Pada、守护星等信息。
|
||
|
||
返回:
|
||
dict: {planet: {nakshatra, pada, lord, gana, element, degree_in_nak}}
|
||
"""
|
||
results = {}
|
||
for pname, lon in planet_lons.items():
|
||
nak = find_nakshatra(lon)
|
||
results[pname] = {
|
||
'nakshatra': nak['nakshatra'],
|
||
'nakshatra_idx': nak['nakshatra_idx'],
|
||
'nakshatra_lord': nak['nakshatra_lord'],
|
||
'pada': nak['pada'],
|
||
'gana': nak['gana'],
|
||
'element': nak['element'],
|
||
'degree_in_nakshatra': nak['degree_in_nakshatra'],
|
||
'dasha_years': nak['dasha_years'],
|
||
}
|
||
return results
|
||
|
||
|
||
def nakshatra_full_report(
|
||
chart_data: Dict,
|
||
age: Optional[float] = None,
|
||
transit_date: Optional[str] = None,
|
||
) -> Dict:
|
||
"""
|
||
综合星宿力量完整报告 — v2.0 新增
|
||
|
||
包含:
|
||
1. 本命 Nakshatra 分布(所有行星)
|
||
2. Tara Bala 全部分析(以月亮星宿为基准)
|
||
3. Chandra Bala 全部分析(以月亮星座为基准)
|
||
4. Tara+Chandra 双维度综合评分
|
||
5. Nakshatra 兼容性(行星间的星宿关系)
|
||
6. Vimshottari 起始点信息
|
||
7. Sub-Lord KP 分析
|
||
|
||
参数:
|
||
chart_data: 星盘数据 (from jyotish_engine chart command)
|
||
age: 当前年龄(可选)
|
||
transit_date: 过境日期 YYYY-MM-DD(可选)
|
||
|
||
返回:
|
||
dict: 完整星宿报告
|
||
"""
|
||
planets = chart_data.get('planets', {})
|
||
planet_lons = {}
|
||
planet_signs = {}
|
||
for pn, pd in planets.items():
|
||
if isinstance(pd, dict) and 'degree' in pd:
|
||
planet_lons[pn] = pd['degree']
|
||
planet_signs[pn] = int(pd['degree'] / 30) % 12
|
||
|
||
if not planet_lons:
|
||
return {'error': '无法获取行星经度数据'}
|
||
|
||
moon_lon = planet_lons.get('Moon', 0)
|
||
moon_nak_idx = int(moon_lon / (360/27)) % 27
|
||
moon_sign_idx = int(moon_lon / 30) % 12
|
||
|
||
report = {}
|
||
|
||
# 1. 本命星宿分布
|
||
report['natal_nakshatras'] = calc_nakshatra_transits_natal(planet_lons)
|
||
|
||
# 2. Tara Bala
|
||
report['tara_bala'] = calc_all_tara_balas(moon_nak_idx, planet_lons)
|
||
|
||
# 3. Chandra Bala
|
||
chandra_bala = {}
|
||
for pn, lon in planet_lons.items():
|
||
p_sign = int(lon / 30) % 12
|
||
chandra_bala[pn] = {
|
||
'planet_sign': p_sign,
|
||
'chandra': calc_chandra_bala(moon_sign_idx, p_sign),
|
||
}
|
||
report['chandra_bala'] = chandra_bala
|
||
|
||
# 4. Tara + Chandra 双维综合
|
||
report['tara_chandra_combined'] = calc_tara_chandra_combined(
|
||
moon_nak_idx, moon_sign_idx, planet_lons)
|
||
|
||
# 5. Sub-Lords
|
||
report['sub_lords'] = {pn: calc_sub_lord(lon) for pn, lon in planet_lons.items()}
|
||
|
||
# 6. Vimshottari 起始点
|
||
report['vimshottari_start'] = calc_vimshottari_start(moon_lon)
|
||
|
||
# 7. 星宿力量排序
|
||
power_ranking = []
|
||
for pn, combined in report['tara_chandra_combined'].items():
|
||
score_val = _score_value(combined['combined_score'])
|
||
power_ranking.append({
|
||
'planet': pn,
|
||
'nakshatra': combined['nakshatra'],
|
||
'tara_name': combined['tara']['tara_cn'],
|
||
'tara_quality': combined['tara']['quality'],
|
||
'chandra_name': combined['chandra']['chandra_cn'],
|
||
'chandra_quality': combined['chandra']['quality'],
|
||
'combined': combined['combined_score'],
|
||
'score': score_val,
|
||
'assessment': combined['assessment'],
|
||
})
|
||
power_ranking.sort(key=lambda x: x['score'], reverse=True)
|
||
report['power_ranking'] = power_ranking
|
||
|
||
# 8. 汇总
|
||
double_auspicious = [p['planet'] for p in power_ranking if p['combined'] == 'double_auspicious']
|
||
double_dangerous = [p['planet'] for p in power_ranking if p['combined'] == 'double_dangerous']
|
||
report['summary'] = {
|
||
'moon_nakshatra': NAK_NAMES[moon_nak_idx],
|
||
'moon_nakshatra_lord': NAK_LORDS[moon_nak_idx],
|
||
'moon_sign_idx': moon_sign_idx,
|
||
'strongest_planets': [p['planet'] for p in power_ranking[:3]],
|
||
'weakest_planets': [p['planet'] for p in power_ranking[-3:]],
|
||
'double_auspicious_planets': double_auspicious,
|
||
'double_dangerous_planets': double_dangerous,
|
||
'tara_auspicious_count': sum(1 for p in power_ranking if p['tara_quality'] == 'auspicious'),
|
||
'chandra_auspicious_count': sum(1 for p in power_ranking if p['chandra_quality'] == 'auspicious'),
|
||
}
|
||
# 将关键字段也复制到顶层,方便直接访问(兼容旧版验证脚本)
|
||
report['moon_nakshatra'] = NAK_NAMES[moon_nak_idx]
|
||
report['moon_nakshatra_lord'] = NAK_LORDS[moon_nak_idx]
|
||
report['moon_pada'] = int((moon_lon % (360.0/27)) / (360.0/108)) + 1
|
||
|
||
return report
|
||
|
||
|
||
def _score_value(combined: str) -> int:
|
||
"""将组合评分转为数值"""
|
||
scores = {
|
||
'double_auspicious': 100,
|
||
'tara_good_chandra_bad': 60,
|
||
'tara_bad_chandra_good': 60,
|
||
'mixed_favorable': 55,
|
||
'neutral': 50,
|
||
'mixed_unfavorable': 45,
|
||
'double_dangerous': 0,
|
||
}
|
||
return scores.get(combined, 50)
|