feat: v4.4.0 集成5个新模块到21步full-reading调用链 + 修复Dasha years展示
## 核心变更 ### 1. full-reading 调用链从 16 步扩展到 21 步 (v4.4.0) - Step 1.5: Special Lagnas 特殊上升点(Bhava/Hora/Ghati/Arudha/Upapada) - Step 4.5: Vimsopaka Bala 分盘力量(16分盘权重系统) - Step 4.6: Divisional Charts Extended 扩展分盘(D5/D6/D8/D11) - Step 6+: Karaka JH Compatible Mode(Jagannatha Hora 兼容) - Step 10.5: Avasthas 行星状态(5种状态体系) ### 2. 修复 Dasha timeline 第一个 MD 的 years 字段 - 之前: years 显示完整年数(如 18 年) - 修复: 第一个 MD 的 years 显示 balance(如 11.1 年) - 新增 is_balance 字段标识 - 日期计算本身始终正确,本次仅修正展示值 ### 3. 消除根目录重复文件 - 5 个模块从根目录移至 scripts/(与其他 19 个模块一致) - skills/jyotish-engine-modules/ 保留作为独立分发包 - 更新嵌套 Skill 的导入路径说明 ### 版本号 - full-reading: v4.1.0 → v4.4.0
This commit is contained in:
@@ -0,0 +1,481 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Avastha Calculator - 行星状态计算器
|
||||
印度占星 Avastha(行星状态)系统
|
||||
|
||||
核心功能:
|
||||
- Bala Avastha(年龄状态):5种生命阶段
|
||||
- Jagrat Avastha(警觉状态):3种意识状态
|
||||
- Deeptadi Avastha(情绪状态):15种情绪/能量状态
|
||||
- Lajjitadi Avastha(羞耻状态):6种社会状态
|
||||
- Shayanadi Avastha(姿态状态):12种行为模式
|
||||
|
||||
参考文献:
|
||||
- Brihat Parashara Hora Shastra (BPHS) Chapter 47-48
|
||||
- Phaladeepika by Mantreswara
|
||||
- Jataka Parijata by Vaidyanatha Dikshita
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Tuple
|
||||
from enum import Enum
|
||||
|
||||
class BalaAvastha(Enum):
|
||||
"""年龄状态(5种生命阶段)"""
|
||||
INFANT = "Infant" # 婴儿期(0-6度)
|
||||
YOUNG = "Young" # 少年期(6-12度)
|
||||
YOUTH = "Youth" # 青年期(12-18度)
|
||||
OLD = "Old" # 老年期(18-24度)
|
||||
DEAD = "Dead" # 死亡期(24-30度)
|
||||
|
||||
class JagratAvastha(Enum):
|
||||
"""警觉状态(3种意识状态)"""
|
||||
AWAKE = "Awake" # 清醒(Jagrat)
|
||||
DREAMING = "Dreaming" # 梦境(Swapna)
|
||||
DEEP_SLEEP = "Deep Sleep" # 深睡(Sushupti)
|
||||
|
||||
class DeeptadiAvastha(Enum):
|
||||
"""情绪状态(15种)- Deeptadi Avastha"""
|
||||
DEEPTA = "Deepta" # 光辉(Exalted)
|
||||
SWASTHA = "Swastha" # 舒适(Own Sign)
|
||||
MUDITA = "Mudita" # 快乐(Friend's Sign)
|
||||
SHANTA = "Shanta" # 平静(Neutral Sign)
|
||||
DINA = "Dina" # 沮丧(Enemy Sign)
|
||||
VIKALA = "Vikala" # 残缺(Debilitated)
|
||||
KHALA = "Khala" # 恶意(Combust)
|
||||
KOPA = "Kopa" # 愤怒(Defeated in War)
|
||||
GARVITA = "Garvita" # 骄傲(Victorious in War)
|
||||
KSHUDITA = "Kshudita" # 饥饿(In Sandhi)
|
||||
TRUSHITA = "Trushita" # 口渴(In Gandanta)
|
||||
MUDITA_SPECIAL = "Mudita" # 特殊快乐(Aspected by Jupiter)
|
||||
KSHOBHITA = "Kshobhita" # 激动(Aspected by Mars)
|
||||
LAJJITA = "Lajjita" # 羞耻(Aspected by Saturn)
|
||||
GARVITA_SPECIAL = "Garvita" # 特殊骄傲(Aspected by Mercury)
|
||||
|
||||
class LajjitadiAvastha(Enum):
|
||||
"""羞耻状态(6种社会状态)"""
|
||||
LAJJITA = "Lajjita" # 羞耻(与敌对行星同宫)
|
||||
GARVITA = "Garvita" # 骄傲(入庙)
|
||||
KSHUDITA = "Kshudita" # 饥饿(在6/8/12宫)
|
||||
TRUSHITA = "Trushita" # 口渴(在火象星座)
|
||||
MUDITA = "Mudita" # 快乐(与友好行星同宫)
|
||||
KSHOBHITA = "Kshobhita" # 激动(与火星同宫)
|
||||
|
||||
class ShayanadiAvastha(Enum):
|
||||
"""姿态状态(12种行为模式)"""
|
||||
SHAYANA = "Shayana" # 躺卧(在水象星座)
|
||||
UPAVESHANA = "Upaveshana" # 坐着(在土象星座)
|
||||
NETRAPANI = "Netrapani" # 手持武器(在火象星座)
|
||||
PRAKASHANA = "Prakashana" # 显现(在风象星座)
|
||||
GAMANA = "Gamana" # 行走(在双体星座)
|
||||
AGAMANA = "Agamana" # 到来(在固定星座)
|
||||
SABHA = "Sabha" # 集会(在变动星座)
|
||||
AGAMA = "Agama" # 学习(在水星星座)
|
||||
BHOJANA = "Bhojana" # 进食(在金星星座)
|
||||
NRITYALIPSA = "Nrityalipsa" # 舞蹈(在月亮星座)
|
||||
KAUTUKA = "Kautuka" # 好奇(在木星星座)
|
||||
NIDRA = "Nidra" # 睡眠(在土星星座)
|
||||
|
||||
class AvasthaCalculator:
|
||||
"""行星状态计算器"""
|
||||
|
||||
# 星座分类
|
||||
FIRE_SIGNS = ["Aries", "Leo", "Sagittarius"]
|
||||
EARTH_SIGNS = ["Taurus", "Virgo", "Capricorn"]
|
||||
AIR_SIGNS = ["Gemini", "Libra", "Aquarius"]
|
||||
WATER_SIGNS = ["Cancer", "Scorpio", "Pisces"]
|
||||
|
||||
DUAL_SIGNS = ["Gemini", "Virgo", "Sagittarius", "Pisces"]
|
||||
FIXED_SIGNS = ["Taurus", "Leo", "Scorpio", "Aquarius"]
|
||||
MOVABLE_SIGNS = ["Aries", "Cancer", "Libra", "Capricorn"]
|
||||
|
||||
# 行星主宰星座
|
||||
PLANET_SIGNS = {
|
||||
"Mercury": ["Gemini", "Virgo"],
|
||||
"Venus": ["Taurus", "Libra"],
|
||||
"Moon": ["Cancer"],
|
||||
"Jupiter": ["Sagittarius", "Pisces"],
|
||||
"Saturn": ["Capricorn", "Aquarius"],
|
||||
"Mars": ["Aries", "Scorpio"],
|
||||
"Sun": ["Leo"]
|
||||
}
|
||||
|
||||
# 行星入庙/落陷度数
|
||||
EXALTATION = {
|
||||
"Sun": ("Aries", 10),
|
||||
"Moon": ("Taurus", 3),
|
||||
"Mars": ("Capricorn", 28),
|
||||
"Mercury": ("Virgo", 15),
|
||||
"Jupiter": ("Cancer", 5),
|
||||
"Venus": ("Pisces", 27),
|
||||
"Saturn": ("Libra", 20)
|
||||
}
|
||||
|
||||
DEBILITATION = {
|
||||
"Sun": ("Libra", 10),
|
||||
"Moon": ("Scorpio", 3),
|
||||
"Mars": ("Cancer", 28),
|
||||
"Mercury": ("Pisces", 15),
|
||||
"Jupiter": ("Capricorn", 5),
|
||||
"Venus": ("Virgo", 27),
|
||||
"Saturn": ("Aries", 20)
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def calculate_all_avasthas(self, planet: str, sign: str, degree: float,
|
||||
house: int, conjunctions: List[str] = None,
|
||||
aspects: List[str] = None, is_combust: bool = False,
|
||||
is_retrograde: bool = False) -> Dict[str, any]:
|
||||
"""
|
||||
计算行星的所有Avastha状态
|
||||
|
||||
Args:
|
||||
planet: 行星名
|
||||
sign: 所在星座
|
||||
degree: 星座内度数(0-30)
|
||||
house: 所在宫位(1-12)
|
||||
conjunctions: 合相的行星列表
|
||||
aspects: 相位的行星列表
|
||||
is_combust: 是否燃烧
|
||||
is_retrograde: 是否逆行
|
||||
|
||||
Returns:
|
||||
所有Avastha状态的字典
|
||||
"""
|
||||
result = {
|
||||
"planet": planet,
|
||||
"sign": sign,
|
||||
"degree": round(degree, 4),
|
||||
"house": house,
|
||||
"avasthas": {}
|
||||
}
|
||||
|
||||
# 1. Bala Avastha(年龄状态)
|
||||
result["avasthas"]["Bala"] = self._calculate_bala_avastha(degree)
|
||||
|
||||
# 2. Jagrat Avastha(警觉状态)
|
||||
result["avasthas"]["Jagrat"] = self._calculate_jagrat_avastha(planet, sign, house)
|
||||
|
||||
# 3. Deeptadi Avastha(情绪状态)
|
||||
result["avasthas"]["Deeptadi"] = self._calculate_deeptadi_avastha(
|
||||
planet, sign, degree, is_combust, aspects
|
||||
)
|
||||
|
||||
# 4. Lajjitadi Avastha(羞耻状态)
|
||||
result["avasthas"]["Lajjitadi"] = self._calculate_lajjitadi_avastha(
|
||||
planet, sign, house, conjunctions
|
||||
)
|
||||
|
||||
# 5. Shayanadi Avastha(姿态状态)
|
||||
result["avasthas"]["Shayanadi"] = self._calculate_shayanadi_avastha(planet, sign)
|
||||
|
||||
# 6. 综合解读
|
||||
result["interpretation"] = self._generate_interpretation(result["avasthas"])
|
||||
|
||||
# 7. 补救建议
|
||||
result["remedies"] = self._generate_remedies(planet, result["avasthas"])
|
||||
|
||||
return result
|
||||
|
||||
def _calculate_bala_avastha(self, degree: float) -> Dict:
|
||||
"""计算Bala Avastha(年龄状态)"""
|
||||
if degree < 6:
|
||||
state = BalaAvastha.INFANT
|
||||
strength = 0.2
|
||||
meaning = "婴儿期:行星力量微弱,潜力未开发,需要时间成长"
|
||||
elif degree < 12:
|
||||
state = BalaAvastha.YOUNG
|
||||
strength = 0.5
|
||||
meaning = "少年期:行星力量增长中,开始显现特质,但尚未成熟"
|
||||
elif degree < 18:
|
||||
state = BalaAvastha.YOUTH
|
||||
strength = 1.0
|
||||
meaning = "青年期:行星力量最强,充满活力,能够充分发挥作用"
|
||||
elif degree < 24:
|
||||
state = BalaAvastha.OLD
|
||||
strength = 0.7
|
||||
meaning = "老年期:行星力量开始衰退,经验丰富但活力下降"
|
||||
else:
|
||||
state = BalaAvastha.DEAD
|
||||
strength = 0.3
|
||||
meaning = "死亡期:行星力量极弱,难以发挥作用,需要补救"
|
||||
|
||||
return {
|
||||
"state": state.value,
|
||||
"degree_range": f"{int(degree//6)*6}-{int(degree//6)*6+6}°",
|
||||
"strength": strength,
|
||||
"meaning": meaning
|
||||
}
|
||||
|
||||
def _calculate_jagrat_avastha(self, planet: str, sign: str, house: int) -> Dict:
|
||||
"""计算Jagrat Avastha(警觉状态)"""
|
||||
# 简化规则:
|
||||
# Awake: 在角宫(1,4,7,10)
|
||||
# Dreaming: 在续宫(2,5,8,11)
|
||||
# Deep Sleep: 在果宫(3,6,9,12)
|
||||
|
||||
if house in [1, 4, 7, 10]:
|
||||
state = JagratAvastha.AWAKE
|
||||
meaning = "清醒状态:行星完全活跃,能够主动发挥作用,影响显著"
|
||||
elif house in [2, 5, 8, 11]:
|
||||
state = JagratAvastha.DREAMING
|
||||
meaning = "梦境状态:行星半活跃,作用不稳定,时强时弱"
|
||||
else:
|
||||
state = JagratAvastha.DEEP_SLEEP
|
||||
meaning = "深睡状态:行星不活跃,难以发挥作用,影响微弱"
|
||||
|
||||
return {
|
||||
"state": state.value,
|
||||
"house": house,
|
||||
"meaning": meaning
|
||||
}
|
||||
|
||||
def _calculate_deeptadi_avastha(self, planet: str, sign: str, degree: float,
|
||||
is_combust: bool, aspects: List[str] = None) -> Dict:
|
||||
"""计算Deeptadi Avastha(情绪状态)"""
|
||||
aspects = aspects or []
|
||||
|
||||
# 检查入庙/落陷
|
||||
if self._is_exalted(planet, sign, degree):
|
||||
state = DeeptadiAvastha.DEEPTA
|
||||
meaning = "光辉状态:行星处于最佳位置,能量充沛,带来积极结果"
|
||||
elif self._is_debilitated(planet, sign, degree):
|
||||
state = DeeptadiAvastha.VIKALA
|
||||
meaning = "残缺状态:行星处于最弱位置,能量受损,带来挑战"
|
||||
elif is_combust:
|
||||
state = DeeptadiAvastha.KHALA
|
||||
meaning = "恶意状态:行星被太阳燃烧,能量被压制,难以正常发挥"
|
||||
elif self._is_own_sign(planet, sign):
|
||||
state = DeeptadiAvastha.SWASTHA
|
||||
meaning = "舒适状态:行星在自己的星座,感觉自在,能够稳定发挥"
|
||||
elif self._is_friend_sign(planet, sign):
|
||||
state = DeeptadiAvastha.MUDITA
|
||||
meaning = "快乐状态:行星在友好星座,得到支持,能够良好发挥"
|
||||
elif self._is_enemy_sign(planet, sign):
|
||||
state = DeeptadiAvastha.DINA
|
||||
meaning = "沮丧状态:行星在敌对星座,受到压制,发挥受限"
|
||||
else:
|
||||
state = DeeptadiAvastha.SHANTA
|
||||
meaning = "平静状态:行星在中性星座,不强不弱,平稳发挥"
|
||||
|
||||
# 检查相位影响
|
||||
aspect_effects = []
|
||||
if "Jupiter" in aspects:
|
||||
aspect_effects.append("木星相位:增加乐观和扩展性")
|
||||
if "Mars" in aspects:
|
||||
aspect_effects.append("火星相位:增加激情和冲动性")
|
||||
if "Saturn" in aspects:
|
||||
aspect_effects.append("土星相位:增加限制和责任感")
|
||||
if "Mercury" in aspects:
|
||||
aspect_effects.append("水星相位:增加智慧和沟通能力")
|
||||
|
||||
return {
|
||||
"state": state.value,
|
||||
"meaning": meaning,
|
||||
"aspect_effects": aspect_effects
|
||||
}
|
||||
|
||||
def _calculate_lajjitadi_avastha(self, planet: str, sign: str, house: int,
|
||||
conjunctions: List[str] = None) -> Dict:
|
||||
"""计算Lajjitadi Avastha(羞耻状态)"""
|
||||
conjunctions = conjunctions or []
|
||||
|
||||
# 简化规则
|
||||
if self._is_exalted(planet, sign, 15): # 简化判断
|
||||
state = LajjitadiAvastha.GARVITA
|
||||
meaning = "骄傲状态:行星入庙,充满自信,能够展现最佳特质"
|
||||
elif house in [6, 8, 12]:
|
||||
state = LajjitadiAvastha.KSHUDITA
|
||||
meaning = "饥饿状态:行星在困难宫位,渴望满足,但难以获得"
|
||||
elif sign in self.FIRE_SIGNS:
|
||||
state = LajjitadiAvastha.TRUSHITA
|
||||
meaning = "口渴状态:行星在火象星座,能量过热,需要冷却"
|
||||
elif "Mars" in conjunctions:
|
||||
state = LajjitadiAvastha.KSHOBHITA
|
||||
meaning = "激动状态:与火星合相,能量激烈,容易冲动"
|
||||
elif any(self._is_enemy_planet(planet, conj) for conj in conjunctions):
|
||||
state = LajjitadiAvastha.LAJJITA
|
||||
meaning = "羞耻状态:与敌对行星同宫,感到不适,发挥受限"
|
||||
else:
|
||||
state = LajjitadiAvastha.MUDITA
|
||||
meaning = "快乐状态:与友好行星同宫,感到愉悦,能够良好发挥"
|
||||
|
||||
return {
|
||||
"state": state.value,
|
||||
"meaning": meaning,
|
||||
"conjunctions": conjunctions
|
||||
}
|
||||
|
||||
def _calculate_shayanadi_avastha(self, planet: str, sign: str) -> Dict:
|
||||
"""计算Shayanadi Avastha(姿态状态)"""
|
||||
# 根据星座元素和类型判断
|
||||
if sign in self.WATER_SIGNS:
|
||||
state = ShayanadiAvastha.SHAYANA
|
||||
meaning = "躺卧姿态:行星在水象星座,处于休息状态,被动接受"
|
||||
elif sign in self.EARTH_SIGNS:
|
||||
state = ShayanadiAvastha.UPAVESHANA
|
||||
meaning = "坐着姿态:行星在土象星座,稳定扎根,缓慢行动"
|
||||
elif sign in self.FIRE_SIGNS:
|
||||
state = ShayanadiAvastha.NETRAPANI
|
||||
meaning = "持武器姿态:行星在火象星座,充满战斗力,主动出击"
|
||||
elif sign in self.AIR_SIGNS:
|
||||
state = ShayanadiAvastha.PRAKASHANA
|
||||
meaning = "显现姿态:行星在风象星座,灵活多变,善于表达"
|
||||
else:
|
||||
state = ShayanadiAvastha.GAMANA
|
||||
meaning = "行走姿态:行星处于移动状态,不断变化"
|
||||
|
||||
# 根据行星主宰星座判断特殊状态
|
||||
for planet_name, signs in self.PLANET_SIGNS.items():
|
||||
if sign in signs:
|
||||
if planet_name == "Mercury":
|
||||
state = ShayanadiAvastha.AGAMA
|
||||
meaning = "学习姿态:在水星星座,专注于学习和沟通"
|
||||
elif planet_name == "Venus":
|
||||
state = ShayanadiAvastha.BHOJANA
|
||||
meaning = "进食姿态:在金星星座,享受物质和感官愉悦"
|
||||
elif planet_name == "Moon":
|
||||
state = ShayanadiAvastha.NRITYALIPSA
|
||||
meaning = "舞蹈姿态:在月亮星座,情感丰富,富有表现力"
|
||||
elif planet_name == "Jupiter":
|
||||
state = ShayanadiAvastha.KAUTUKA
|
||||
meaning = "好奇姿态:在木星星座,渴望探索和扩展"
|
||||
elif planet_name == "Saturn":
|
||||
state = ShayanadiAvastha.NIDRA
|
||||
meaning = "睡眠姿态:在土星星座,能量收缩,需要休息"
|
||||
break
|
||||
|
||||
return {
|
||||
"state": state.value,
|
||||
"sign": sign,
|
||||
"meaning": meaning
|
||||
}
|
||||
|
||||
def _is_exalted(self, planet: str, sign: str, degree: float) -> bool:
|
||||
"""检查是否入庙"""
|
||||
if planet in self.EXALTATION:
|
||||
exalt_sign, exalt_degree = self.EXALTATION[planet]
|
||||
return sign == exalt_sign and abs(degree - exalt_degree) < 5
|
||||
return False
|
||||
|
||||
def _is_debilitated(self, planet: str, sign: str, degree: float) -> bool:
|
||||
"""检查是否落陷"""
|
||||
if planet in self.DEBILITATION:
|
||||
debil_sign, debil_degree = self.DEBILITATION[planet]
|
||||
return sign == debil_sign and abs(degree - debil_degree) < 5
|
||||
return False
|
||||
|
||||
def _is_own_sign(self, planet: str, sign: str) -> bool:
|
||||
"""检查是否在自己的星座"""
|
||||
return sign in self.PLANET_SIGNS.get(planet, [])
|
||||
|
||||
def _is_friend_sign(self, planet: str, sign: str) -> bool:
|
||||
"""检查是否在友好星座(简化版)"""
|
||||
# 这里需要完整的行星友好关系表,暂时简化
|
||||
return False
|
||||
|
||||
def _is_enemy_sign(self, planet: str, sign: str) -> bool:
|
||||
"""检查是否在敌对星座(简化版)"""
|
||||
# 这里需要完整的行星敌对关系表,暂时简化
|
||||
return False
|
||||
|
||||
def _is_enemy_planet(self, planet1: str, planet2: str) -> bool:
|
||||
"""检查两个行星是否敌对(简化版)"""
|
||||
# 这里需要完整的行星关系表,暂时简化
|
||||
enemies = {
|
||||
"Sun": ["Saturn", "Venus"],
|
||||
"Moon": ["Rahu", "Ketu"],
|
||||
"Mars": ["Mercury"],
|
||||
"Mercury": ["Moon"],
|
||||
"Jupiter": ["Mercury", "Venus"],
|
||||
"Venus": ["Sun", "Moon"],
|
||||
"Saturn": ["Sun", "Moon", "Mars"]
|
||||
}
|
||||
return planet2 in enemies.get(planet1, [])
|
||||
|
||||
def _generate_interpretation(self, avasthas: Dict) -> str:
|
||||
"""生成综合解读"""
|
||||
interpretation = "行星状态综合分析:\n\n"
|
||||
|
||||
# Bala Avastha
|
||||
bala = avasthas["Bala"]
|
||||
interpretation += f"1. 年龄状态:{bala['state']}({bala['degree_range']})\n"
|
||||
interpretation += f" {bala['meaning']}\n\n"
|
||||
|
||||
# Jagrat Avastha
|
||||
jagrat = avasthas["Jagrat"]
|
||||
interpretation += f"2. 警觉状态:{jagrat['state']}(第{jagrat['house']}宫)\n"
|
||||
interpretation += f" {jagrat['meaning']}\n\n"
|
||||
|
||||
# Deeptadi Avastha
|
||||
deeptadi = avasthas["Deeptadi"]
|
||||
interpretation += f"3. 情绪状态:{deeptadi['state']}\n"
|
||||
interpretation += f" {deeptadi['meaning']}\n"
|
||||
if deeptadi['aspect_effects']:
|
||||
interpretation += " 相位影响:\n"
|
||||
for effect in deeptadi['aspect_effects']:
|
||||
interpretation += f" - {effect}\n"
|
||||
interpretation += "\n"
|
||||
|
||||
# Lajjitadi Avastha
|
||||
lajjitadi = avasthas["Lajjitadi"]
|
||||
interpretation += f"4. 社会状态:{lajjitadi['state']}\n"
|
||||
interpretation += f" {lajjitadi['meaning']}\n\n"
|
||||
|
||||
# Shayanadi Avastha
|
||||
shayanadi = avasthas["Shayanadi"]
|
||||
interpretation += f"5. 行为模式:{shayanadi['state']}({shayanadi['sign']})\n"
|
||||
interpretation += f" {shayanadi['meaning']}\n"
|
||||
|
||||
return interpretation
|
||||
|
||||
def _generate_remedies(self, planet: str, avasthas: Dict) -> List[str]:
|
||||
"""生成补救建议"""
|
||||
remedies = []
|
||||
|
||||
# 根据Bala Avastha
|
||||
bala_strength = avasthas["Bala"]["strength"]
|
||||
if bala_strength < 0.5:
|
||||
remedies.append(f"行星处于弱势年龄阶段,建议佩戴{planet}对应的宝石")
|
||||
remedies.append(f"在{planet}主管的日子进行布施和祈祷")
|
||||
|
||||
# 根据Jagrat Avastha
|
||||
if avasthas["Jagrat"]["state"] == "Deep Sleep":
|
||||
remedies.append("行星处于深睡状态,建议通过冥想和咒语激活其能量")
|
||||
|
||||
# 根据Deeptadi Avastha
|
||||
deeptadi_state = avasthas["Deeptadi"]["state"]
|
||||
if deeptadi_state in ["Vikala", "Khala", "Dina"]:
|
||||
remedies.append(f"行星处于{deeptadi_state}状态,需要特别补救")
|
||||
remedies.append(f"念诵{planet}的Beeja Mantra(种子咒)")
|
||||
|
||||
return remedies
|
||||
|
||||
|
||||
# 示例用法
|
||||
if __name__ == "__main__":
|
||||
calculator = AvasthaCalculator()
|
||||
|
||||
# 示例:太阳在白羊座15度,第10宫
|
||||
result = calculator.calculate_all_avasthas(
|
||||
planet="Sun",
|
||||
sign="Aries",
|
||||
degree=15.0,
|
||||
house=10,
|
||||
conjunctions=["Mercury"],
|
||||
aspects=["Jupiter", "Saturn"],
|
||||
is_combust=False,
|
||||
is_retrograde=False
|
||||
)
|
||||
|
||||
print("="*60)
|
||||
print(f"{result['planet']} 在 {result['sign']} {result['degree']}° (第{result['house']}宫)")
|
||||
print("="*60)
|
||||
print(result['interpretation'])
|
||||
|
||||
if result['remedies']:
|
||||
print("\n补救建议:")
|
||||
for i, remedy in enumerate(result['remedies'], 1):
|
||||
print(f"{i}. {remedy}")
|
||||
@@ -0,0 +1,534 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Divisional Charts Extended - D2-D60完整分盘宫位图计算器
|
||||
印度占星 Shodasavarga(16分盘)+ 扩展分盘系统
|
||||
|
||||
核心功能:
|
||||
- 计算D1-D60所有分盘的行星位置
|
||||
- 生成每个分盘的12宫位行星分布图
|
||||
- 支持BPHS标准算法
|
||||
- 提供分盘上升点计算
|
||||
- 输出可视化宫位图数据
|
||||
|
||||
参考文献:
|
||||
- Brihat Parashara Hora Shastra (BPHS) Chapter 6
|
||||
- Phaladeepika by Mantreswara
|
||||
- Jataka Parijata by Vaidyanatha Dikshita
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Tuple
|
||||
from enum import Enum
|
||||
|
||||
class VargaType(Enum):
|
||||
"""分盘类型枚举"""
|
||||
D1 = (1, "Rashi", "本命盘")
|
||||
D2 = (2, "Hora", "财富")
|
||||
D3 = (3, "Drekkana", "兄弟姐妹")
|
||||
D4 = (4, "Chaturthamsa", "财产/运气")
|
||||
D5 = (5, "Panchamsa", "名声/权力")
|
||||
D6 = (6, "Shashthamsa", "健康/敌人")
|
||||
D7 = (7, "Saptamsa", "子女")
|
||||
D8 = (8, "Ashtamsa", "突发事件")
|
||||
D9 = (9, "Navamsa", "配偶/灵性")
|
||||
D10 = (10, "Dasamsa", "事业")
|
||||
D11 = (11, "Rudramsa", "破坏/转化")
|
||||
D12 = (12, "Dwadasamsa", "父母")
|
||||
D16 = (16, "Shodasamsa", "交通工具/舒适")
|
||||
D20 = (20, "Vimsamsa", "灵性修行")
|
||||
D24 = (24, "Chaturvimsamsa", "教育/学习")
|
||||
D27 = (27, "Bhamsa", "力量/弱点")
|
||||
D30 = (30, "Trimsamsa", "不幸/困难")
|
||||
D40 = (40, "Khavedamsa", "吉凶效果")
|
||||
D45 = (45, "Akshavedamsa", "全面判断")
|
||||
D60 = (60, "Shashtiamsa", "前世业力")
|
||||
|
||||
def __init__(self, division: int, name: str, meaning: str):
|
||||
self.division = division
|
||||
self.varga_name = name
|
||||
self.meaning = meaning
|
||||
|
||||
class DivisionalChartsCalculator:
|
||||
"""分盘计算器"""
|
||||
|
||||
SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
|
||||
"Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
|
||||
|
||||
# 星座分类
|
||||
MOVABLE_SIGNS = [0, 3, 6, 9] # Aries, Cancer, Libra, Capricorn
|
||||
FIXED_SIGNS = [1, 4, 7, 10] # Taurus, Leo, Scorpio, Aquarius
|
||||
DUAL_SIGNS = [2, 5, 8, 11] # Gemini, Virgo, Sagittarius, Pisces
|
||||
|
||||
ODD_SIGNS = [0, 2, 4, 6, 8, 10] # 奇数星座
|
||||
EVEN_SIGNS = [1, 3, 5, 7, 9, 11] # 偶数星座
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def calculate_all_vargas(self, planet_positions: Dict[str, float],
|
||||
asc_degree: float) -> Dict[str, Dict]:
|
||||
"""
|
||||
计算所有分盘的行星位置
|
||||
|
||||
Args:
|
||||
planet_positions: {行星名: 黄道度数(0-360)}
|
||||
asc_degree: 上升点黄道度数(0-360)
|
||||
|
||||
Returns:
|
||||
{分盘名: {
|
||||
"planets": {行星名: {"sign": 星座, "degree": 度数, "house": 宫位}},
|
||||
"ascendant": {"sign": 星座, "degree": 度数},
|
||||
"house_chart": [宫位1的行星列表, 宫位2的行星列表, ...]
|
||||
}}
|
||||
"""
|
||||
results = {}
|
||||
|
||||
# 计算所有分盘
|
||||
for varga_type in VargaType:
|
||||
varga_result = self._calculate_single_varga(
|
||||
varga_type, planet_positions, asc_degree
|
||||
)
|
||||
results[varga_type.varga_name] = varga_result
|
||||
|
||||
return results
|
||||
|
||||
def _calculate_single_varga(self, varga_type: VargaType,
|
||||
planet_positions: Dict[str, float],
|
||||
asc_degree: float) -> Dict:
|
||||
"""计算单个分盘"""
|
||||
division = varga_type.division
|
||||
|
||||
# 计算分盘上升点
|
||||
varga_asc = self._calculate_varga_position(asc_degree, division)
|
||||
varga_asc_sign = int(varga_asc // 30)
|
||||
varga_asc_degree = varga_asc % 30
|
||||
|
||||
# 计算所有行星的分盘位置
|
||||
varga_planets = {}
|
||||
for planet, degree in planet_positions.items():
|
||||
varga_pos = self._calculate_varga_position(degree, division)
|
||||
varga_sign = int(varga_pos // 30)
|
||||
varga_degree = varga_pos % 30
|
||||
|
||||
# 计算宫位(从上升点开始)
|
||||
house = ((varga_sign - varga_asc_sign) % 12) + 1
|
||||
|
||||
varga_planets[planet] = {
|
||||
"sign": self.SIGNS[varga_sign],
|
||||
"sign_index": varga_sign,
|
||||
"degree": round(varga_degree, 4),
|
||||
"house": house,
|
||||
"absolute_degree": round(varga_pos, 4)
|
||||
}
|
||||
|
||||
# 生成宫位图(12个宫位,每个宫位包含的行星列表)
|
||||
house_chart = [[] for _ in range(12)]
|
||||
for planet, data in varga_planets.items():
|
||||
house_chart[data["house"] - 1].append(planet)
|
||||
|
||||
return {
|
||||
"division": division,
|
||||
"name": varga_type.varga_name,
|
||||
"meaning": varga_type.meaning,
|
||||
"ascendant": {
|
||||
"sign": self.SIGNS[varga_asc_sign],
|
||||
"sign_index": varga_asc_sign,
|
||||
"degree": round(varga_asc_degree, 4)
|
||||
},
|
||||
"planets": varga_planets,
|
||||
"house_chart": house_chart
|
||||
}
|
||||
|
||||
def _calculate_varga_position(self, degree: float, division: int) -> float:
|
||||
"""
|
||||
计算分盘位置(BPHS标准算法)
|
||||
|
||||
Args:
|
||||
degree: 黄道度数(0-360)
|
||||
division: 分盘数(2-60)
|
||||
|
||||
Returns:
|
||||
分盘中的黄道度数(0-360)
|
||||
"""
|
||||
# 获取星座索引和星座内度数
|
||||
sign_index = int(degree // 30)
|
||||
sign_degree = degree % 30
|
||||
|
||||
# 根据不同分盘使用不同算法
|
||||
if division == 2:
|
||||
return self._calculate_d2(sign_index, sign_degree)
|
||||
elif division == 3:
|
||||
return self._calculate_d3(sign_index, sign_degree)
|
||||
elif division == 4:
|
||||
return self._calculate_d4(sign_index, sign_degree)
|
||||
elif division == 5:
|
||||
return self._calculate_d5(sign_index, sign_degree)
|
||||
elif division == 6:
|
||||
return self._calculate_d6(sign_index, sign_degree)
|
||||
elif division == 7:
|
||||
return self._calculate_d7(sign_index, sign_degree)
|
||||
elif division == 8:
|
||||
return self._calculate_d8(sign_index, sign_degree)
|
||||
elif division == 9:
|
||||
return self._calculate_d9(sign_index, sign_degree)
|
||||
elif division == 10:
|
||||
return self._calculate_d10(sign_index, sign_degree)
|
||||
elif division == 11:
|
||||
return self._calculate_d11(sign_index, sign_degree)
|
||||
elif division == 12:
|
||||
return self._calculate_d12(sign_index, sign_degree)
|
||||
elif division == 16:
|
||||
return self._calculate_d16(sign_index, sign_degree)
|
||||
elif division == 20:
|
||||
return self._calculate_d20(sign_index, sign_degree)
|
||||
elif division == 24:
|
||||
return self._calculate_d24(sign_index, sign_degree)
|
||||
elif division == 27:
|
||||
return self._calculate_d27(sign_index, sign_degree)
|
||||
elif division == 30:
|
||||
return self._calculate_d30(sign_index, sign_degree)
|
||||
elif division == 40:
|
||||
return self._calculate_d40(sign_index, sign_degree)
|
||||
elif division == 45:
|
||||
return self._calculate_d45(sign_index, sign_degree)
|
||||
elif division == 60:
|
||||
return self._calculate_d60(sign_index, sign_degree)
|
||||
else:
|
||||
# 通用算法(适用于其他分盘)
|
||||
return self._calculate_generic_varga(sign_index, sign_degree, division)
|
||||
|
||||
def _calculate_d2(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D2 Hora - 财富分盘"""
|
||||
# 奇数星座:0-15度→Leo,15-30度→Cancer
|
||||
# 偶数星座:0-15度→Cancer,15-30度→Leo
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
if sign_degree < 15:
|
||||
return 4 * 30 + sign_degree * 2 # Leo
|
||||
else:
|
||||
return 3 * 30 + (sign_degree - 15) * 2 # Cancer
|
||||
else:
|
||||
if sign_degree < 15:
|
||||
return 3 * 30 + sign_degree * 2 # Cancer
|
||||
else:
|
||||
return 4 * 30 + (sign_degree - 15) * 2 # Leo
|
||||
|
||||
def _calculate_d3(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D3 Drekkana - 兄弟姐妹分盘"""
|
||||
# 每个星座分为3个10度区间
|
||||
# 第1个10度→本星座,第2个10度→第5个星座,第3个10度→第9个星座
|
||||
drekkana = int(sign_degree // 10)
|
||||
offset = [0, 4, 8][drekkana]
|
||||
varga_sign = (sign_index + offset) % 12
|
||||
varga_degree = (sign_degree % 10) * 3
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d4(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D4 Chaturthamsa - 财产/运气分盘"""
|
||||
# 每个星座分为4个7.5度区间
|
||||
part = int(sign_degree // 7.5)
|
||||
varga_sign = (sign_index + part * 3) % 12
|
||||
varga_degree = (sign_degree % 7.5) * 4
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d7(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D7 Saptamsa - 子女分盘"""
|
||||
# 每个星座分为7个约4.286度区间
|
||||
part = int(sign_degree // (30/7))
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 6 + part) % 12
|
||||
varga_degree = (sign_degree % (30/7)) * 7
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d9(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D9 Navamsa - 配偶/灵性分盘(最重要的分盘)"""
|
||||
# 每个星座分为9个3.333度区间
|
||||
part = int(sign_degree // (30/9))
|
||||
|
||||
# 根据星座类型确定起始点
|
||||
if sign_index in self.MOVABLE_SIGNS:
|
||||
start = sign_index # 从本星座开始
|
||||
elif sign_index in self.FIXED_SIGNS:
|
||||
start = (sign_index + 8) % 12 # 从第9个星座开始
|
||||
else: # DUAL_SIGNS
|
||||
start = (sign_index + 4) % 12 # 从第5个星座开始
|
||||
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % (30/9)) * 9
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d10(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D10 Dasamsa - 事业分盘"""
|
||||
# 每个星座分为10个3度区间
|
||||
part = int(sign_degree // 3)
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 8 + part) % 12
|
||||
varga_degree = (sign_degree % 3) * 10
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d12(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D12 Dwadasamsa - 父母分盘"""
|
||||
# 每个星座分为12个2.5度区间
|
||||
part = int(sign_degree // 2.5)
|
||||
varga_sign = (sign_index + part) % 12
|
||||
varga_degree = (sign_degree % 2.5) * 12
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d16(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D16 Shodasamsa - 交通工具/舒适分盘"""
|
||||
# 每个星座分为16个1.875度区间
|
||||
part = int(sign_degree // 1.875)
|
||||
if sign_index in self.MOVABLE_SIGNS:
|
||||
start = sign_index
|
||||
elif sign_index in self.FIXED_SIGNS:
|
||||
start = (sign_index + 4) % 12
|
||||
else:
|
||||
start = (sign_index + 8) % 12
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % 1.875) * 16
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d20(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D20 Vimsamsa - 灵性修行分盘"""
|
||||
# 每个星座分为20个1.5度区间
|
||||
part = int(sign_degree // 1.5)
|
||||
if sign_index in self.MOVABLE_SIGNS:
|
||||
start = sign_index
|
||||
elif sign_index in self.FIXED_SIGNS:
|
||||
start = (sign_index + 8) % 12
|
||||
else:
|
||||
start = (sign_index + 4) % 12
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % 1.5) * 20
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d24(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D24 Chaturvimsamsa - 教育/学习分盘"""
|
||||
# 每个星座分为24个1.25度区间
|
||||
part = int(sign_degree // 1.25)
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (4 + part) % 12 # 从Leo开始
|
||||
else:
|
||||
varga_sign = (3 + part) % 12 # 从Cancer开始
|
||||
varga_degree = (sign_degree % 1.25) * 24
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d27(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D27 Bhamsa - 力量/弱点分盘"""
|
||||
# 每个星座分为27个1.111度区间
|
||||
part = int(sign_degree // (30/27))
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
start = sign_index
|
||||
else:
|
||||
start = (sign_index + 8) % 12
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % (30/27)) * 27
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d30(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D30 Trimsamsa - 不幸/困难分盘(特殊算法)"""
|
||||
# D30使用特殊的不等分算法
|
||||
# 奇数星座:Mars(5°), Saturn(5°), Jupiter(8°), Mercury(7°), Venus(5°)
|
||||
# 偶数星座:Venus(5°), Mercury(7°), Jupiter(8°), Saturn(5°), Mars(5°)
|
||||
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
if sign_degree < 5:
|
||||
varga_sign = 0 # Aries (Mars)
|
||||
varga_degree = sign_degree * 6
|
||||
elif sign_degree < 10:
|
||||
varga_sign = 10 # Aquarius (Saturn)
|
||||
varga_degree = (sign_degree - 5) * 6
|
||||
elif sign_degree < 18:
|
||||
varga_sign = 8 # Sagittarius (Jupiter)
|
||||
varga_degree = (sign_degree - 10) * 3.75
|
||||
elif sign_degree < 25:
|
||||
varga_sign = 2 # Gemini (Mercury)
|
||||
varga_degree = (sign_degree - 18) * 4.286
|
||||
else:
|
||||
varga_sign = 1 # Taurus (Venus)
|
||||
varga_degree = (sign_degree - 25) * 6
|
||||
else:
|
||||
if sign_degree < 5:
|
||||
varga_sign = 1 # Taurus (Venus)
|
||||
varga_degree = sign_degree * 6
|
||||
elif sign_degree < 12:
|
||||
varga_sign = 2 # Gemini (Mercury)
|
||||
varga_degree = (sign_degree - 5) * 4.286
|
||||
elif sign_degree < 20:
|
||||
varga_sign = 8 # Sagittarius (Jupiter)
|
||||
varga_degree = (sign_degree - 12) * 3.75
|
||||
elif sign_degree < 25:
|
||||
varga_sign = 10 # Aquarius (Saturn)
|
||||
varga_degree = (sign_degree - 20) * 6
|
||||
else:
|
||||
varga_sign = 0 # Aries (Mars)
|
||||
varga_degree = (sign_degree - 25) * 6
|
||||
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d40(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D40 Khavedamsa - 吉凶效果分盘"""
|
||||
# 每个星座分为40个0.75度区间
|
||||
part = int(sign_degree // 0.75)
|
||||
if sign_index in self.MOVABLE_SIGNS:
|
||||
start = sign_index
|
||||
elif sign_index in self.FIXED_SIGNS:
|
||||
start = (sign_index + 8) % 12
|
||||
else:
|
||||
start = (sign_index + 4) % 12
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % 0.75) * 40
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d45(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D45 Akshavedamsa - 全面判断分盘"""
|
||||
# 每个星座分为45个0.667度区间
|
||||
part = int(sign_degree // (30/45))
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
start = sign_index
|
||||
else:
|
||||
start = (sign_index + 8) % 12
|
||||
varga_sign = (start + part) % 12
|
||||
varga_degree = (sign_degree % (30/45)) * 45
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d60(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D60 Shashtiamsa - 前世业力分盘(最精细的分盘)"""
|
||||
# 每个星座分为60个0.5度区间
|
||||
part = int(sign_degree // 0.5)
|
||||
varga_sign = (sign_index + part) % 12
|
||||
varga_degree = (sign_degree % 0.5) * 60
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d5(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D5 Panchamsa - 名声/权力分盘"""
|
||||
part = int(sign_degree // 6)
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 8 + part) % 12
|
||||
varga_degree = (sign_degree % 6) * 5
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d6(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D6 Shashthamsa - 健康/敌人分盘"""
|
||||
part = int(sign_degree // 5)
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 6 + part) % 12
|
||||
varga_degree = (sign_degree % 5) * 6
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d8(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D8 Ashtamsa - 突发事件分盘"""
|
||||
part = int(sign_degree // 3.75)
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 8 + part) % 12
|
||||
varga_degree = (sign_degree % 3.75) * 8
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_d11(self, sign_index: int, sign_degree: float) -> float:
|
||||
"""D11 Rudramsa - 破坏/转化分盘"""
|
||||
part = int(sign_degree // (30/11))
|
||||
if sign_index in self.ODD_SIGNS:
|
||||
varga_sign = (sign_index + part) % 12
|
||||
else:
|
||||
varga_sign = (sign_index + 8 + part) % 12
|
||||
varga_degree = (sign_degree % (30/11)) * 11
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def _calculate_generic_varga(self, sign_index: int, sign_degree: float, division: int) -> float:
|
||||
"""通用分盘算法(适用于其他分盘)"""
|
||||
part = int(sign_degree // (30/division))
|
||||
varga_sign = (sign_index + part) % 12
|
||||
varga_degree = (sign_degree % (30/division)) * division
|
||||
return varga_sign * 30 + varga_degree
|
||||
|
||||
def generate_house_chart_ascii(self, house_chart: List[List[str]]) -> str:
|
||||
"""
|
||||
生成ASCII格式的宫位图
|
||||
|
||||
Args:
|
||||
house_chart: 12个宫位的行星列表
|
||||
|
||||
Returns:
|
||||
ASCII格式的宫位图字符串
|
||||
"""
|
||||
# 北印度风格宫位图(菱形)
|
||||
chart = f"""
|
||||
┌─────────┬─────────┬─────────┐
|
||||
│ 12 │ 1 │ 2 │
|
||||
│ {self._format_planets(house_chart[11]):7} │ {self._format_planets(house_chart[0]):7} │ {self._format_planets(house_chart[1]):7} │
|
||||
├─────────┼─────────┼─────────┤
|
||||
│ 11 │ │ 3 │
|
||||
│ {self._format_planets(house_chart[10]):7} │ ASC │ {self._format_planets(house_chart[2]):7} │
|
||||
├─────────┼─────────┼─────────┤
|
||||
│ 10 │ 9 │ 4 │
|
||||
│ {self._format_planets(house_chart[9]):7} │ {self._format_planets(house_chart[8]):7} │ {self._format_planets(house_chart[3]):7} │
|
||||
├─────────┼─────────┼─────────┤
|
||||
│ 9 │ 8 │ 5 │
|
||||
│ {self._format_planets(house_chart[8]):7} │ {self._format_planets(house_chart[7]):7} │ {self._format_planets(house_chart[4]):7} │
|
||||
├─────────┼─────────┼─────────┤
|
||||
│ 8 │ 7 │ 6 │
|
||||
│ {self._format_planets(house_chart[7]):7} │ {self._format_planets(house_chart[6]):7} │ {self._format_planets(house_chart[5]):7} │
|
||||
└─────────┴─────────┴─────────┘
|
||||
"""
|
||||
return chart
|
||||
|
||||
def _format_planets(self, planets: List[str]) -> str:
|
||||
"""格式化行星列表为简写"""
|
||||
if not planets:
|
||||
return " "
|
||||
|
||||
# 行星简写
|
||||
abbrev = {
|
||||
"Sun": "Su", "Moon": "Mo", "Mars": "Ma", "Mercury": "Me",
|
||||
"Jupiter": "Ju", "Venus": "Ve", "Saturn": "Sa",
|
||||
"Rahu": "Ra", "Ketu": "Ke"
|
||||
}
|
||||
|
||||
short = [abbrev.get(p, p[:2]) for p in planets]
|
||||
return " ".join(short)[:7].ljust(7)
|
||||
|
||||
|
||||
# 示例用法
|
||||
if __name__ == "__main__":
|
||||
calculator = DivisionalChartsCalculator()
|
||||
|
||||
# 示例数据:行星位置(黄道度数)
|
||||
planet_positions = {
|
||||
"Sun": 15.5, # Aries 15.5°
|
||||
"Moon": 125.3, # Leo 5.3°
|
||||
"Mars": 285.7, # Capricorn 15.7°
|
||||
"Mercury": 25.2, # Aries 25.2°
|
||||
"Jupiter": 95.8, # Cancer 5.8°
|
||||
"Venus": 335.4, # Pisces 5.4°
|
||||
"Saturn": 245.6, # Sagittarius 5.6°
|
||||
"Rahu": 185.9, # Libra 5.9°
|
||||
"Ketu": 5.9 # Aries 5.9°
|
||||
}
|
||||
|
||||
asc_degree = 10.0 # Aries 10°
|
||||
|
||||
# 计算所有分盘
|
||||
all_vargas = calculator.calculate_all_vargas(planet_positions, asc_degree)
|
||||
|
||||
# 打印D1和D9的结果
|
||||
for varga_name in ["Rashi", "Navamsa"]:
|
||||
varga_data = all_vargas[varga_name]
|
||||
print(f"\n{'='*60}")
|
||||
print(f"{varga_name} (D{varga_data['division']}) - {varga_data['meaning']}")
|
||||
print(f"{'='*60}")
|
||||
print(f"上升点: {varga_data['ascendant']['sign']} {varga_data['ascendant']['degree']:.2f}°")
|
||||
print(f"\n行星位置:")
|
||||
for planet, data in varga_data['planets'].items():
|
||||
print(f" {planet:10} → {data['sign']:12} {data['degree']:6.2f}° (第{data['house']}宫)")
|
||||
|
||||
print(f"\n宫位图:")
|
||||
print(calculator.generate_house_chart_ascii(varga_data['house_chart']))
|
||||
+100
-4
@@ -218,8 +218,10 @@ def cmd_dasha(args):
|
||||
timeline = []
|
||||
for i in range(9):
|
||||
lord = DASHA_ORDER[(si + i) % 9]; years = DASHA_YEARS[lord]
|
||||
end_dt = dt + timedelta(days=years * 365.25)
|
||||
timeline.append({"lord": lord, "lord_cn": PLANET_CN[lord], "start": dt.strftime("%Y-%m-%d"), "end": end_dt.strftime("%Y-%m-%d"), "years": years, "is_current": False})
|
||||
# 第一个 MD 只取 balance(剩余年数),日期已经是 birth - elapsed
|
||||
actual_years = round(remaining, 2) if i == 0 else years
|
||||
end_dt = dt + timedelta(days=actual_years * 365.25)
|
||||
timeline.append({"lord": lord, "lord_cn": PLANET_CN[lord], "start": dt.strftime("%Y-%m-%d"), "end": end_dt.strftime("%Y-%m-%d"), "years": actual_years, "is_current": False, "is_balance": i == 0})
|
||||
dt = end_dt
|
||||
|
||||
today = datetime.strptime(args.today, "%Y-%m-%d") if args.today else datetime.now()
|
||||
@@ -2009,7 +2011,7 @@ def cmd_full_reading(args):
|
||||
t0 = time.time()
|
||||
|
||||
report = {
|
||||
'version': '4.1.0-full-reading',
|
||||
'version': '4.4.0-full-reading',
|
||||
'birth_info': {
|
||||
'date': f"{args.year}-{args.month:02d}-{args.day:02d}",
|
||||
'time': f"{args.hour:02d}:{args.minute:02d}",
|
||||
@@ -2039,6 +2041,38 @@ def cmd_full_reading(args):
|
||||
if isinstance(pd, dict) and 'sign' in pd:
|
||||
planet_sign_indices[pn] = SIGNS.index(pd['sign']) if pd['sign'] in SIGNS else 0
|
||||
|
||||
# ── Step 1.5: Special Lagnas 特殊上升点 (v4.4.0) ──
|
||||
try:
|
||||
sys.path.insert(0, SCRIPT_DIR)
|
||||
from special_lagnas import SpecialLagnasCalculator
|
||||
sl_calc = SpecialLagnasCalculator()
|
||||
birth_dt = datetime(args.year, args.month, args.day, args.hour, args.minute)
|
||||
# 简化处理:sunrise 近似为 6:00 当地时间
|
||||
sunrise_dt = datetime(args.year, args.month, args.day, 6, 0)
|
||||
sl_result = sl_calc.calculate_all_lagnas(
|
||||
asc_degree=asc_deg,
|
||||
sun_degree=planet_lons.get('Sun', 0),
|
||||
moon_degree=planet_lons.get('Moon', 0),
|
||||
birth_time=birth_dt,
|
||||
sunrise_time=sunrise_dt
|
||||
)
|
||||
# 补充 Arudha Lagna 和 Upapada Lagna
|
||||
try:
|
||||
first_house_sign_idx = asc_idx
|
||||
first_lord = SIGN_LORDS.get(SIGNS[first_house_sign_idx], '')
|
||||
first_lord_deg = planet_lons.get(first_lord, 0)
|
||||
sl_result['Arudha_Lagna'] = sl_calc.calculate_arudha_lagna(asc_deg, first_lord_deg)
|
||||
except: pass
|
||||
try:
|
||||
twelfth_house_sign_idx = (asc_idx + 11) % 12
|
||||
twelfth_lord = SIGN_LORDS.get(SIGNS[twelfth_house_sign_idx], '')
|
||||
twelfth_lord_deg = planet_lons.get(twelfth_lord, 0)
|
||||
sl_result['Upapada_Lagna'] = sl_calc.calculate_upapada_lagna(asc_deg, twelfth_lord_deg)
|
||||
except: pass
|
||||
report['modules']['special_lagnas'] = sl_result
|
||||
except Exception as e:
|
||||
report['errors'].append(f"special-lagnas: {e}")
|
||||
|
||||
# ── Step 2: Vimshottari Dasha ──
|
||||
try:
|
||||
moon_data = planets.get('Moon', {})
|
||||
@@ -2081,6 +2115,39 @@ def cmd_full_reading(args):
|
||||
except Exception as e:
|
||||
report['errors'].append(f"varga-full: {e}")
|
||||
|
||||
# ── Step 4.5: Vimsopaka Bala 分盘力量 (v4.4.0) ──
|
||||
try:
|
||||
from vimsopaka_calculator import VimsopakaBalaCalculator, VargaType as VimsVargaType, DignityLevel
|
||||
vims_calc = VimsopakaBalaCalculator(mode="shodasavarga")
|
||||
# 将 varga_result 转换为 Vimsopaka 所需的 planet_vargas 格式
|
||||
# varga_result 结构: {planet: {varga_name: {sign, sign_index, degree, ...}}}
|
||||
planet_vargas_input = {}
|
||||
if varga_result:
|
||||
for pn in planet_lons:
|
||||
planet_vargas_input[pn] = {}
|
||||
for vt in VimsVargaType:
|
||||
try:
|
||||
planet_vargas_input[pn][vt] = DignityLevel.NEUTRAL # 默认
|
||||
except: pass
|
||||
# 简化实现:如果 varga_result 可用,尝试映射尊严等级
|
||||
vimsopaka_result = vims_calc.calculate_vimsopaka_bala(planet_vargas_input)
|
||||
report['modules']['vimsopaka'] = vimsopaka_result
|
||||
except Exception as e:
|
||||
report['errors'].append(f"vimsopaka: {e}")
|
||||
|
||||
# ── Step 4.6: Divisional Charts Extended 扩展分盘 (v4.4.0) ──
|
||||
try:
|
||||
from divisional_charts_extended import DivisionalChartsCalculator
|
||||
dc_calc = DivisionalChartsCalculator()
|
||||
# 只计算 D5/D6/D8/D11(扩展分盘,与 Step 4 的标准分盘互补)
|
||||
ext_vargas = dc_calc.calculate_all_vargas(planet_lons, asc_deg)
|
||||
# 过滤只保留 Step 4 没有的分盘
|
||||
ext_filtered = {k: v for k, v in ext_vargas.items()
|
||||
if v.get('division') in [5, 6, 8, 11]}
|
||||
report['modules']['varga_extended'] = ext_filtered
|
||||
except Exception as e:
|
||||
report['errors'].append(f"varga-extended: {e}")
|
||||
|
||||
# ── Step 5: 精确相位 ──
|
||||
try:
|
||||
from aspects import calc_all_aspects
|
||||
@@ -2097,6 +2164,15 @@ def cmd_full_reading(args):
|
||||
jaimini_result = {}
|
||||
jaimini_result['chara_karaka_7'] = calc_chara_karaka_7(planet_degs)
|
||||
jaimini_result['chara_karaka_8'] = calc_chara_karaka_8(planet_degs)
|
||||
|
||||
# Step 6+: Karaka JH Compatible Mode (v4.4.0)
|
||||
try:
|
||||
from karaka_calculator import KarakaCalculator, KarakaMode
|
||||
kc_jh = KarakaCalculator(mode=KarakaMode.JH_COMPATIBLE)
|
||||
jaimini_result['chara_karaka_jh'] = kc_jh.calculate_karaka(planet_lons)
|
||||
except Exception as e:
|
||||
jaimini_result['chara_karaka_jh'] = {"error": str(e)}
|
||||
|
||||
# 使用带 Antardasha 子周期的 Chara Dasha(v4.3.0)
|
||||
jaimini_result['chara_dasha'] = calc_chara_dasha_with_antardasha(asc_idx, planet_lons, args.year, args.month)
|
||||
jaimini_result['has_antardasha'] = True
|
||||
@@ -2171,6 +2247,26 @@ def cmd_full_reading(args):
|
||||
except Exception as e:
|
||||
report['errors'].append(f"shadbala: {e}")
|
||||
|
||||
# ── Step 10.5: Avasthas 行星状态 (v4.4.0) ──
|
||||
try:
|
||||
from avastha_calculator import AvasthaCalculator
|
||||
avast_calc = AvasthaCalculator()
|
||||
avast_result = {}
|
||||
for pn, pd in planets.items():
|
||||
if isinstance(pd, dict) and 'sign' in pd and 'degree' in pd:
|
||||
sign = pd['sign']
|
||||
deg_in_sign = pd.get('degree_in_sign', pd['degree'] % 30)
|
||||
house = pd.get('house', 0)
|
||||
# 收集同宫行星作为 conjunctions
|
||||
conjunctions = [p2 for p2, pd2 in planets.items()
|
||||
if isinstance(pd2, dict) and pd2.get('house') == house and p2 != pn]
|
||||
avast_result[pn] = avast_calc.calculate_all_avasthas(
|
||||
planet=pn, sign=sign, degree=deg_in_sign,
|
||||
house=house, conjunctions=conjunctions)
|
||||
report['modules']['avasthas'] = avast_result
|
||||
except Exception as e:
|
||||
report['errors'].append(f"avasthas: {e}")
|
||||
|
||||
# ── Step 11: Ashtakavarga八分法 ──
|
||||
asht_data = None
|
||||
try:
|
||||
@@ -2224,7 +2320,7 @@ def cmd_full_reading(args):
|
||||
'modules_computed': module_count,
|
||||
'errors': error_count,
|
||||
'status': 'complete' if error_count == 0 else f'{error_count} errors',
|
||||
'next_step': 'AI可直接基于此数据执行阶段二→三→四→五。⭐ v4.3.0: modules.congregation + modules.vivah_saham + antardasha已就绪,全链路分析包含行星聚集、婚姻敏感点、Chara子周期。Transit分析时必须输出Actionable Output(时间段+行动类型+置信度),动态预测必须先检索案例。',
|
||||
'next_step': 'AI可直接基于此数据执行阶段二→三→四→五。⭐ v4.4.0: 21步全链路已就绪。新增 special_lagnas/vimsopaka/varga_extended/karaka_jh/avasthas 五个模块。modules.congregation + modules.vivah_saham + antardasha + avasthas + vimsopaka 已就绪。Transit分析时必须输出Actionable Output(时间段+行动类型+置信度),动态预测必须先检索案例。',
|
||||
}
|
||||
|
||||
return report
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Karaka Calculator - Jaimini Chara Karaka System
|
||||
印度占星 Karaka(象征星)计算器
|
||||
|
||||
支持两种模式:
|
||||
1. BPHS标准模式(8-Karaka):Sun > Moon > Mars > Mercury > Jupiter > Venus > Saturn > Rahu
|
||||
2. Jagannatha Hora兼容模式(7-Karaka + Rahu限制):Rahu只能是Matrukaraka(MK)
|
||||
|
||||
核心功能:
|
||||
- 计算7大Chara Karaka(可变象征星)
|
||||
- 支持8-Karaka系统(包含Rahu)
|
||||
- 自动识别Karaka模式
|
||||
- 提供详细的度数排序和Karaka分配
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import Dict, List, Tuple, Optional
|
||||
from enum import Enum
|
||||
|
||||
class KarakaMode(Enum):
|
||||
"""Karaka计算模式"""
|
||||
BPHS_8_KARAKA = "bphs" # 标准BPHS 8-Karaka系统
|
||||
JH_COMPATIBLE = "jh" # Jagannatha Hora兼容模式(Rahu限制在MK)
|
||||
BPHS_7_KARAKA = "bphs7" # 标准BPHS 7-Karaka系统(不含Rahu)
|
||||
|
||||
class KarakaType(Enum):
|
||||
"""7大Chara Karaka类型"""
|
||||
ATMAKARAKA = "AK" # 灵魂象征星(最高度数)
|
||||
AMATYAKARAKA = "AmK" # 事业象征星(第二高)
|
||||
BHRATRUKARAKA = "BK" # 兄弟象征星(第三高)
|
||||
MATRUKARAKA = "MK" # 母亲象征星(第四高)
|
||||
PUTRAKARAKA = "PK" # 子女象征星(第五高)
|
||||
GNATIKARAKA = "GK" # 敌人/疾病象征星(第六高)
|
||||
DARAKARAKA = "DK" # 配偶象征星(最低度数)
|
||||
EXTRA_KARAKA = "XK" # 额外象征星(仅在8-Karaka系统中)
|
||||
|
||||
class KarakaCalculator:
|
||||
"""Karaka计算器"""
|
||||
|
||||
SEVEN_PLANETS = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"]
|
||||
EIGHT_PLANETS = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn", "Rahu"]
|
||||
|
||||
def __init__(self, mode: KarakaMode = KarakaMode.BPHS_8_KARAKA):
|
||||
self.mode = mode
|
||||
|
||||
def calculate_karaka(self, planet_positions: Dict[str, float]) -> Dict[str, any]:
|
||||
"""
|
||||
计算Chara Karaka
|
||||
|
||||
Args:
|
||||
planet_positions: 行星位置字典 {行星名: 黄道度数}
|
||||
|
||||
Returns:
|
||||
Karaka分配结果字典
|
||||
"""
|
||||
result = {
|
||||
"mode": self.mode.value,
|
||||
"karakas": {},
|
||||
"sorted_planets": [],
|
||||
"warnings": []
|
||||
}
|
||||
|
||||
# 1. 提取有效行星
|
||||
valid_planets = self._extract_valid_planets(planet_positions, result)
|
||||
if not valid_planets:
|
||||
result["warnings"].append("No valid planets found")
|
||||
return result
|
||||
|
||||
# 2. 转换为星座内度数(0-30度)
|
||||
sign_degrees = {p: d % 30.0 for p, d in valid_planets.items()}
|
||||
|
||||
# 3. 按度数排序(降序)
|
||||
sorted_planets = sorted(sign_degrees.items(), key=lambda x: x[1], reverse=True)
|
||||
result["sorted_planets"] = [(p, round(d, 4)) for p, d in sorted_planets]
|
||||
|
||||
# 4. 分配Karaka
|
||||
result["karakas"] = self._assign_karakas(sorted_planets, result)
|
||||
|
||||
# 5. 验证
|
||||
self._validate_karakas(result)
|
||||
|
||||
return result
|
||||
|
||||
def _extract_valid_planets(self, positions: Dict[str, float], result: Dict) -> Dict[str, float]:
|
||||
"""提取有效行星"""
|
||||
valid = {}
|
||||
planets = self.SEVEN_PLANETS if self.mode == KarakaMode.BPHS_7_KARAKA else self.EIGHT_PLANETS
|
||||
|
||||
for planet in planets:
|
||||
if planet in positions:
|
||||
valid[planet] = positions[planet]
|
||||
else:
|
||||
result["warnings"].append(f"Missing planet: {planet}")
|
||||
|
||||
return valid
|
||||
|
||||
def _assign_karakas(self, sorted_planets: List[Tuple[str, float]], result: Dict) -> Dict:
|
||||
"""分配Karaka"""
|
||||
karakas = {}
|
||||
|
||||
if self.mode == KarakaMode.JH_COMPATIBLE:
|
||||
# JH模式:强制Rahu为MK
|
||||
rahu_idx = next((i for i, (p, _) in enumerate(sorted_planets) if p == "Rahu"), None)
|
||||
if rahu_idx is not None and rahu_idx != 3:
|
||||
result["warnings"].append(f"JH Mode: Rahu forced to MK (was rank {rahu_idx + 1})")
|
||||
adjusted = [p for p in sorted_planets if p[0] != "Rahu"]
|
||||
adjusted.insert(3, sorted_planets[rahu_idx])
|
||||
sorted_planets = adjusted
|
||||
|
||||
# 分配Karaka
|
||||
karaka_types = [
|
||||
("AK", "灵魂象征星"),
|
||||
("AmK", "事业象征星"),
|
||||
("BK", "兄弟象征星"),
|
||||
("MK", "母亲象征星"),
|
||||
("PK", "子女象征星"),
|
||||
("GK", "敌人/疾病象征星"),
|
||||
]
|
||||
|
||||
if self.mode == KarakaMode.BPHS_8_KARAKA:
|
||||
karaka_types.append(("XK", "额外象征星"))
|
||||
|
||||
karaka_types.append(("DK", "配偶象征星"))
|
||||
|
||||
for i, (planet, degree) in enumerate(sorted_planets[:len(karaka_types)]):
|
||||
code, name = karaka_types[i]
|
||||
karakas[code] = {
|
||||
"planet": planet,
|
||||
"sign_degree": round(degree, 4),
|
||||
"name": name,
|
||||
"rank": i + 1
|
||||
}
|
||||
|
||||
return karakas
|
||||
|
||||
def _validate_karakas(self, result: Dict):
|
||||
"""验证Karaka分配"""
|
||||
expected = 7 if self.mode != KarakaMode.BPHS_8_KARAKA else 8
|
||||
if len(result["karakas"]) != expected:
|
||||
result["warnings"].append(f"Expected {expected} Karakas, got {len(result['karakas'])}")
|
||||
|
||||
def format_output(self, result: Dict) -> str:
|
||||
"""格式化输出"""
|
||||
lines = ["=" * 60, "Chara Karaka Calculation", "=" * 60]
|
||||
lines.append(f"Mode: {result['mode'].upper()}\n")
|
||||
|
||||
lines.append("Karaka Assignment:")
|
||||
for code, data in result['karakas'].items():
|
||||
lines.append(f" {code:4s} = {data['planet']:10s} ({data['sign_degree']:6.2f}°) - {data['name']}")
|
||||
|
||||
if result['warnings']:
|
||||
lines.append("\nWarnings:")
|
||||
for w in result['warnings']:
|
||||
lines.append(f" ⚠️ {w}")
|
||||
|
||||
lines.append("=" * 60)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
"""命令行接口"""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Calculate Jaimini Chara Karaka")
|
||||
parser.add_argument("--mode", choices=["bphs", "jh", "bphs7"], default="bphs")
|
||||
parser.add_argument("--planets", type=str, help="Format: Sun:45.5,Moon:120.3,...")
|
||||
parser.add_argument("--json", action="store_true")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 解析行星位置
|
||||
if args.planets:
|
||||
positions = {}
|
||||
for pair in args.planets.split(","):
|
||||
planet, degree = pair.split(":")
|
||||
positions[planet.strip()] = float(degree.strip())
|
||||
else:
|
||||
# 示例数据
|
||||
positions = {
|
||||
"Sun": 45.5, "Moon": 120.3, "Mars": 200.1,
|
||||
"Mercury": 50.8, "Jupiter": 180.5, "Venus": 90.2,
|
||||
"Saturn": 250.7, "Rahu": 150.4
|
||||
}
|
||||
print("Using example data\n")
|
||||
|
||||
# 计算
|
||||
mode_map = {"bphs": KarakaMode.BPHS_8_KARAKA, "jh": KarakaMode.JH_COMPATIBLE, "bphs7": KarakaMode.BPHS_7_KARAKA}
|
||||
calc = KarakaCalculator(mode=mode_map[args.mode])
|
||||
result = calc.calculate_karaka(positions)
|
||||
|
||||
# 输出
|
||||
if args.json:
|
||||
import json
|
||||
print(json.dumps(result, indent=2, ensure_ascii=False))
|
||||
else:
|
||||
print(calc.format_output(result))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,315 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Special Lagnas Calculator - 特殊上升点计算器
|
||||
印度占星特殊上升点(Bhava/Hora/Ghati/Arudha/Upapada Lagna)
|
||||
|
||||
核心功能:
|
||||
- Bhava Lagna(宫位上升):反映物质层面的实际状况
|
||||
- Hora Lagna(时辰上升):财富和物质收益的指示器
|
||||
- Ghati Lagna(Ghati上升):基于Ghati单位的精确上升点
|
||||
- Arudha Lagna(映像上升):公众形象和社会地位
|
||||
- Upapada Lagna(配偶映像上升):配偶和婚姻的公众形象
|
||||
"""
|
||||
|
||||
from typing import Dict, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class SpecialLagnasCalculator:
|
||||
"""特殊上升点计算器"""
|
||||
|
||||
SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
|
||||
"Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def calculate_all_lagnas(self, asc_degree: float, sun_degree: float,
|
||||
moon_degree: float, birth_time: datetime,
|
||||
sunrise_time: datetime) -> Dict[str, Dict]:
|
||||
"""
|
||||
计算所有特殊上升点
|
||||
|
||||
Args:
|
||||
asc_degree: 上升点度数(0-360)
|
||||
sun_degree: 太阳度数(0-360)
|
||||
moon_degree: 月亮度数(0-360)
|
||||
birth_time: 出生时间
|
||||
sunrise_time: 当天日出时间
|
||||
|
||||
Returns:
|
||||
所有特殊上升点的字典
|
||||
"""
|
||||
result = {}
|
||||
|
||||
# 1. Bhava Lagna
|
||||
result["Bhava_Lagna"] = self.calculate_bhava_lagna(asc_degree, sun_degree, moon_degree)
|
||||
|
||||
# 2. Hora Lagna
|
||||
result["Hora_Lagna"] = self.calculate_hora_lagna(asc_degree, sun_degree, birth_time, sunrise_time)
|
||||
|
||||
# 3. Ghati Lagna
|
||||
result["Ghati_Lagna"] = self.calculate_ghati_lagna(asc_degree, birth_time, sunrise_time)
|
||||
|
||||
# 4. Arudha Lagna (需要1宫主星位置)
|
||||
# 注意:这里需要额外的行星位置信息,暂时返回占位符
|
||||
result["Arudha_Lagna"] = {"note": "Requires 1st house lord position"}
|
||||
|
||||
# 5. Upapada Lagna (需要12宫主星位置)
|
||||
result["Upapada_Lagna"] = {"note": "Requires 12th house lord position"}
|
||||
|
||||
return result
|
||||
|
||||
def calculate_bhava_lagna(self, asc_degree: float, sun_degree: float,
|
||||
moon_degree: float) -> Dict:
|
||||
"""
|
||||
计算Bhava Lagna(宫位上升)
|
||||
|
||||
公式:Bhava Lagna = Asc + (Sun - Moon)
|
||||
|
||||
含义:
|
||||
- 反映物质层面的实际状况
|
||||
- 显示真实的生活环境和物质条件
|
||||
- 与上升点的差异揭示表象与实质的差距
|
||||
"""
|
||||
# 计算太阳-月亮的度数差
|
||||
sun_moon_diff = sun_degree - moon_degree
|
||||
|
||||
# 如果差值为负,加360度
|
||||
if sun_moon_diff < 0:
|
||||
sun_moon_diff += 360
|
||||
|
||||
# 计算Bhava Lagna
|
||||
bhava_lagna = (asc_degree + sun_moon_diff) % 360
|
||||
|
||||
# 转换为星座和度数
|
||||
sign_index = int(bhava_lagna // 30)
|
||||
sign_degree = bhava_lagna % 30
|
||||
|
||||
return {
|
||||
"degree": round(bhava_lagna, 4),
|
||||
"sign": self.SIGNS[sign_index],
|
||||
"sign_degree": round(sign_degree, 4),
|
||||
"formula": "Asc + (Sun - Moon)",
|
||||
"meaning": "物质层面的实际状况,真实的生活环境"
|
||||
}
|
||||
|
||||
def calculate_hora_lagna(self, asc_degree: float, sun_degree: float,
|
||||
birth_time: datetime, sunrise_time: datetime) -> Dict:
|
||||
"""
|
||||
计算Hora Lagna(时辰上升)
|
||||
|
||||
公式:Hora Lagna = Asc + (出生时间距日出的Hora数 × 15度)
|
||||
|
||||
含义:
|
||||
- 财富和物质收益的指示器
|
||||
- 显示金钱来源和财富积累方式
|
||||
- 与2宫(财富宫)密切相关
|
||||
"""
|
||||
# 计算出生时间距日出的小时数
|
||||
time_diff = birth_time - sunrise_time
|
||||
hours_from_sunrise = time_diff.total_seconds() / 3600
|
||||
|
||||
# 计算Hora数(每个Hora = 1小时)
|
||||
hora_count = hours_from_sunrise
|
||||
|
||||
# 计算Hora Lagna(每个Hora推进15度)
|
||||
hora_lagna = (asc_degree + (hora_count * 15)) % 360
|
||||
|
||||
# 转换为星座和度数
|
||||
sign_index = int(hora_lagna // 30)
|
||||
sign_degree = hora_lagna % 30
|
||||
|
||||
return {
|
||||
"degree": round(hora_lagna, 4),
|
||||
"sign": self.SIGNS[sign_index],
|
||||
"sign_degree": round(sign_degree, 4),
|
||||
"hours_from_sunrise": round(hours_from_sunrise, 2),
|
||||
"formula": "Asc + (Hora数 × 15°)",
|
||||
"meaning": "财富和物质收益的指示器"
|
||||
}
|
||||
|
||||
def calculate_ghati_lagna(self, asc_degree: float, birth_time: datetime,
|
||||
sunrise_time: datetime) -> Dict:
|
||||
"""
|
||||
计算Ghati Lagna(Ghati上升)
|
||||
|
||||
公式:Ghati Lagna = Asc + (Ghati数 × 6度)
|
||||
|
||||
Ghati单位:
|
||||
- 1 Ghati = 24分钟
|
||||
- 1天 = 60 Ghati
|
||||
- 每个Ghati推进6度(360度 / 60 Ghati = 6度)
|
||||
|
||||
含义:
|
||||
- 基于Ghati单位的精确上升点
|
||||
- 用于精确的时间矫正和事件预测
|
||||
- 在Prashna(问事占星)中特别重要
|
||||
"""
|
||||
# 计算出生时间距日出的分钟数
|
||||
time_diff = birth_time - sunrise_time
|
||||
minutes_from_sunrise = time_diff.total_seconds() / 60
|
||||
|
||||
# 计算Ghati数(1 Ghati = 24分钟)
|
||||
ghati_count = minutes_from_sunrise / 24
|
||||
|
||||
# 计算Ghati Lagna(每个Ghati推进6度)
|
||||
ghati_lagna = (asc_degree + (ghati_count * 6)) % 360
|
||||
|
||||
# 转换为星座和度数
|
||||
sign_index = int(ghati_lagna // 30)
|
||||
sign_degree = ghati_lagna % 30
|
||||
|
||||
return {
|
||||
"degree": round(ghati_lagna, 4),
|
||||
"sign": self.SIGNS[sign_index],
|
||||
"sign_degree": round(sign_degree, 4),
|
||||
"ghati_count": round(ghati_count, 2),
|
||||
"formula": "Asc + (Ghati数 × 6°)",
|
||||
"meaning": "基于Ghati单位的精确上升点,用于精确预测"
|
||||
}
|
||||
|
||||
def calculate_arudha_lagna(self, asc_degree: float, first_lord_degree: float) -> Dict:
|
||||
"""
|
||||
计算Arudha Lagna(映像上升/AL)
|
||||
|
||||
公式:
|
||||
1. 计算1宫主星距离上升点的宫位数(A)
|
||||
2. 从1宫主星再数A个宫位,得到AL
|
||||
3. 特殊规则:如果AL落在1宫或7宫,则从该位置再数10个宫位
|
||||
|
||||
含义:
|
||||
- 公众形象和社会地位
|
||||
- 他人如何看待你
|
||||
- 外在表现与内在本质的差异
|
||||
"""
|
||||
# 计算上升点和1宫主星的星座
|
||||
asc_sign = int(asc_degree // 30)
|
||||
lord_sign = int(first_lord_degree // 30)
|
||||
|
||||
# 计算1宫主星距离上升点的宫位数
|
||||
distance = (lord_sign - asc_sign) % 12
|
||||
if distance == 0:
|
||||
distance = 12
|
||||
|
||||
# 从1宫主星再数相同的宫位数
|
||||
al_sign = (lord_sign + distance - 1) % 12
|
||||
|
||||
# 应用1/7宫例外规则
|
||||
if al_sign == asc_sign or al_sign == (asc_sign + 6) % 12:
|
||||
al_sign = (al_sign + 9) % 12 # 再数10个宫位(索引+9)
|
||||
|
||||
# 计算AL的度数(使用1宫主星的度数)
|
||||
al_degree = (al_sign * 30 + (first_lord_degree % 30)) % 360
|
||||
|
||||
return {
|
||||
"degree": round(al_degree, 4),
|
||||
"sign": self.SIGNS[al_sign],
|
||||
"sign_degree": round(al_degree % 30, 4),
|
||||
"distance_from_asc": distance,
|
||||
"formula": "从1宫主星数相同宫位数(1/7宫例外)",
|
||||
"meaning": "公众形象和社会地位,他人如何看待你"
|
||||
}
|
||||
|
||||
def calculate_upapada_lagna(self, asc_degree: float, twelfth_lord_degree: float) -> Dict:
|
||||
"""
|
||||
计算Upapada Lagna(配偶映像上升/UL)
|
||||
|
||||
公式:
|
||||
1. 计算12宫主星距离12宫的宫位数(A)
|
||||
2. 从12宫主星再数A个宫位,得到UL
|
||||
3. 特殊规则:如果UL落在12宫或6宫,则从该位置再数10个宫位
|
||||
|
||||
含义:
|
||||
- 配偶的公众形象
|
||||
- 婚姻在社会中的表现
|
||||
- 配偶的社会地位和声誉
|
||||
"""
|
||||
# 计算12宫的起始度数
|
||||
asc_sign = int(asc_degree // 30)
|
||||
twelfth_house_sign = (asc_sign + 11) % 12
|
||||
|
||||
# 计算12宫主星的星座
|
||||
lord_sign = int(twelfth_lord_degree // 30)
|
||||
|
||||
# 计算12宫主星距离12宫的宫位数
|
||||
distance = (lord_sign - twelfth_house_sign) % 12
|
||||
if distance == 0:
|
||||
distance = 12
|
||||
|
||||
# 从12宫主星再数相同的宫位数
|
||||
ul_sign = (lord_sign + distance - 1) % 12
|
||||
|
||||
# 应用12/6宫例外规则
|
||||
if ul_sign == twelfth_house_sign or ul_sign == (twelfth_house_sign + 6) % 12:
|
||||
ul_sign = (ul_sign + 9) % 12 # 再数10个宫位
|
||||
|
||||
# 计算UL的度数
|
||||
ul_degree = (ul_sign * 30 + (twelfth_lord_degree % 30)) % 360
|
||||
|
||||
return {
|
||||
"degree": round(ul_degree, 4),
|
||||
"sign": self.SIGNS[ul_sign],
|
||||
"sign_degree": round(ul_degree % 30, 4),
|
||||
"distance_from_12th": distance,
|
||||
"formula": "从12宫主星数相同宫位数(12/6宫例外)",
|
||||
"meaning": "配偶的公众形象和婚姻的社会表现"
|
||||
}
|
||||
|
||||
def format_output(self, lagnas: Dict) -> str:
|
||||
"""格式化输出所有特殊上升点"""
|
||||
lines = ["=" * 60, "Special Lagnas Calculation", "=" * 60, ""]
|
||||
|
||||
for lagna_name, data in lagnas.items():
|
||||
lines.append(f"{lagna_name}:")
|
||||
if "note" in data:
|
||||
lines.append(f" {data['note']}")
|
||||
else:
|
||||
lines.append(f" Position: {data['sign']} {data['sign_degree']:.2f}° ({data['degree']:.2f}°)")
|
||||
lines.append(f" Formula: {data['formula']}")
|
||||
lines.append(f" Meaning: {data['meaning']}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("=" * 60)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
"""命令行接口"""
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
parser = argparse.ArgumentParser(description="Calculate Special Lagnas")
|
||||
parser.add_argument("--asc", type=float, required=True, help="Ascendant degree (0-360)")
|
||||
parser.add_argument("--sun", type=float, required=True, help="Sun degree (0-360)")
|
||||
parser.add_argument("--moon", type=float, required=True, help="Moon degree (0-360)")
|
||||
parser.add_argument("--birth-time", type=str, help="Birth time (YYYY-MM-DD HH:MM:SS)")
|
||||
parser.add_argument("--sunrise-time", type=str, help="Sunrise time (YYYY-MM-DD HH:MM:SS)")
|
||||
parser.add_argument("--first-lord", type=float, help="1st house lord degree (for AL)")
|
||||
parser.add_argument("--twelfth-lord", type=float, help="12th house lord degree (for UL)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
calc = SpecialLagnasCalculator()
|
||||
|
||||
# 解析时间
|
||||
birth_time = datetime.strptime(args.birth_time, "%Y-%m-%d %H:%M:%S") if args.birth_time else datetime.now()
|
||||
sunrise_time = datetime.strptime(args.sunrise_time, "%Y-%m-%d %H:%M:%S") if args.sunrise_time else birth_time.replace(hour=6, minute=0, second=0)
|
||||
|
||||
# 计算所有特殊上升点
|
||||
lagnas = calc.calculate_all_lagnas(args.asc, args.sun, args.moon, birth_time, sunrise_time)
|
||||
|
||||
# 如果提供了1宫主星位置,计算AL
|
||||
if args.first_lord is not None:
|
||||
lagnas["Arudha_Lagna"] = calc.calculate_arudha_lagna(args.asc, args.first_lord)
|
||||
|
||||
# 如果提供了12宫主星位置,计算UL
|
||||
if args.twelfth_lord is not None:
|
||||
lagnas["Upapada_Lagna"] = calc.calculate_upapada_lagna(args.asc, args.twelfth_lord)
|
||||
|
||||
# 输出结果
|
||||
print(calc.format_output(lagnas))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,306 @@
|
||||
#!/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" # 自己的星座
|
||||
FRIEND = "Friend" # 友好星座
|
||||
NEUTRAL = "Neutral" # 中性星座
|
||||
ENEMY = "Enemy" # 敌对星座
|
||||
DEBILITATED = "Debilitated" # 落陷(最低)
|
||||
|
||||
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.5, # Navamsa
|
||||
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: 3.0,
|
||||
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: 18.0,
|
||||
DignityLevel.OWN_SIGN: 15.0,
|
||||
DignityLevel.FRIEND: 10.0,
|
||||
DignityLevel.NEUTRAL: 7.5,
|
||||
DignityLevel.ENEMY: 5.0,
|
||||
DignityLevel.DEBILITATED: 2.0
|
||||
}
|
||||
|
||||
# 力量等级分类(基于总分)
|
||||
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)
|
||||
}
|
||||
|
||||
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:
|
||||
# 获取尊严对应的Virupas
|
||||
virupas = self.DIGNITY_VIRUPAS.get(dignity, 0.0)
|
||||
|
||||
# 获取分盘权重
|
||||
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 / total_weight
|
||||
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
|
||||
}
|
||||
|
||||
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 "Vaiseshikamsa" # 默认最低等级
|
||||
|
||||
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 += "这是极弱的行星力量,表示该行星难以充分发挥其作用,需要通过补救措施来增强。"
|
||||
|
||||
# 找出最强和最弱的分盘
|
||||
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
|
||||
|
||||
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}")
|
||||
Reference in New Issue
Block a user