- Functional default = PVR Table 30 (functional_profile=pvr_table_30); the former product table is bphs_exception_profile, scored only when named (rectification names it, scores unchanged). profile_divergence shows both roles side by side; movable-lagna Moon by the table's paksha note; dual-lordship note; prior rulings BUG-1570/1590/#166 Q4 checked against Table 30. - Shadbala: six open items labelled parameter_sensitive; every option combination computed; only planets whose pass/fail flips get minimum_check=parameter_sensitive. - Vimshottari AD/PD rows carry parent_period_start / visible_period_start; the consult card cuts the balance MD from its full parent and clips at birth. - KP DBA: full first parent, clipped at birth (no balance rescale). - Mudda: balance fields + balance_method (angle default, time comparison apart), nominal_year_days, her crossing wording; Harsha combined blocked reason lists items. - D30 _meta describes the unequal parts (as her r40). - Golden recaptured with TTL=0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbBXoyn7Hj3LCW3BUs5bZ8
269 lines
14 KiB
Python
269 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Career Analysis(事业分析)引擎 v1.0
|
|
超越 vedic-astro-skills 的 AI prompt,实现结构化引擎级分析
|
|
|
|
核心分析链:
|
|
D10(Dashamsa)事业盘 → 10宫主状态 → Saturn/Jupiter角色 → Dasha事业窗口 → Yogas
|
|
"""
|
|
|
|
from typing import Dict, List, Any
|
|
import math
|
|
|
|
try:
|
|
from .functional_benefics import derive_functional_benefic_malefic, moon_paksha_from_planets, SIGN_LORDS
|
|
from .affliction_evidence import collect_affliction_evidence
|
|
except ImportError:
|
|
from functional_benefics import derive_functional_benefic_malefic, moon_paksha_from_planets, SIGN_LORDS
|
|
from affliction_evidence import collect_affliction_evidence
|
|
|
|
SIGNS = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo',
|
|
'Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces']
|
|
|
|
CAREER_SIGN_INDICATORS = {
|
|
'Aries': ['军事/执法','工程/技术','创业/先驱','外科医学'],
|
|
'Taurus': ['金融/银行','艺术/设计','餐饮/食品','奢侈品'],
|
|
'Gemini': ['媒体/传播','教育/培训','销售/贸易','IT/编程'],
|
|
'Cancer': ['医疗/护理','房地产','酒店/旅游','心理学/咨询'],
|
|
'Leo': ['管理/领导','娱乐/表演','政府/政治','教育/学术'],
|
|
'Virgo': ['数据分析','会计/审计','编辑/校对','医疗技术'],
|
|
'Libra': ['法律/司法','艺术/美学','公共关系','人力资源'],
|
|
'Scorpio': ['投资/风控','研究/侦探','心理学/精神分析','保险/精算'],
|
|
'Sagittarius': ['国际商务','教育/哲学','法律/宗教','出版/写作'],
|
|
'Capricorn': ['管理/行政','土木工程','政府/政策','传统行业'],
|
|
'Aquarius': ['科技/创新','NGO/公益','科学/研究','网络/电商'],
|
|
'Pisces': ['艺术/影视','医疗/康复','慈善/NGO','创意/设计'],
|
|
}
|
|
|
|
PLANET_CAREER_ROLES = {
|
|
'Sun': {'domain': '领导/管理','strength': '威权、决策、独立执业'},
|
|
'Moon': {'domain': '公众/服务','strength': '人际、关怀、变动适应'},
|
|
'Mars': {'domain': '执行/技术','strength': '行动力、工程、军事'},
|
|
'Mercury': {'domain': '信息/沟通','strength': '智力、商业、IT'},
|
|
'Jupiter': {'domain': '指导/教育','strength': '教导、咨询、法律'},
|
|
'Venus': {'domain': '艺术/财富','strength': '审美、金融、奢侈'},
|
|
'Saturn': {'domain': '管理/组织','strength': '纪律、行政、工业'},
|
|
'Rahu': {'domain': '创新/涉外','strength': '科技、外企、非传统'},
|
|
'Ketu': {'domain': '研究/灵性','strength': '分析、玄学、幕后'},
|
|
}
|
|
|
|
# Candidate symbolism, not a calibrated occupation classifier. Each candidate
|
|
# carries the actual tenth-house/lord witness; scores are not probabilities.
|
|
PLANET_INDUSTRIES = {
|
|
'Sun': ['领导/管理', '权力/公职'],
|
|
'Moon': ['公众/服务', '照护/餐旅'],
|
|
'Mars': ['体育/竞技', '工程/技术', '军事/执法'],
|
|
'Mercury': ['信息/沟通', '商业/贸易', '计算/分析'],
|
|
'Jupiter': ['教育/咨询', '法律/学术'],
|
|
'Venus': ['艺术/表演', '设计/审美'],
|
|
'Saturn': ['工业/工程', '组织/行政'],
|
|
}
|
|
|
|
D10_HOUSE_MEANINGS = {
|
|
1: '事业身份/职业形象', 2: '事业财富/收入来源', 3: '事业沟通/技能',
|
|
4: '事业根基/安稳度', 5: '事业创意/子女相关', 6: '事业竞争/服务',
|
|
7: '事业合作/客户', 8: '事业变革/危机管理', 9: '事业远见/高等教育',
|
|
10: '事业成就/社会地位', 11: '事业收益/人脉', 12: '事业幕后/海外',
|
|
}
|
|
|
|
|
|
def analyze_career(planets: Dict, asc_sign: str = 'Aries',
|
|
d10_positions: Dict = None, dasha_info: Dict = None,
|
|
shadbala: Dict = None,
|
|
career_semantic_profile: Dict = None, a10: Dict = None,
|
|
user_industry: str | None = None) -> Dict:
|
|
"""
|
|
完整事业分析引擎。
|
|
|
|
Args:
|
|
planets: D1行星位置 {planet: {'sign','house','degree',...}}
|
|
asc_sign: 上升星座
|
|
d10_positions: D10分盘行星位置(可选,提升精度)
|
|
dasha_info: 当前大运/小运信息(可选)
|
|
shadbala: Shadbala结果(可选)
|
|
|
|
Returns:
|
|
结构化事业分析
|
|
"""
|
|
analysis = {'indicators': [], 'strengths': [], 'challenges': [], 'timing': [], 'fields': []}
|
|
if asc_sign not in SIGNS:
|
|
raise ValueError('asc_sign must be a valid sign')
|
|
# 占星师 2026-11-08 第五轮裁定 3:默认 PVR 表 30;月亮盈亏供动星座上升的月亮用。
|
|
functional = derive_functional_benefic_malefic(asc_sign, moon_paksha=moon_paksha_from_planets(planets))
|
|
analysis['functional_benefic_malefic'] = functional
|
|
analysis['assertion_label'] = 'single_system_inference'
|
|
analysis['career_claim_gate'] = {
|
|
'industry_claim_allowed': bool(user_industry),
|
|
'public_backstage_claim_allowed': bool(user_industry and a10),
|
|
'user_industry': user_industry,
|
|
'boundary': 'Without the user\'s actual industry, fields remain candidate symbolism; public/backstage is not inferred from 6/8/12 placement alone.',
|
|
}
|
|
|
|
# 1. 10宫分析
|
|
asc_idx = SIGNS.index(asc_sign)
|
|
h10_sign = SIGNS[(asc_idx + 9) % 12]
|
|
h10_lord = {'Aries':'Mars','Taurus':'Venus','Gemini':'Mercury','Cancer':'Moon',
|
|
'Leo':'Sun','Virgo':'Mercury','Libra':'Venus','Scorpio':'Mars',
|
|
'Sagittarius':'Jupiter','Capricorn':'Saturn','Aquarius':'Saturn','Pisces':'Jupiter'}[h10_sign]
|
|
|
|
# 10宫主状态
|
|
h10_data = planets.get(h10_lord, {})
|
|
h10_house = h10_data.get('house', 0)
|
|
h10_dignity = h10_data.get('dignity', 'neutral')
|
|
|
|
analysis['indicators'].append({
|
|
'type': '10宫主分析',
|
|
'lord': h10_lord,
|
|
'sign': h10_sign,
|
|
'house': h10_house,
|
|
'dignity': h10_dignity,
|
|
'potential_fields': CAREER_SIGN_INDICATORS.get(h10_sign, []),
|
|
})
|
|
analysis['affliction_evidence'] = collect_affliction_evidence(
|
|
target_house=10,
|
|
target_lord=h10_lord,
|
|
planets=planets,
|
|
functional_malefics=functional.get('functional_malefics', []),
|
|
varga_pressure=bool(d10_positions),
|
|
)
|
|
|
|
# 2. 行星角色分配
|
|
for planet in ['Sun','Moon','Mars','Mercury','Jupiter','Venus','Saturn']:
|
|
pd = planets.get(planet, {})
|
|
if not pd:
|
|
continue
|
|
house = pd.get('house', 0)
|
|
if house in (1, 4, 7, 10):
|
|
analysis['strengths'].append({
|
|
'planet': planet,
|
|
'role': PLANET_CAREER_ROLES.get(planet, {}).get('domain', ''),
|
|
'detail': PLANET_CAREER_ROLES.get(planet, {}).get('strength', ''),
|
|
'house': house,
|
|
'note': f'{planet}在角宫({house}) — 事业核心驱动力',
|
|
})
|
|
|
|
# 3. Saturn角色(事业核心指示星)
|
|
saturn = planets.get('Saturn', {})
|
|
saturn_house = saturn.get('house', 0)
|
|
if saturn_house in (10, 6):
|
|
analysis['strengths'].append({'planet':'Saturn','role':'事业纪律候选','detail':'土星落事业/服务宫;组织、责任或持续训练是候选主题,需结合功能角色与强度。'})
|
|
if saturn_house in (8, 12):
|
|
analysis['challenges'].append({'planet':'Saturn','issue':'需核验工作环境与压力',
|
|
'detail':f'Saturn在{saturn_house}宫;这一落位不能单独确定发展速度或后期回报。',
|
|
'assertion_label':'user_history_verification_required', 'source_path':'planets.Saturn.house'})
|
|
|
|
# 4. 事业领域推荐
|
|
scored_fields = {}
|
|
# 10宫星座
|
|
for field in CAREER_SIGN_INDICATORS.get(h10_sign, []):
|
|
scored_fields[field] = scored_fields.get(field, 0) + 3
|
|
# 10宫主
|
|
if h10_lord in PLANET_CAREER_ROLES:
|
|
scored_fields[PLANET_CAREER_ROLES[h10_lord]['domain']] = scored_fields.get(PLANET_CAREER_ROLES[h10_lord]['domain'], 0) + 2
|
|
# D10分析(如果有)
|
|
d10_positions = d10_positions or {}
|
|
d10_planets = d10_positions.get('planets', d10_positions)
|
|
d10_asc = d10_positions.get('ascendant', d10_positions.get('Ascendant'))
|
|
if isinstance(d10_asc, dict):
|
|
d10_asc = d10_asc.get('sign')
|
|
d10_h10_sign = SIGNS[(SIGNS.index(d10_asc) + 9) % 12] if d10_asc in SIGNS else None
|
|
analysis['d10_evidence'] = {'ascendant': d10_asc, 'tenth_sign': d10_h10_sign,
|
|
'status': 'executed' if d10_h10_sign else 'blocked',
|
|
'missing_inputs': [] if d10_h10_sign else ['D10 ascendant']}
|
|
if d10_h10_sign:
|
|
for field in CAREER_SIGN_INDICATORS.get(d10_h10_sign, []):
|
|
scored_fields[field] = scored_fields.get(field, 0) + 1
|
|
|
|
candidates = {}
|
|
for layer, positions, lord in (
|
|
('D1', planets, h10_lord),
|
|
('D10', d10_planets, SIGN_LORDS.get(d10_h10_sign)),
|
|
):
|
|
for planet, fields in PLANET_INDUSTRIES.items():
|
|
pd = positions.get(planet)
|
|
if not isinstance(pd, dict) or not pd:
|
|
continue
|
|
witnesses = []
|
|
if pd.get('house') == 10:
|
|
witnesses.append('tenth_house_occupant')
|
|
if planet == lord:
|
|
witnesses.append('tenth_house_lord')
|
|
for field in fields:
|
|
if not witnesses:
|
|
continue
|
|
candidate = candidates.setdefault(field, {'field': field,
|
|
'assertion_label': 'single_system_inference', 'supporting_evidence': [],
|
|
'verification_question': '实际训练、作品或职业经历是否支持这一候选方向?'})
|
|
candidate['supporting_evidence'].append({'layer': layer, 'planet': planet,
|
|
'roles': witnesses, 'source_path': f'{layer}.planets.{planet}',
|
|
'functional_role': next(k for k in ('functional_benefics', 'functional_malefics', 'functional_neutrals') if planet in functional[k])})
|
|
analysis['industry_candidates'] = sorted(candidates.values(),
|
|
key=lambda row: (-len(row['supporting_evidence']), row['field']))
|
|
|
|
top_fields = sorted(scored_fields.items(), key=lambda x: x[1], reverse=True)[:5]
|
|
ranked_clusters = (
|
|
career_semantic_profile.get('ranked_role_clusters')
|
|
if isinstance(career_semantic_profile, dict)
|
|
and career_semantic_profile.get('status') == 'used'
|
|
else None
|
|
)
|
|
if isinstance(ranked_clusters, list) and ranked_clusters:
|
|
analysis['fields'] = ranked_clusters
|
|
analysis['field_recommendation_mode'] = 'evidence_ranked_clusters'
|
|
else:
|
|
analysis['fields'] = analysis['industry_candidates'] or [
|
|
{'field': f, 'score': s, 'assertion_label': 'parameter_sensitive',
|
|
'source_path': 'D1.tenth_sign', 'boundary': 'sign-only candidate, not a career verdict'}
|
|
for f, s in top_fields]
|
|
analysis['field_recommendation_mode'] = 'legacy_sign_indicator'
|
|
|
|
# 5. 时间窗口
|
|
if dasha_info:
|
|
current = dasha_info.get('current_dasha') or {}
|
|
current_ad = current.get('antardasha') or {}
|
|
md = current.get('lord') or dasha_info.get('maha_dasha') or dasha_info.get('current_md')
|
|
ad = current_ad.get('lord') if isinstance(current_ad, dict) else None
|
|
ad = ad or dasha_info.get('antar_dasha') or dasha_info.get('current_ad')
|
|
if md:
|
|
analysis['timing'].append({'current': '-'.join(p for p in (md, ad) if p),
|
|
'mahadasha': md, 'antardasha': ad, 'start': current.get('start'), 'end': current.get('end'),
|
|
'note': '保留引擎已计算的当前周期;具体事业应期还需领域激活与交叉验证。',
|
|
'assertion_label': 'single_system_inference'})
|
|
|
|
# 6. 综合评估
|
|
sb = shadbala or {}
|
|
sb_planets = sb.get('planets', sb)
|
|
strength_row = sb_planets.get(h10_lord) or {}
|
|
h10_strength = strength_row.get('total_rupas', strength_row.get('rupas'))
|
|
strength_present = isinstance(h10_strength, (int, float)) and not isinstance(h10_strength, bool) and math.isfinite(h10_strength) and h10_strength >= 0
|
|
analysis['strength_evidence'] = {'planet': h10_lord,
|
|
'rupas': h10_strength if strength_present else None,
|
|
'min_required': strength_row.get('min_required'),
|
|
'source_path': f'shadbala.{"planets." if "planets" in sb else ""}{h10_lord}'}
|
|
analysis['assessment_status'] = 'single_system_inference' if strength_present else 'blocked'
|
|
level = (f'10宫主{h10_lord}的Shadbala为{h10_strength:g} rupas;强度不是职业成功或公众知名度的保证。'
|
|
if strength_present else '缺少10宫主强度,不能确定事业承载力;已有职业候选与盘面依据仍保留。')
|
|
visibility = []
|
|
if planets.get('Sun', {}).get('house') == 10:
|
|
visibility.append({'source_path': 'D1.planets.Sun.house', 'theme': 'public_responsibility_candidate'})
|
|
if h10_house in (1, 4, 7, 10):
|
|
visibility.append({'source_path': f'D1.planets.{h10_lord}.house', 'theme': 'angular_career_lord'})
|
|
if a10:
|
|
visibility.append({'source_path': 'special_lagnas.A10_Karma_Pada', 'value': a10,
|
|
'theme': 'public_image_point_requires_context'})
|
|
analysis['visibility'] = {'status': 'single_system_inference' if visibility else 'blocked',
|
|
'supporting_evidence': visibility,
|
|
'boundary': '缺少公众信号不等于幕后;可见度与行业、工作方式分别判断。'}
|
|
analysis['technique_audit'] = [
|
|
{'technique': name, 'status': 'executed' if present else 'blocked'} for name, present in (
|
|
('D1', bool(planets)), ('Functional Benefic/Malefic', True),
|
|
('D10', bool(d10_h10_sign)), ('A10', bool(a10)),
|
|
('Shadbala', strength_present), ('Vimshottari', bool(analysis['timing'])),
|
|
('Narayana', False), ('MEVG / Global Web Evidence', False), ('Real Case Calibration', False))]
|
|
analysis['workflow_complete'] = False
|
|
|
|
analysis['assessment'] = level
|
|
|
|
return analysis
|