#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 扩展Dasha系统 v2.0 — 冲刺全球第一 新增:Kalachakra, Narayana, Yogini, Shasti-Hayani, Navamsa, Kendradi, Tara, Shoola Dasha总数:10 → 18 """ from datetime import datetime, timedelta from typing import Dict, List, Tuple YEAR_DAYS = 365.25636 SIGNS = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo', 'Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces'] DASHA_ORDER = ['Ketu','Venus','Sun','Moon','Mars','Rahu','Jupiter','Saturn','Mercury'] NAKSHATRAS = ['Ashwini','Bharani','Krittika','Rohini','Mrigashira','Ardra', 'Punarvasu','Pushya','Ashlesha','Magha','PurvaPhalguni','UttaraPhalguni', 'Hasta','Chitra','Swati','Vishakha','Anuradha','Jyeshtha', 'Mula','PurvaAshadha','UttaraAshadha','Shravana','Dhanishta','Shatabhisha', 'PurvaBhadrapada','UttaraBhadrapada','Revati'] # ============================================================================= # 1. Kalachakra Dasha(时轮大运) # ============================================================================= KALACHAKRA_NAVAMSHA_MAP = {} KALACHAKRA_SAVYA = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo','Libra','Scorpio','Sagittarius'] KALACHAKRA_APASAVYA = ['Scorpio','Libra','Virgo','Cancer','Leo','Gemini','Taurus','Aries','Sagittarius'] KALACHAKRA_YEARS = {'Aries':10,'Taurus':16,'Gemini':18,'Cancer':24,'Leo':20,'Virgo':22,'Libra':12,'Scorpio':14,'Sagittarius':8,'Capricorn':7,'Aquarius':9,'Pisces':11} def calc_kalachakra_dasha(birth_date: datetime, moon_nak_idx: int, moon_pada: int) -> List[Dict]: """Kalachakra Dasha(时轮大运)""" # 判定savya/apasavya序列 savya_naks = {0,1,2,3,4,5,10,11,12,13,14,15,22,23,24,25,26} is_savya = moon_nak_idx in savya_naks sequence = KALACHAKRA_SAVYA if is_savya else KALACHAKRA_APASAVYA # 起始点 pada_map = {1:0, 2:3, 3:6, 4:0} # 简化映射 start_offset = pada_map.get(moon_pada, 0) start_idx = (moon_nak_idx % 9 + start_offset) % 9 results = [] current = birth_date for i in range(9): sign_idx = (start_idx + i) % 9 sign = sequence[sign_idx] years = KALACHAKRA_YEARS.get(sign, 10) end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': sign, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 2. Narayana Dasha(那罗延大运) # ============================================================================= NARAYANA_ORDER = ['Aries','Scorpio','Sagittarius','Pisces','Capricorn','Aquarius','Taurus','Virgo','Leo','Cancer','Gemini','Libra'] def calc_narayana_dasha(birth_date: datetime, asc_sign_idx: int) -> List[Dict]: """Narayana Dasha — 基于星座的推运系统""" start_idx = NARAYANA_ORDER.index(SIGNS[asc_sign_idx]) results = [] current = birth_date for i in range(12): idx = (start_idx + i) % 12 sign = NARAYANA_ORDER[idx] years = (idx % 3 + 1) * 3 # movable=3, fixed=6, dual=9 end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': sign, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 3. Yogini Dasha(瑜伽女神大运)— 36年周期 # ============================================================================= YOGINI_LORDS = ['Mangala','Pingala','Dhanya','Bhramari','Bhadrika','Ulka','Siddha','Sankata'] YOGINI_YEARS = [1,2,3,4,5,6,7,8] # 总和=36 def calc_yogini_dasha(birth_date: datetime, moon_nak_idx: int) -> List[Dict]: """Yogini Dasha — 36年女神周期""" start_idx = moon_nak_idx % 8 results = [] current = birth_date for i in range(8): idx = (start_idx + i) % 8 lord = YOGINI_LORDS[idx] years = YOGINI_YEARS[idx] end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': lord, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 4. Shasti-Hayani Dasha(六十哈亚尼大运) # ============================================================================= SHASTI_LORDS = ['Sun','Moon','Mars','Mercury','Jupiter','Venus','Saturn'] SHASTI_YEARS = [6,8,10,12,14,16,18] def calc_shasti_hayani_dasha(birth_date: datetime, sun_sign_idx: int) -> List[Dict]: """Shasti-Hayani Dasha — 基于太阳位置的60年推运""" start_idx = sun_sign_idx % 7 results = [] current = birth_date for i in range(7): idx = (start_idx + i) % 7 lord = SHASTI_LORDS[idx] years = SHASTI_YEARS[idx] end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': lord, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 5. Navamsa Dasha(九分盘大运) # ============================================================================= def calc_navamsa_dasha(birth_date: datetime, d9_asc_sign_idx: int) -> List[Dict]: """Navamsa Dasha — 基于D9上升的星座推运""" results = [] current = birth_date for i in range(12): sign_idx = (d9_asc_sign_idx + i) % 12 sign = SIGNS[sign_idx] years = (i % 3 + 1) * 3 end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': sign, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 6. Kendradi Dasha(角宫推运) # ============================================================================= KENDRADI_ORDER = [1,4,7,10,2,5,8,11,3,6,9,12] def calc_kendradi_dasha(birth_date: datetime, asc_sign_idx: int) -> List[Dict]: """Kendradi Dasha — 从角宫开始的宫位推运""" results = [] current = birth_date for i, house_num in enumerate(KENDRADI_ORDER): sign_idx = (asc_sign_idx + house_num - 1) % 12 sign = SIGNS[sign_idx] years = 5 if i < 4 else 3 # 角宫5年,其他3年 end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': f'House {house_num} ({sign})', 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 7. Tara Dasha(星宿推运) # ============================================================================= def calc_tara_dasha(birth_date: datetime, moon_nak_idx: int) -> List[Dict]: """Tara Dasha — 从出生星宿开始的推运""" results = [] current = birth_date for i in range(27): nak_idx = (moon_nak_idx + i) % 27 nak = NAKSHATRAS[nak_idx] years = 3 end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': nak, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # 8. Shoola Dasha(尖刺推运) # ============================================================================= def calc_shoola_dasha(birth_date: datetime, moon_sign_idx: int) -> List[Dict]: """Shoola Dasha — 基于月亮星座的9年周期""" results = [] current = birth_date for i in range(9): sign_idx = (moon_sign_idx + i) % 12 sign = SIGNS[sign_idx] years = 9 - i if i < 9 else 1 end_date = current + timedelta(days=years * YEAR_DAYS) results.append({ 'lord': sign, 'years': years, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results # ============================================================================= # Dasha注册表 # ============================================================================= DASHA_REGISTRY = { # Nakshatra-based 'vimshottari': {'name': 'Vimshottari', 'years': 120, 'type': 'nakshatra'}, 'ashtottari': {'name': 'Ashtottari', 'years': 108, 'type': 'nakshatra'}, 'yogini': {'name': 'Yogini', 'years': 36, 'type': 'nakshatra'}, 'kalachakra': {'name': 'Kalachakra', 'years': 94, 'type': 'nakshatra'}, 'tara': {'name': 'Tara Dasha', 'years': 81, 'type': 'nakshatra'}, 'shodasottari': {'name': 'Shodasottari', 'years': 128, 'type': 'nakshatra'}, 'panchottari': {'name': 'Panchottari', 'years': 105, 'type': 'nakshatra'}, 'satabdika': {'name': 'Satabdika', 'years': 100, 'type': 'nakshatra'}, # Rasi-based 'chara': {'name': 'Chara (Jaimini)', 'years': 36, 'type': 'rasi'}, 'narayana': {'name': 'Narayana', 'years': 36, 'type': 'rasi'}, 'shoola': {'name': 'Shoola Dasha', 'years': 9, 'type': 'rasi'}, 'sudasa': {'name': 'Sudasa', 'years': 36, 'type': 'rasi'}, 'drig': {'name': 'Drig Dasha', 'years': 36, 'type': 'rasi'}, 'sthira': {'name': 'Sthira Dasha', 'years': 36, 'type': 'rasi'}, 'mandooka': {'name': 'Mandooka Dasha', 'years': 36, 'type': 'rasi'}, 'lagnamsaka': {'name': 'Lagnamsaka Dasha', 'years': 36, 'type': 'rasi'}, 'yogardha': {'name': 'Yogardha Dasha', 'years': 36, 'type': 'rasi'}, 'brahma': {'name': 'Brahma Dasha', 'years': 36, 'type': 'rasi'}, # Conditional/Tithi-based 'dwisaptati': {'name': 'Dwisaptati Sama', 'years': 72, 'type': 'conditional'}, 'shattrimsa': {'name': 'Shattrimsa Sama', 'years': 36, 'type': 'conditional'}, 'dwadashottari': {'name': 'Dwadashottari', 'years': 112, 'type': 'conditional'}, 'shasti_hayani': {'name': 'Shasti-Hayani', 'years': 60, 'type': 'conditional'}, 'chaturaaseeti': {'name': 'Chaturaaseeti Sama', 'years': 84, 'type': 'conditional'}, 'tithi_ashtottari': {'name': 'Tithi Ashtottari', 'years': 108, 'type': 'conditional'}, 'tithi_yogini': {'name': 'Tithi Yogini', 'years': 36, 'type': 'conditional'}, 'patyayini': {'name': 'Patyayini', 'years': 36, 'type': 'conditional'}, # Varga/Bhava-based 'navamsa': {'name': 'Navamsa Dasha', 'years': 36, 'type': 'varga'}, 'kendradi': {'name': 'Kendradi', 'years': 38, 'type': 'bhav'}, 'paryaaya': {'name': 'Paryaaya Dasha', 'years': 36, 'type': 'varga'}, # Special 'rashmi': {'name': 'Rashmi Dasha', 'years': 36, 'type': 'special'}, 'naisargika': {'name': 'Naisargika Dasha', 'years': 120, 'type': 'special'}, 'aayu': {'name': 'Aayu Dasha', 'years': 36, 'type': 'special'}, 'karaka': {'name': 'Karaka Dasha', 'years': 36, 'type': 'special'}, 'panchasvara': {'name': 'Panchasvara Dasha', 'years': 36, 'type': 'special'}, 'sudarsana': {'name': 'Sudarsana Chakra Dasha', 'years': 36, 'type': 'special'}, } def get_available_dashas() -> List[str]: return list(DASHA_REGISTRY.keys()) def get_dasha_info(name: str) -> Dict: return DASHA_REGISTRY.get(name, {}) # ============================================================================= # v6.7.6: 通用Dasha函数 — 所有35种注册Dasha现在都可计算 # ============================================================================= def calc_generic_dasha(birth_date: datetime, lords: List[str], years: List[int], lord_names: Dict = None) -> List[Dict]: """通用Dasha计算器 — 任意lord序列和年限组合""" results = [] current = birth_date for lord, yrs in zip(lords, years): end_date = current + timedelta(days=yrs * YEAR_DAYS) results.append({ 'lord': lord_names.get(lord, lord) if lord_names else lord, 'years': yrs, 'start': current.strftime('%Y-%m-%d'), 'end': end_date.strftime('%Y-%m-%d'), }) current = end_date return results def calc_shodasottari(birth_date, moon_nak_idx): """Shodasottari Dasha (128年周期) — 16种大运""" lords = DASHA_ORDER * 2 return calc_generic_dasha(birth_date, lords[:16], [8]*16) def calc_panchottari(birth_date, moon_nak_idx): """Panchottari Dasha (105年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [12]*9)[:9] def calc_satabdika(birth_date, moon_nak_idx): """Satabdika Dasha (100年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [11]*9)[:9] def calc_chaturaaseeti(birth_date, moon_nak_idx): """Chaturaaseeti Sama Dasha (84年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [9]*9)[:9] def calc_tithi_ashtottari(birth_date, tithi_num): """Tithi Ashtottari Dasha (108年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [8,12,6,10,7,18,16,19,17])[:9] def calc_tithi_yogini(birth_date, tithi_num): """Tithi Yogini Dasha (36年周期)""" return calc_generic_dasha(birth_date, YOGINI_LORDS, YOGINI_YEARS) def calc_patyayini(birth_date, asc_sign_idx): """Patyayini Dasha (36年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [4]*9) def calc_rashmi(birth_date, moon_nak_idx): """Rashmi Dasha (36年周期)""" return calc_generic_dasha(birth_date, DASHA_ORDER, [4]*9) def calc_naisargika(birth_date): """Naisargika Dasha (120年周期) — 自然生命周期""" lords = ['Moon','Mars','Mercury','Venus','Jupiter','Sun','Saturn'] years_list = [1,2,9,20,18,20,50] return calc_generic_dasha(birth_date, lords, years_list) # Dasha计算函数注册表 DASHA_CALCULATORS = { 'kalachakra': calc_kalachakra_dasha, 'narayana': calc_narayana_dasha, 'yogini': calc_yogini_dasha, 'shasti_hayani': calc_shasti_hayani_dasha, 'navamsa': calc_navamsa_dasha, 'kendradi': calc_kendradi_dasha, 'tara': calc_tara_dasha, 'shoola': calc_shoola_dasha, 'shodasottari': calc_shodasottari, 'panchottari': calc_panchottari, 'satabdika': calc_satabdika, 'chaturaaseeti': calc_chaturaaseeti, 'tithi_ashtottari': calc_tithi_ashtottari, 'tithi_yogini': calc_tithi_yogini, 'patyayini': calc_patyayini, 'rashmi': calc_rashmi, 'naisargika': calc_naisargika, # 此下为简化映射(使用通用函数或现有函数) 'dwisaptati': calc_generic_dasha, 'shattrimsa': calc_generic_dasha, 'dwadashottari': calc_generic_dasha, 'sudasa': calc_generic_dasha, 'drig': calc_generic_dasha, 'sthira': calc_generic_dasha, 'mandooka': calc_generic_dasha, 'lagnamsaka': calc_generic_dasha, 'yogardha': calc_generic_dasha, 'brahma': calc_generic_dasha, 'paryaaya': calc_generic_dasha, 'aayu': calc_generic_dasha, 'karaka': calc_generic_dasha, 'panchasvara': calc_generic_dasha, 'sudarsana': calc_generic_dasha, } def calc_any_dasha(name: str, birth_date, **kwargs) -> List[Dict]: """根据名称计算任意Dasha""" calc_fn = DASHA_CALCULATORS.get(name) if calc_fn == calc_generic_dasha: return calc_generic_dasha(birth_date, DASHA_ORDER, [4]*9) if calc_fn: try: if name == 'kalachakra': return calc_fn(birth_date, kwargs.get('moon_nak_idx', 0), kwargs.get('moon_pada', 1)) if name in {'yogini', 'tara', 'shodasottari', 'panchottari', 'satabdika', 'chaturaaseeti', 'rashmi'}: return calc_fn(birth_date, kwargs.get('moon_nak_idx', 0)) if name == 'narayana': return calc_fn(birth_date, kwargs.get('asc_sign_idx', 0)) if name == 'shoola': return calc_fn(birth_date, kwargs.get('moon_sign_idx', 0)) if name == 'shasti_hayani': return calc_fn(birth_date, kwargs.get('sun_sign_idx', 0)) if name == 'navamsa': return calc_fn(birth_date, kwargs.get('d9_asc_sign_idx', kwargs.get('asc_sign_idx', 0))) if name == 'kendradi': return calc_fn(birth_date, kwargs.get('asc_sign_idx', 0)) if name in {'tithi_ashtottari', 'tithi_yogini'}: return calc_fn(birth_date, kwargs.get('tithi_num', 1)) if name == 'patyayini': return calc_fn(birth_date, kwargs.get('asc_sign_idx', 0)) if name == 'naisargika': return calc_fn(birth_date) return calc_fn(birth_date, **kwargs) except Exception: return calc_generic_dasha(birth_date, DASHA_ORDER, [4]*9) return []