a4f8620a71
## 新增模块 (16个) ### P0 精度修复 - ashtakavarga: calc_prastara_av() + calc_sodhita_av() - kakshya.py: Kakshya评分系统 (8区间×3.75°) - shadbala.py: Sputa Drishti + Yuddha Bala ### P1 核心升级 - bhava_bala.py: 宫位三元力量 (jyotishganit MIT) - pancha_mahapurusha.py: PMC完整检测含4层失效条件 - sade_sati.py: Sade Sati+Kantaka Shani - sudarshana_chakra.py: 三参考点盘+收敛分析 - tajika.py: Sahams 7→36 + Tajika Yogas 10种 - birth_time_rectifier.py: 生时矫正 ### P2 覆盖扩展 - kp_system.py: KP Sublord+ABCD Significator (diliprk/VedicAstro MIT) - synastry.py: 16因子合盘36分制 (dashaflow MIT) - muhurtha_election.py: 6活动选举 (dashaflow MIT) - career_analysis.py: 结构化事业引擎 - relationship_analysis.py: 结构化感情引擎 - conditional_dashas.py: Dwisaptati+Shattrimsa+Dwadashottari - divisional_charts_extended: D81/D108/D144 - remedies.py: 5类补救系统 ## 修改文件 jaimini/dasha_calculator/shadbala/SKILL.md/COVERAGE_AUDIT等12个 ## 开源复用: 4个MIT项目
232 lines
7.5 KiB
Python
232 lines
7.5 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Muhurtha(择时占星)完整模块 v1.0
|
||
基于 dashaflow (MIT License) muhurtha.py 核心算法适配
|
||
|
||
支持6类活动的吉祥择时:
|
||
- marriage 婚姻
|
||
- travel 出行
|
||
- business 商业
|
||
- education 学业
|
||
- house_entry 入宅
|
||
- medical 医疗
|
||
|
||
包含:Panchanga Suddhi五清 + 活动专项规则 + Dosha检测 + 评分
|
||
"""
|
||
|
||
from typing import Dict, List, Optional
|
||
|
||
# =============================================================================
|
||
# 数据表(来自 dashaflow MIT License)
|
||
# =============================================================================
|
||
|
||
# 不吉Panchang Yoga(0-indexed)
|
||
BAD_YOGAS = {0, 5, 8, 9, 12, 14, 16, 18, 26}
|
||
|
||
# 普遍避开的日子
|
||
BAD_TITHIS = {4, 6, 8, 12, 14, 30}
|
||
|
||
# 普遍避开的星宿
|
||
BAD_NAKSHATRAS = {"Bharani", "Krittika"}
|
||
|
||
# 婚姻规则
|
||
MARRIAGE_RULES = {
|
||
"good_nakshatras": {"Rohini", "Mrigashira", "Magha", "Uttara Phalguni", "Hasta",
|
||
"Swati", "Anuradha", "Moola", "Uttara Ashadha", "Uttara Bhadrapada", "Revati"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_lagnas": {"Taurus", "Gemini", "Cancer", "Virgo", "Libra", "Sagittarius"},
|
||
}
|
||
|
||
# 出行规则
|
||
TRAVEL_RULES = {
|
||
"good_nakshatras": {"Ashwini", "Mrigashira", "Punarvasu", "Pushya", "Hasta",
|
||
"Anuradha", "Shravana", "Dhanishta", "Revati"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_lagnas": {"Aries", "Taurus", "Cancer", "Leo", "Libra", "Sagittarius"},
|
||
}
|
||
|
||
# 商业规则
|
||
BUSINESS_RULES = {
|
||
"good_nakshatras": {"Ashwini", "Rohini", "Punarvasu", "Pushya", "Uttara Phalguni",
|
||
"Hasta", "Chitra", "Swati", "Anuradha", "Shravana", "Dhanishta", "Revati"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_weekdays": {"Monday", "Wednesday", "Thursday", "Friday"},
|
||
"good_moon_signs": {"Taurus", "Cancer", "Virgo", "Libra", "Sagittarius", "Pisces"},
|
||
}
|
||
|
||
# 学业规则
|
||
EDUCATION_RULES = {
|
||
"good_nakshatras": {"Ashwini", "Punarvasu", "Pushya", "Hasta", "Chitra",
|
||
"Swati", "Shravana", "Dhanishta", "Shatabhisha", "Revati"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_lagnas": {"Gemini", "Virgo", "Sagittarius", "Pisces"},
|
||
}
|
||
|
||
# 入宅规则
|
||
HOUSE_ENTRY_RULES = {
|
||
"good_nakshatras": {"Rohini", "Uttara Phalguni", "Uttara Ashadha", "Uttara Bhadrapada",
|
||
"Shravana", "Dhanishta", "Revati", "Ashwini", "Mrigashira"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_weekdays": {"Monday", "Wednesday", "Thursday", "Friday"},
|
||
}
|
||
|
||
# 医疗规则
|
||
MEDICAL_RULES = {
|
||
"good_nakshatras": {"Ashwini", "Rohini", "Mrigashira", "Pushya", "Hasta",
|
||
"Chitra", "Swati", "Anuradha", "Shravana", "Revati"},
|
||
"good_tithis": {2, 3, 5, 7, 10, 11, 13},
|
||
"good_weekdays": {"Saturday", "Monday"},
|
||
}
|
||
|
||
ACTIVITY_RULES = {
|
||
"marriage": MARRIAGE_RULES,
|
||
"travel": TRAVEL_RULES,
|
||
"business": BUSINESS_RULES,
|
||
"education": EDUCATION_RULES,
|
||
"house_entry": HOUSE_ENTRY_RULES,
|
||
"medical": MEDICAL_RULES,
|
||
}
|
||
|
||
|
||
def check_panchanga_suddhi(tithi_num: int, nakshatra_name: str, yoga_index: int) -> List[str]:
|
||
"""检查Panchanga五清(Tithi/Nakshatra/Yoga纯度)"""
|
||
issues = []
|
||
if tithi_num in BAD_TITHIS:
|
||
issues.append(f"不吉日: Tithi #{tithi_num}")
|
||
if nakshatra_name in BAD_NAKSHATRAS:
|
||
issues.append(f"不吉星宿: {nakshatra_name}")
|
||
if yoga_index in BAD_YOGAS:
|
||
issues.append(f"不吉Yoga: #{yoga_index}")
|
||
return issues
|
||
|
||
|
||
def check_marriage_doshas(planets: Dict) -> List[str]:
|
||
"""婚姻专项Dosha检测"""
|
||
doshas = []
|
||
moon = planets.get("Moon", {})
|
||
moon_sign = moon.get("sign", "")
|
||
|
||
# Sagraha Dosha: Moon conjunct any planet
|
||
for p_name, pd in planets.items():
|
||
if p_name != "Moon" and pd.get("sign") == moon_sign:
|
||
doshas.append(f"Sagraha Dosha: Moon合{p_name}在{moon_sign}")
|
||
break
|
||
|
||
# Moon in 6/8/12
|
||
moon_house = moon.get("house", 0)
|
||
if moon_house in (6, 8, 12):
|
||
doshas.append(f"Shashtashta Dosha: Moon在{moon_house}宫")
|
||
|
||
# Venus in 6th
|
||
if planets.get("Venus", {}).get("house") == 6:
|
||
doshas.append("Bhrigupta Shatka: Venus在6宫")
|
||
|
||
# Mars in 8th
|
||
if planets.get("Mars", {}).get("house") == 8:
|
||
doshas.append("Kujaasthama: Mars在8宫")
|
||
|
||
return doshas
|
||
|
||
|
||
def evaluate_muhurtha(activity: str, tithi_num: int, nakshatra_name: str,
|
||
yoga_index: int, weekday: str = "", lagna_sign: str = "",
|
||
planets: Optional[Dict] = None) -> Dict:
|
||
"""
|
||
评估特定活动的择时吉凶。
|
||
|
||
Args:
|
||
activity: 'marriage'|'travel'|'business'|'education'|'house_entry'|'medical'
|
||
tithi_num: 阴历日编号(1-30)
|
||
nakshatra_name: 星宿名称
|
||
yoga_index: Panchang Yoga索引
|
||
weekday: 星期几
|
||
lagna_sign: 上升星座
|
||
planets: 行星位置(用于dosha检测)
|
||
|
||
Returns:
|
||
吉凶评估结果
|
||
"""
|
||
rules = ACTIVITY_RULES.get(activity)
|
||
if not rules:
|
||
return {"verdict": "error", "reason": f"未知活动: {activity}",
|
||
"activities": list(ACTIVITY_RULES.keys())}
|
||
|
||
positive, negative = [], []
|
||
|
||
# 1. Panchanga Suddhi
|
||
issues = check_panchanga_suddhi(tithi_num, nakshatra_name, yoga_index)
|
||
negative.extend(issues)
|
||
|
||
# 2. Nakshatra
|
||
good_naks = rules.get("good_nakshatras", set())
|
||
if nakshatra_name in good_naks:
|
||
positive.append(f"吉祥星宿: {nakshatra_name}")
|
||
elif nakshatra_name and nakshatra_name not in BAD_NAKSHATRAS:
|
||
negative.append(f"星宿{nakshatra_name}非最佳")
|
||
|
||
# 3. Tithi
|
||
good_tithis = rules.get("good_tithis", set())
|
||
if tithi_num in good_tithis:
|
||
positive.append(f"吉祥日: Tithi #{tithi_num}")
|
||
|
||
# 4. Weekday
|
||
good_wds = rules.get("good_weekdays")
|
||
if good_wds and weekday:
|
||
if weekday in good_wds:
|
||
positive.append(f"吉祥曜日: {weekday}")
|
||
else:
|
||
negative.append(f"曜日{weekday}非最佳")
|
||
|
||
# 5. Lagna
|
||
good_lagnas = rules.get("good_lagnas")
|
||
if good_lagnas and lagna_sign:
|
||
if lagna_sign in good_lagnas:
|
||
positive.append(f"吉祥上升: {lagna_sign}")
|
||
else:
|
||
negative.append(f"上升{lagna_sign}非最佳")
|
||
|
||
# 6. Moon sign (business)
|
||
good_moon = rules.get("good_moon_signs")
|
||
if good_moon and planets:
|
||
ms = planets.get("Moon", {}).get("sign", "")
|
||
if ms in good_moon:
|
||
positive.append(f"月亮在吉位: {ms}")
|
||
else:
|
||
negative.append(f"月亮{ms}非最佳")
|
||
|
||
# 7. Marriage doshas
|
||
if activity == "marriage" and planets:
|
||
for d in check_marriage_doshas(planets):
|
||
negative.append(f"DOSHA: {d}")
|
||
|
||
# 8. 8th house check
|
||
if activity in ("marriage", "medical", "house_entry") and planets:
|
||
for pn, pd in planets.items():
|
||
if pn not in ("Rahu", "Ketu") and pd.get("house") == 8:
|
||
negative.append(f"行星在8宫: {pn}")
|
||
break
|
||
|
||
# Scoring
|
||
score = len(positive) * 10 - len(negative) * 15
|
||
has_hard_reject = any("DOSHA:" in n for n in negative)
|
||
|
||
if has_hard_reject:
|
||
verdict = "不吉"
|
||
elif len(negative) == 0 and len(positive) >= 2:
|
||
verdict = "大吉"
|
||
elif len(positive) > len(negative):
|
||
verdict = "尚可"
|
||
elif len(negative) > len(positive):
|
||
verdict = "不吉"
|
||
else:
|
||
verdict = "中性"
|
||
|
||
return {
|
||
"activity": activity,
|
||
"verdict": verdict,
|
||
"score": max(0, score),
|
||
"positive": positive,
|
||
"negative": negative,
|
||
}
|