Files
Jyotisha/scripts/vimsopaka_calculator.py
T

300 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Vimsopaka Bala Calculator - 分盘综合力量计算器
印度占星 Vimsopaka Bala(20分力量)系统
核心功能:
- 计算16种分盘(Shodasavarga)的行星尊严
- 根据BPHS权重系统计算Vimsopaka Bala
- 提供行星在各分盘的综合力量评分
- 支持Dasa Varga(10分盘)和Shodasavarga(16分盘)两种模式
参考文献:
- Brihat Parashara Hora Shastra (BPHS) Chapter 7
- B.V. Raman - "A Manual of Hindu Astrology"
"""
from typing import Dict, List, Tuple
from enum import Enum
class VargaType(Enum):
"""分盘类型"""
D1 = "Rashi" # 本命盘
D2 = "Hora" # 财富
D3 = "Drekkana" # 兄弟姐妹
D4 = "Chaturthamsa" # 财产/运气
D7 = "Saptamsa" # 子女
D9 = "Navamsa" # 配偶/灵性
D10 = "Dasamsa" # 事业
D12 = "Dwadasamsa" # 父母
D16 = "Shodasamsa" # 交通工具
D20 = "Vimsamsa" # 灵性修行
D24 = "Chaturvimsamsa" # 教育/学习
D27 = "Bhamsa" # 力量/弱点
D30 = "Trimsamsa" # 不幸/困难
D40 = "Khavedamsa" # 吉凶效果
D45 = "Akshavedamsa" # 全面判断
D60 = "Shashtiamsa" # 前世业力
class DignityLevel(Enum):
"""行星尊严等级"""
EXALTED = "Exalted" # 入庙(最高)
MOOLATRIKONA = "Moolatrikona" # 根本三角
OWN_SIGN = "Own Sign" # 自己的星座
GREAT_FRIEND = "Great Friend" # 极友
FRIEND = "Friend" # 友好星座
NEUTRAL = "Neutral" # 中性星座
ENEMY = "Enemy" # 敌对星座
GREAT_ENEMY = "Great Enemy" # 极敌
DEBILITATED = "Debilitated" # 落陷(最低)
NEECHA_BHANGA = "Neecha Bhanga" # 落陷取消
class VimsopakaBalaCalculator:
"""Vimsopaka Bala计算器"""
# BPHS标准权重系统(Shodasavarga - 16分盘)
SHODASAVARGA_WEIGHTS = {
VargaType.D1: 3.5, # Rashi
VargaType.D2: 1.0, # Hora
VargaType.D3: 1.0, # Drekkana
VargaType.D4: 0.5, # Chaturthamsa
VargaType.D7: 0.5, # Saptamsa
VargaType.D9: 3.0, # Navamsa;十六分盘权重合计 20
VargaType.D10: 0.5, # Dasamsa
VargaType.D12: 0.5, # Dwadasamsa
VargaType.D16: 2.0, # Shodasamsa
VargaType.D20: 0.5, # Vimsamsa
VargaType.D24: 0.5, # Chaturvimsamsa
VargaType.D27: 0.5, # Bhamsa
VargaType.D30: 1.0, # Trimsamsa
VargaType.D40: 0.5, # Khavedamsa
VargaType.D45: 0.5, # Akshavedamsa
VargaType.D60: 4.0 # Shashtiamsa
}
# Dasa Varga权重系统(10分盘 - 简化版)
DASAVARGA_WEIGHTS = {
VargaType.D1: 3.0,
VargaType.D2: 1.5,
VargaType.D3: 1.5,
VargaType.D7: 1.5,
VargaType.D9: 1.5,
VargaType.D10: 1.5,
VargaType.D12: 1.5,
VargaType.D16: 1.5,
VargaType.D30: 1.5,
VargaType.D60: 5.0
}
# 星主关系对应的 Virupas。落陷和落陷取消不是这项的输入。
DIGNITY_VIRUPAS = {
DignityLevel.EXALTED: 20.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 = {
"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"):
"""
初始化计算器
Args:
mode: "shodasavarga" (16分盘) 或 "dasavarga" (10分盘)
"""
self.mode = mode
self.weights = self.SHODASAVARGA_WEIGHTS if mode == "shodasavarga" else self.DASAVARGA_WEIGHTS
def calculate_vimsopaka_bala(self, planet_vargas: Dict[str, Dict[VargaType, DignityLevel]]) -> Dict[str, Dict]:
"""
计算所有行星的Vimsopaka Bala
Args:
planet_vargas: {行星名: {分盘类型: 尊严等级}}
Returns:
{行星名: {
"total_score": 总分,
"category": 力量等级,
"varga_scores": {分盘: 得分},
"interpretation": 解读
}}
"""
results = {}
for planet, vargas in planet_vargas.items():
planet_result = self._calculate_planet_vimsopaka(planet, vargas)
results[planet] = planet_result
return results
def _calculate_planet_vimsopaka(self, planet: str, vargas: Dict[VargaType, DignityLevel]) -> Dict:
"""计算单个行星的Vimsopaka Bala"""
varga_scores = {}
total_weighted_score = 0.0
total_weight = 0.0
# 计算每个分盘的得分
for varga_type, dignity in vargas.items():
if varga_type in self.weights:
# 只接受星主关系。落陷或落陷取消不能当作尊贵分。
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]
# 计算加权得分
weighted_score = virupas * weight
varga_scores[varga_type.value] = {
"dignity": dignity.value,
"virupas": virupas,
"weight": weight,
"weighted_score": round(weighted_score, 2)
}
total_weighted_score += weighted_score
total_weight += weight
# 分母固定为 20,不按已提供分盘的权重再归一。
if total_weight > 0:
final_score = total_weighted_score / 20.0
else:
final_score = 0.0
# 确定力量等级
category = self._get_strength_category(final_score)
# 生成解读
interpretation = self._generate_interpretation(planet, final_score, category, varga_scores)
return {
"planet": planet,
"total_score": round(final_score, 2),
"category": category,
"varga_scores": varga_scores,
"interpretation": interpretation,
"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:
"""根据得分确定力量等级"""
for category, (min_score, max_score) in self.STRENGTH_CATEGORIES.items():
if min_score <= score < max_score:
return category
return "Unclassified"
def _generate_interpretation(self, planet: str, score: float, category: str, varga_scores: Dict) -> str:
"""陈述加权后的星主关系,不把分数说成吉凶或应验。"""
text = (
f"{planet}的 Vimsopaka Bala 为 {score:.2f}/20,数值分档 {category}。"
"这项只计分盘里的星主关系,不是功能吉凶,也不表示必然结果。"
)
if varga_scores:
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]]:
"""
比较所有行星的力量,返回排序列表
Args:
results: calculate_vimsopaka_bala的返回结果
Returns:
[(行星名, 得分), ...] 按得分降序排列
"""
planet_scores = [(planet, data["total_score"]) for planet, data in results.items()]
return sorted(planet_scores, key=lambda x: x[1], reverse=True)
def get_remedial_recommendations(self, planet: str, score: float) -> List[str]:
"""
根据Vimsopaka Bala得分提供补救建议
Args:
planet: 行星名
score: Vimsopaka Bala得分
Returns:
补救建议列表
"""
recommendations = []
if score < 8: # 力量较弱,需要补救
recommendations.append(f"建议佩戴{planet}对应的宝石来增强力量")
recommendations.append(f"在{planet}主管的日子进行布施(Daan)")
recommendations.append(f"念诵{planet}的咒语(Mantra)")
recommendations.append(f"在{planet}主管的时辰进行重要活动")
if score < 4: # 极弱,需要额外补救
recommendations.append(f"考虑进行{planet}的火祭仪式(Homa)")
recommendations.append(f"在{planet}主管的日子断食")
return recommendations
# 示例用法
if __name__ == "__main__":
# 创建计算器(使用16分盘模式)
calculator = VimsopakaBalaCalculator(mode="shodasavarga")
# 示例数据:太阳在各分盘的尊严
sun_vargas = {
VargaType.D1: DignityLevel.EXALTED,
VargaType.D2: DignityLevel.OWN_SIGN,
VargaType.D3: DignityLevel.FRIEND,
VargaType.D9: DignityLevel.MOOLATRIKONA,
VargaType.D10: DignityLevel.FRIEND,
VargaType.D12: DignityLevel.NEUTRAL,
VargaType.D16: DignityLevel.OWN_SIGN,
VargaType.D20: DignityLevel.FRIEND,
VargaType.D30: DignityLevel.ENEMY,
VargaType.D60: DignityLevel.EXALTED
}
# 计算所有行星的Vimsopaka Bala
planet_vargas = {
"Sun": sun_vargas
}
results = calculator.calculate_vimsopaka_bala(planet_vargas)
# 打印结果
for planet, data in results.items():
print(f"\n{'='*60}")
print(f"{planet} - Vimsopaka Bala分析")
print(f"{'='*60}")
print(f"总分:{data['total_score']}/20")
print(f"等级:{data['category']}")
print(f"\n{data['interpretation']}")
# 如果需要补救
remedies = calculator.get_remedial_recommendations(planet, data['total_score'])
if remedies:
print(f"\n补救建议:")
for i, remedy in enumerate(remedies, 1):
print(f"{i}. {remedy}")