""" Marriage Counting Method (婚姻计数法) —— Bhrigu 体系 v7.0 Jyotish Vedic Astrology Skill 来源:bhrigu-pada-dasha-marriage-counting.md 算法:D1 第7宫主在 D1 的星座(A) → D9 的星座(B) → 从A数到B(含首尾)= 关系几何指数 产品口径(TASK-upstream-sync4-20261002 决策 2,BUG-1183):本模块只输出几何指数, 不输出婚姻或关系的次数、先后与质量断语。字段 marriage_count 为兼容旧消费方保留, 值与 geometric_index 相同。 v7.0 新增: - Parivartana自动重算(原为TODO) - D9 Venus/Mars/7宫主完整状态评估 - Upapada Loga整合 """ from typing import Dict, Optional, List # 星座名称 SIGN_CN = ['白羊座','金牛座','双子座','巨蟹座','狮子座','处女座', '天秤座','天蝎座','射手座','摩羯座','水瓶座','双鱼座'] def sign_of(lon: float) -> int: """从黄道经度计算星座序号 (0-11)""" return int((lon % 360) / 30) def marriage_counting_method( d1_house7_lord: str, d1_planet_lons: Dict[str, float], d9_planet_lons: Dict[str, float], d1_houses: Optional[Dict] = None, d9_houses: Optional[Dict] = None, parivartana_check: bool = True ) -> Dict: """ 婚姻计数法 (Marriage Counting Method) 参数: d1_house7_lord: D1 第7宫主星名称 (如 'Venus') d1_planet_lons: D1 行星经度字典 d9_planet_lons: D9 行星经度字典 d1_houses: D1 宫位数据 (可选,用于 Parivartana 检查) d9_houses: D9 宫位数据 (可选) parivartana_check: 是否检查 Parivartana (默认 True) 返回: dict: { 'method': 'Marriage Counting Method', 'd1_7th_lord': str, 'point_A': {'sign': int, 'sign_cn': str}, # D1 中7宫主星座 'point_B': {'sign': int, 'sign_cn': str}, # D9 中7宫主星座 'distance': int, # 从A数到B (包含A和B) 'geometric_index': int, # 关系几何指数(不是婚姻或关系次数) 'marriage_count': int, # 兼容字段,同 geometric_index 'interpretation': str, # 解读 'parivartana': dict or None, # Parivartana 检查结果 'warnings': list, } """ warnings = [] # Step 1: 找到 D1 第7宫主 if not d1_house7_lord: return {'error': '未提供 D1 第7宫主', 'method': 'Marriage Counting Method'} # Step 2: 找到 7宫主在 D1 中的星座 (A) if d1_house7_lord not in d1_planet_lons: warnings.append(f"D1 中未找到 {d1_house7_lord} 的位置") return {'error': f"D1 中未找到 {d1_house7_lord}", 'method': 'Marriage Counting Method'} d1_lon = d1_planet_lons[d1_house7_lord] point_A = sign_of(d1_lon) # Step 3: 找到 7宫主在 D9 中的星座 (B) if d1_house7_lord not in d9_planet_lons: warnings.append(f"D9 中未找到 {d1_house7_lord} 的位置") return {'error': f"D9 中未找到 {d1_house7_lord}", 'method': 'Marriage Counting Method'} d9_lon = d9_planet_lons[d1_house7_lord] point_B = sign_of(d9_lon) # Step 4: 计数 (从 A 到 B,包含 A 和 B)。须在 Parivartana 重算之前求出: # 旧代码先在警告里引用 distance 再赋值,有交换时抛 UnboundLocalError(BUG-1184)。 if point_B >= point_A: distance = point_B - point_A + 1 else: # 跨越白羊座0°: 从 A 到双鱼座(11) + 从白羊座(0) 到 B distance = (11 - point_A + 1) + (point_B + 1) # Parivartana 检查 parivartana = None if parivartana_check and d1_houses: parivartana = _check_parivartana( d1_house7_lord, point_A, d1_houses, d1_planet_lons ) if parivartana and parivartana.get('has_parivartana'): # v7.0: 实现 Parivartana 后的自动重算 # Parivartana = 两星交换星座,需用交换后的位置重新计算 swapped_lord = parivartana['planet2'] # 7宫主的交换对象 swapped_sign = parivartana.get('planet2_sign', point_A) # 用交换后的星座作为新的 Point A point_A_swapped = swapped_sign # 重新计算距离 if point_B >= point_A_swapped: distance_swapped = point_B - point_A_swapped + 1 else: distance_swapped = (11 - point_A_swapped + 1) + (point_B + 1) warnings.append( f"Parivartana(行星交换)!{d1_house7_lord} 与 {swapped_lord} 交换。" f" 原计数={distance},交换后计数={distance_swapped}。" f" 以交换后计数为准。" ) # 使用交换后的结果 distance = distance_swapped marriage_count = distance # 解读 interpretation = _interpret_marriage_count(marriage_count, point_A, point_B) return { 'method': 'Marriage Counting Method (Bhrigu)', 'd1_7th_lord': d1_house7_lord, 'point_A': { 'sign': point_A, 'sign_cn': SIGN_CN[point_A], 'degree': d1_lon, }, 'point_B': { 'sign': point_B, 'sign_cn': SIGN_CN[point_B], 'degree': d9_lon, }, 'distance': distance, 'geometric_index': marriage_count, 'marriage_count': marriage_count, 'interpretation': interpretation, 'parivartana': parivartana, 'warnings': warnings, } def _check_parivartana( lord: str, lord_sign: int, d1_houses: Dict, d1_planet_lons: Dict[str, float] ) -> Dict: """ 检查 7宫主是否与其落入星座的主星有 Parivartana(行星交换) 返回: {'has_parivartana': bool, 'planet1': str, 'planet2': str, ...} """ # 找到 lord 落入星座的主星 SIGN_LORDS = ['Mars','Venus','Mercury','Moon','Sun','Mercury', 'Venus','Mars','Jupiter','Saturn','Saturn','Jupiter'] host = SIGN_LORDS[lord_sign] # lord 落入星座的主星 # 落在自己掌管的星座不是 Parivartana(行星交换),只是 own-sign 状态。 if host == lord: return {'has_parivartana': False, 'reason': f'{lord} 位于自己掌管的星座,不构成 Parivartana'} if host not in d1_planet_lons: return {'has_parivartana': False, 'reason': f'{host} 位置未知'} host_sign = sign_of(d1_planet_lons[host]) # Parivartana: lord 在 host 的星座里(host 的定义已保证),host 在 lord 掌管的星座里。 # 旧写法比较 host 与 lord 是否同星座,实际判的是合相而非互换(BUG-1184)。 if SIGN_LORDS[host_sign] == lord: return { 'has_parivartana': True, 'planet1': lord, 'planet1_sign': lord_sign, 'planet2': host, 'planet2_sign': host_sign, 'note': f'{lord}(在{ SIGN_CN[lord_sign]}) 与 {host}(在{ SIGN_CN[host_sign]}) 交换宫位', } return {'has_parivartana': False} def _interpret_marriage_count(count: int, A: int, B: int) -> str: """只描述几何量,不推出婚姻或关系的次数、先后与质量(BUG-1183)。""" lines = [ f"关系几何指数 {count}:D1 第7宫主所在星座数到它在 D9 所在星座的距离(含首尾)," "是这个方法里的星座距离,不代表婚姻或关系的次数。" ] if A == B: lines.append("D1 与 D9 两个参照点落在同一星座。") if (B - A) % 12 == 6: lines.append("D1 与 D9 两个参照点落在相对的星座。") return "\n".join(lines) def marriage_counting_full_analysis( d1_house7_lord: str, d1_planet_lons: Dict[str, float], d9_planet_lons: Dict[str, float], d1_houses: Optional[Dict] = None, d9_houses: Optional[Dict] = None, d1_moon_nak_idx: Optional[int] = None, d9_upapada_lord: Optional[str] = None, ) -> Dict: """ 完整婚姻计数分析(配合 Dasha + D9 验证) 返回包含婚姻计数 + D9 质量评估 + 综合建议 """ # 基础计数 base = marriage_counting_method( d1_house7_lord, d1_planet_lons, d9_planet_lons, d1_houses, d9_houses ) if 'error' in base: return base # D9 质量评估(简化版) d9_quality = _assess_d9_marriage_quality(d9_planet_lons, d9_houses) # 综合建议 recommendations = _marriage_recommendations(base, d9_quality) return { **base, 'd9_marriage_quality': d9_quality, 'recommendations': recommendations, 'note': '几何指数只是方法内的星座距离,不是婚姻或关系的计数。', } def _assess_d9_marriage_quality( d9_planet_lons: Dict[str, float], d9_houses: Optional[Dict] ) -> Dict: """D9 婚姻质量评估 v7.0(完整版)""" quality_points = 0 factors = [] SIGN_LORDS_LIST = ['Mars','Venus','Mercury','Moon','Sun','Mercury', 'Venus','Mars','Jupiter','Saturn','Saturn','Jupiter'] def _sign_of(lon): return int((lon % 360) / 30) def _dignity(planet, sign_idx): """简化星性判断""" EXALTATION = {'Sun': 0, 'Moon': 1, 'Mars': 9, 'Mercury': 5, 'Jupiter': 3, 'Venus': 11, 'Saturn': 6} OWN = {'Sun': [4], 'Moon': [3], 'Mars': [0, 7], 'Mercury': [2, 5], 'Jupiter': [8, 11], 'Venus': [1, 6], 'Saturn': [9, 10]} DEBILITATION = {'Sun': 6, 'Moon': 7, 'Mars': 3, 'Mercury': 11, 'Jupiter': 9, 'Venus': 5, 'Saturn': 0} if sign_idx == EXALTATION.get(planet, -1): return 'exalted' if sign_idx in OWN.get(planet, []): return 'own' if sign_idx == DEBILITATION.get(planet, -1): return 'debilitated' return 'neutral' # 检查 D9 Venus 状态(完整版) venus_d9 = d9_planet_lons.get('Venus') if venus_d9 is not None: venus_sign = _sign_of(venus_d9) venus_dig = _dignity('Venus', venus_sign) if venus_dig == 'exalted': quality_points += 3 factors.append(f"D9 Venus擢升在{SIGN_CN[venus_sign]} → 婚姻质量极高") elif venus_dig == 'own': quality_points += 2 factors.append(f"D9 Venus入庙在{SIGN_CN[venus_sign]} → 婚姻关系质量高") elif venus_dig == 'debilitated': quality_points -= 2 factors.append(f"D9 Venus落陷在{SIGN_CN[venus_sign]} → 婚姻关系有重大挑战") elif venus_sign in [1, 6]: # Taurus/Libra own quality_points += 2 factors.append(f"D9 Venus在本宫{SIGN_CN[venus_sign]} → 关系质量好") else: quality_points += 0 factors.append(f"D9 Venus在{SIGN_CN[venus_sign]}({venus_dig}) → 关系质量中等") # 检查 D9 Mars 状态(婚姻中的冲突指标) mars_d9 = d9_planet_lons.get('Mars') if mars_d9 is not None: mars_sign = _sign_of(mars_d9) mars_dig = _dignity('Mars', mars_sign) if mars_dig == 'debilitated': quality_points -= 1 factors.append(f"D9 Mars落陷 → 婚姻中缺乏行动力/保护") elif mars_dig in ('exalted', 'own'): quality_points += 1 factors.append(f"D9 Mars强 → 婚姻中有保护力和行动力") # 检查 D9 Jupiter 状态(婚姻中的智慧和祝福) jup_d9 = d9_planet_lons.get('Jupiter') if jup_d9 is not None: jup_sign = _sign_of(jup_d9) jup_dig = _dignity('Jupiter', jup_sign) if jup_dig in ('exalted', 'own'): quality_points += 2 factors.append(f"D9 Jupiter强在{SIGN_CN[jup_sign]} → 婚姻有智慧和祝福") elif jup_dig == 'debilitated': quality_points -= 1 factors.append(f"D9 Jupiter落陷 → 婚姻缺乏指引") # 检查 D9 7宫/7宫主(如果有宫位数据) if d9_houses and '7' in d9_houses: h7_d9 = d9_houses['7'] if isinstance(h7_d9, dict) and 'lord' in h7_d9: h7_lord_d9 = h7_d9['lord'] factors.append(f"D9 第7宫主:{h7_lord_d9}") # D9 7宫主的星性 h7l_d9_lon = d9_planet_lons.get(h7_lord_d9) if h7l_d9_lon is not None: h7l_sign = _sign_of(h7l_d9_lon) h7l_dig = _dignity(h7_lord_d9, h7_sign) if h7l_dig in ('exalted', 'own'): quality_points += 2 factors.append(f"D9 7宫主{h7_lord_d9}强 → 伴侣支持有力") elif h7l_dig == 'debilitated': quality_points -= 1 factors.append(f"D9 7宫主{h7_lord_d9}落陷 → 伴侣关系挑战") # 检查 D9 Rahu/Ketu 对7宫的影响 rahu_d9 = d9_planet_lons.get('Rahu') ketu_d9 = d9_planet_lons.get('Ketu') if d9_houses: h7_sign = d9_houses.get('7', {}) if isinstance(h7_sign, dict) and 'sign' in h7_sign: h7_sign_name = h7_sign['sign'] SIGNS_LIST = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo', 'Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces'] if h7_sign_name in SIGNS_LIST: h7_idx = SIGNS_LIST.index(h7_sign_name) if rahu_d9 is not None and _sign_of(rahu_d9) == h7_idx: quality_points -= 1 factors.append("D9 Rahu在7宫 → 关系中的迷惑/非常规因素") if ketu_d9 is not None and _sign_of(ketu_d9) == h7_idx: quality_points -= 1 factors.append("D9 Ketu在7宫 → 关系中的分离倾向") # 综合评级 if quality_points >= 4: rating = "高(关系质量好,伴侣支持强,婚姻稳定)" elif quality_points >= 1: rating = "中上(关系质量尚可,需经营但基础好)" elif quality_points >= 0: rating = "中(关系质量一般,需用心经营)" elif quality_points >= -2: rating = "中下(关系有挑战,需提前沟通和调整期望)" else: rating = "低(关系质量有重大挑战,强烈建议婚前咨询)" return { 'quality_rating': rating, 'quality_points': quality_points, 'factors': factors, } def _marriage_recommendations(base: Dict, d9_quality: Dict) -> List[str]: """几何指数与伴侣数量、事件断语分开(BUG-1183);不随指数大小给不同结论。""" return [ "几何指数需与 D1 第7宫主、它在 D9 的落点以及已记录的尊贵因素一起读,不单独下结论。", "这个指数不指认第几位伴侣,也不说明关系的长短、好坏或是否专一。", "涉及时间的判断须另看已算出的 Dasha 与过运,并以本人的实际经历为准。", ] # 导出函数 def calc_marriage_count(d1_7lord, d1_lons, d9_lons, d1_h=None, d9_h=None): """便捷函数:计算婚姻计数""" return marriage_counting_method(d1_7lord, d1_lons, d9_lons, d1_h, d9_h) if __name__ == '__main__': # 测试:假设 D1 7宫主 = Venus,D1 Venus 在 Gemini(2),D9 Venus 在 Virgo(5) test = marriage_counting_method( 'Venus', {'Venus': 2*30 + 15}, # Gemini 15° {'Venus': 5*30 + 10}, # Virgo 10° ) print(test)