fix(vimsopaka): score sign-owner relationships on a 20-point scale (BUG-1261, upstream f32472b5)
This commit is contained in:
+15
-10
@@ -651,8 +651,11 @@ def _build_dignity_context(chart_data):
|
||||
}
|
||||
return context
|
||||
|
||||
def _get_dignity_level(planet, sign, deg_in_sign=None, planets_data=None):
|
||||
"""判断行星在某星座的尊严等级 (用于 Vimsopaka 映射), 包含五重敌友和落陷取消"""
|
||||
def _get_dignity_level(planet, sign, deg_in_sign=None, planets_data=None, skip_debilitation=False):
|
||||
"""判断行星在某星座的尊严等级, 包含五重敌友;默认也含落陷取消。
|
||||
|
||||
skip_debilitation 只给 Varga Viswa:落陷和落陷取消不是星主关系。
|
||||
"""
|
||||
if EXALTATION.get(planet) == sign:
|
||||
return 'EXALTED'
|
||||
|
||||
@@ -667,7 +670,7 @@ def _get_dignity_level(planet, sign, deg_in_sign=None, planets_data=None):
|
||||
if SIGN_LORDS.get(sign) == planet:
|
||||
return 'OWN_SIGN'
|
||||
|
||||
if DEBILITATION.get(planet) == sign:
|
||||
if not skip_debilitation and DEBILITATION.get(planet) == sign:
|
||||
if _check_neecha_bhanga(planet, sign, planets_data):
|
||||
return 'NEECHA_BHANGA'
|
||||
return 'DEBILITATED'
|
||||
@@ -706,7 +709,7 @@ def _get_dignity_level(planet, sign, deg_in_sign=None, planets_data=None):
|
||||
return 'NEUTRAL'
|
||||
|
||||
|
||||
def varga_dignity_level(planet, varga_planets):
|
||||
def varga_dignity_level(planet, varga_planets, skip_debilitation=False):
|
||||
"""Dignity of a body inside a divisional chart (Vimsopaka and the chart page alike).
|
||||
|
||||
The temporary half of the compound relationship is read from that varga's
|
||||
@@ -717,7 +720,10 @@ def varga_dignity_level(planet, varga_planets):
|
||||
if not isinstance(pinfo, dict) or pinfo.get('sign') not in SIGN_LORDS:
|
||||
return None
|
||||
deg_in_sign = pinfo.get('degree_in_sign', pinfo.get('degree', 0) % 30)
|
||||
return _get_dignity_level(planet, pinfo['sign'], deg_in_sign, _build_dignity_context(varga_planets))
|
||||
return _get_dignity_level(
|
||||
planet, pinfo['sign'], deg_in_sign, _build_dignity_context(varga_planets),
|
||||
skip_debilitation=skip_debilitation,
|
||||
)
|
||||
|
||||
|
||||
def _get_planet_status_label(planet, sign, deg_in_sign=None, planets_data=None):
|
||||
@@ -15756,7 +15762,6 @@ def cmd_full_reading(args):
|
||||
'OWN_SIGN': DignityLevel.OWN_SIGN, 'GREAT_FRIEND': DignityLevel.GREAT_FRIEND,
|
||||
'FRIEND': DignityLevel.FRIEND, 'NEUTRAL': DignityLevel.NEUTRAL,
|
||||
'ENEMY': DignityLevel.ENEMY, 'GREAT_ENEMY': DignityLevel.GREAT_ENEMY,
|
||||
'DEBILITATED': DignityLevel.DEBILITATED, 'NEECHA_BHANGA': DignityLevel.NEECHA_BHANGA,
|
||||
}
|
||||
# 建立 VargaType → varga_result key 的映射(修复:每个分盘独立计算尊贵)
|
||||
_vt_div = {VimsVargaType.D1:1, VimsVargaType.D2:2, VimsVargaType.D3:3,
|
||||
@@ -15785,15 +15790,15 @@ def cmd_full_reading(args):
|
||||
if div == 1:
|
||||
dl_key = _get_dignity_level(pn, pinfo['sign'],
|
||||
pinfo.get('degree_in_sign', pinfo.get('degree', 0) % 30),
|
||||
planets)
|
||||
planets, skip_debilitation=True)
|
||||
else:
|
||||
dl_key = varga_dignity_level(pn, vdata)
|
||||
dl_key = varga_dignity_level(pn, vdata, skip_debilitation=True)
|
||||
planet_vargas_input[pn][vt] = dignity_map.get(dl_key, DignityLevel.NEUTRAL)
|
||||
elif div == 1:
|
||||
# D1 直接用本命盘数据
|
||||
p_sign = SIGNS[int(planet_lons.get(pn, 0) / 30) % 12]
|
||||
d_in_s = planet_lons.get(pn, 0) % 30
|
||||
dl_key = _get_dignity_level(pn, p_sign, d_in_s, planets)
|
||||
dl_key = _get_dignity_level(pn, p_sign, d_in_s, planets, skip_debilitation=True)
|
||||
planet_vargas_input[pn][vt] = dignity_map.get(dl_key, DignityLevel.NEUTRAL)
|
||||
else:
|
||||
planet_vargas_input[pn][vt] = DignityLevel.NEUTRAL
|
||||
@@ -15801,7 +15806,7 @@ def cmd_full_reading(args):
|
||||
# fallback: D1 从 planet_lons 计算
|
||||
p_sign = SIGNS[int(planet_lons.get(pn, 0) / 30) % 12]
|
||||
d_in_s = planet_lons.get(pn, 0) % 30
|
||||
dl_key = _get_dignity_level(pn, p_sign, d_in_s, planets)
|
||||
dl_key = _get_dignity_level(pn, p_sign, d_in_s, planets, skip_debilitation=True)
|
||||
planet_vargas_input[pn][vt] = dignity_map.get(dl_key, DignityLevel.NEUTRAL)
|
||||
else:
|
||||
planet_vargas_input[pn][vt] = DignityLevel.NEUTRAL
|
||||
|
||||
@@ -60,7 +60,7 @@ class VimsopakaBalaCalculator:
|
||||
VargaType.D3: 1.0, # Drekkana
|
||||
VargaType.D4: 0.5, # Chaturthamsa
|
||||
VargaType.D7: 0.5, # Saptamsa
|
||||
VargaType.D9: 3.5, # Navamsa
|
||||
VargaType.D9: 3.0, # Navamsa;十六分盘权重合计 20
|
||||
VargaType.D10: 0.5, # Dasamsa
|
||||
VargaType.D12: 0.5, # Dwadasamsa
|
||||
VargaType.D16: 2.0, # Shodasamsa
|
||||
@@ -79,7 +79,7 @@ class VimsopakaBalaCalculator:
|
||||
VargaType.D2: 1.5,
|
||||
VargaType.D3: 1.5,
|
||||
VargaType.D7: 1.5,
|
||||
VargaType.D9: 3.0,
|
||||
VargaType.D9: 1.5,
|
||||
VargaType.D10: 1.5,
|
||||
VargaType.D12: 1.5,
|
||||
VargaType.D16: 1.5,
|
||||
@@ -87,31 +87,24 @@ class VimsopakaBalaCalculator:
|
||||
VargaType.D60: 5.0
|
||||
}
|
||||
|
||||
# 尊严等级对应的Virupas(力量单位)
|
||||
# 星主关系对应的 Virupas。落陷和落陷取消不是这项的输入。
|
||||
DIGNITY_VIRUPAS = {
|
||||
DignityLevel.EXALTED: 20.0,
|
||||
DignityLevel.MOOLATRIKONA: 18.0,
|
||||
DignityLevel.OWN_SIGN: 15.0,
|
||||
DignityLevel.GREAT_FRIEND: 12.5,
|
||||
DignityLevel.FRIEND: 10.0,
|
||||
DignityLevel.NEUTRAL: 7.5,
|
||||
DignityLevel.ENEMY: 5.0,
|
||||
DignityLevel.GREAT_ENEMY: 3.5,
|
||||
DignityLevel.DEBILITATED: 2.0,
|
||||
DignityLevel.NEECHA_BHANGA: 9.0,
|
||||
DignityLevel.MOOLATRIKONA: 20.0,
|
||||
DignityLevel.OWN_SIGN: 20.0,
|
||||
DignityLevel.GREAT_FRIEND: 18.0,
|
||||
DignityLevel.FRIEND: 15.0,
|
||||
DignityLevel.NEUTRAL: 10.0,
|
||||
DignityLevel.ENEMY: 7.0,
|
||||
DignityLevel.GREAT_ENEMY: 5.0,
|
||||
}
|
||||
|
||||
# 力量等级分类(基于总分)
|
||||
# 数值分档。不再借用 Vaiseshikamsa 的分盘计数名称。
|
||||
STRENGTH_CATEGORIES = {
|
||||
"Parijatamsa": (18.0, 20.0), # 极强(18-20)
|
||||
"Uttamamsa": (16.0, 18.0), # 优秀(16-18)
|
||||
"Gopuramsa": (12.0, 16.0), # 良好(12-16)
|
||||
"Simhasanamsa": (10.0, 12.0), # 中等偏上(10-12)
|
||||
"Paravatamsa": (8.0, 10.0), # 中等(8-10)
|
||||
"Devalokamsa": (6.0, 8.0), # 中等偏下(6-8)
|
||||
"Brahmalokamsa": (4.0, 6.0), # 较弱(4-6)
|
||||
"Airavata": (2.0, 4.0), # 弱(2-4)
|
||||
"Vaiseshikamsa": (0.0, 2.0) # 极弱(0-2)
|
||||
"High": (15.0, 20.000001),
|
||||
"Moderate": (10.0, 15.0),
|
||||
"Limited": (5.0, 10.0),
|
||||
"Low": (0.0, 5.0),
|
||||
}
|
||||
|
||||
def __init__(self, mode: str = "shodasavarga"):
|
||||
@@ -156,8 +149,10 @@ class VimsopakaBalaCalculator:
|
||||
# 计算每个分盘的得分
|
||||
for varga_type, dignity in vargas.items():
|
||||
if varga_type in self.weights:
|
||||
# 获取尊严对应的Virupas
|
||||
virupas = self.DIGNITY_VIRUPAS.get(dignity, 0.0)
|
||||
# 只接受星主关系。落陷或落陷取消不能当作尊贵分。
|
||||
if dignity not in self.DIGNITY_VIRUPAS:
|
||||
raise ValueError('Varga Viswa requires a sign-owner relationship, not debility/cancellation')
|
||||
virupas = self.DIGNITY_VIRUPAS[dignity]
|
||||
|
||||
# 获取分盘权重
|
||||
weight = self.weights[varga_type]
|
||||
@@ -175,9 +170,9 @@ class VimsopakaBalaCalculator:
|
||||
total_weighted_score += weighted_score
|
||||
total_weight += weight
|
||||
|
||||
# 计算最终得分(归一化到20分制)
|
||||
# 分母固定为 20,不按已提供分盘的权重再归一。
|
||||
if total_weight > 0:
|
||||
final_score = total_weighted_score / total_weight
|
||||
final_score = total_weighted_score / 20.0
|
||||
else:
|
||||
final_score = 0.0
|
||||
|
||||
@@ -193,7 +188,12 @@ class VimsopakaBalaCalculator:
|
||||
"category": category,
|
||||
"varga_scores": varga_scores,
|
||||
"interpretation": interpretation,
|
||||
"mode": self.mode
|
||||
"mode": self.mode,
|
||||
"calculation_profile": "bphs_7_21_27_varga_viswa_compound_relationships",
|
||||
"included_weight": total_weight,
|
||||
"complete": set(vargas).issuperset(self.weights),
|
||||
"missing_vargas": [v.value for v in self.weights if v not in vargas],
|
||||
"category_basis": "Numeric score band; not Vaiseshikamsa varga-count titles",
|
||||
}
|
||||
|
||||
def _get_strength_category(self, score: float) -> str:
|
||||
@@ -201,34 +201,21 @@ class VimsopakaBalaCalculator:
|
||||
for category, (min_score, max_score) in self.STRENGTH_CATEGORIES.items():
|
||||
if min_score <= score < max_score:
|
||||
return category
|
||||
return "Vaiseshikamsa" # 默认最低等级
|
||||
return "Unclassified"
|
||||
|
||||
def _generate_interpretation(self, planet: str, score: float, category: str, varga_scores: Dict) -> str:
|
||||
"""生成解读文本"""
|
||||
interpretation = f"{planet}的Vimsopaka Bala得分为{score:.2f}/20,属于{category}等级。\n\n"
|
||||
|
||||
# 根据等级给出解读
|
||||
if score >= 16:
|
||||
interpretation += "这是极强的行星力量,表示该行星在生活中能够充分发挥其积极作用,带来显著的成果和成功。"
|
||||
elif score >= 12:
|
||||
interpretation += "这是良好的行星力量,表示该行星能够有效发挥作用,在其主管领域带来正面影响。"
|
||||
elif score >= 8:
|
||||
interpretation += "这是中等的行星力量,表示该行星的作用较为平衡,既有积极面也有挑战。"
|
||||
elif score >= 4:
|
||||
interpretation += "这是较弱的行星力量,表示该行星在发挥作用时会遇到一些困难和阻碍。"
|
||||
else:
|
||||
interpretation += "这是极弱的行星力量,表示该行星难以充分发挥其作用,需要通过补救措施来增强。"
|
||||
|
||||
# 找出最强和最弱的分盘
|
||||
"""陈述加权后的星主关系,不把分数说成吉凶或应验。"""
|
||||
text = (
|
||||
f"{planet}的 Vimsopaka Bala 为 {score:.2f}/20,数值分档 {category}。"
|
||||
"这项只计分盘里的星主关系,不是功能吉凶,也不表示必然结果。"
|
||||
)
|
||||
if varga_scores:
|
||||
sorted_vargas = sorted(varga_scores.items(), key=lambda x: x[1]['weighted_score'], reverse=True)
|
||||
strongest = sorted_vargas[0]
|
||||
weakest = sorted_vargas[-1]
|
||||
|
||||
interpretation += f"\n\n最强分盘:{strongest[0]}({strongest[1]['dignity']},得分{strongest[1]['weighted_score']})"
|
||||
interpretation += f"\n最弱分盘:{weakest[0]}({weakest[1]['dignity']},得分{weakest[1]['weighted_score']})"
|
||||
|
||||
return interpretation
|
||||
ranked = sorted(varga_scores.items(), key=lambda item: item[1]['virupas'], reverse=True)
|
||||
text += f" 关系分最高:{ranked[0][0]}({ranked[0][1]['virupas']:g}/20)。"
|
||||
text += f" 关系分最低:{ranked[-1][0]}({ranked[-1][1]['virupas']:g}/20)。"
|
||||
if len(varga_scores) < len(self.weights):
|
||||
text += " 输入不完整,这里只是已计入分盘的合计,不是完整分数。"
|
||||
return text
|
||||
|
||||
def compare_planets(self, results: Dict[str, Dict]) -> List[Tuple[str, float]]:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user