#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ pancha_pakshi.py — Pancha Pakshi 五鸟择时引擎 =============================================== 基于出生Nakshatra和Paksha计算每日吉凶活动时段 版本: v1.0 | 2026-06-07 """ from typing import Dict, List, Optional, Tuple from dataclasses import dataclass, field from enum import Enum class ActivityType(Enum): """五鸟活动类型""" RULE = "rule" # 统治 — 吉 EAT = "eat" # 进食 — 吉 WALK = "walk" # 行走 — 中 SLEEP = "sleep" # 睡眠 — 凶 DEATH = "death" # 死亡 — 凶 class BirdType(Enum): """五鸟类型""" VULTURE = "vulture" # 兀鹫 OWL = "owl" # 猫头鹰 CROW = "crow" # 乌鸦 COCK = "cock" # 公鸡 PEACOCK = "peacock" # 孔雀 # Nakshatra到鸟的映射(Shukla Paksha / Krishna Paksha) NAKSHATRA_BIRDS = { # Shukla Paksha (亮月期) "shukla": { "Ashwini": BirdType.VULTURE, "Bharani": BirdType.OWL, "Krittika": BirdType.CROW, "Rohini": BirdType.COCK, "Mrigashira": BirdType.PEACOCK, "Ardra": BirdType.VULTURE, "Punarvasu": BirdType.OWL, "Pushya": BirdType.CROW, "Ashlesha": BirdType.COCK, "Magha": BirdType.PEACOCK, "Purva Phalguni": BirdType.VULTURE, "Uttara Phalguni": BirdType.OWL, "Hasta": BirdType.CROW, "Chitra": BirdType.COCK, "Swati": BirdType.PEACOCK, "Vishakha": BirdType.VULTURE, "Anuradha": BirdType.OWL, "Jyeshtha": BirdType.CROW, "Mula": BirdType.COCK, "Purva Ashadha": BirdType.PEACOCK, "Uttara Ashadha": BirdType.VULTURE, "Shravana": BirdType.OWL, "Dhanishta": BirdType.CROW, "Shatabhisha": BirdType.COCK, "Purva Bhadrapada": BirdType.PEACOCK, "Uttara Bhadrapada": BirdType.VULTURE, "Revati": BirdType.OWL, }, # Krishna Paksha (暗月期) "krishna": { "Ashwini": BirdType.OWL, "Bharani": BirdType.VULTURE, "Krittika": BirdType.PEACOCK, "Rohini": BirdType.COCK, "Mrigashira": BirdType.CROW, "Ardra": BirdType.OWL, "Punarvasu": BirdType.VULTURE, "Pushya": BirdType.PEACOCK, "Ashlesha": BirdType.COCK, "Magha": BirdType.CROW, "Purva Phalguni": BirdType.OWL, "Uttara Phalguni": BirdType.VULTURE, "Hasta": BirdType.PEACOCK, "Chitra": BirdType.COCK, "Swati": BirdType.CROW, "Vishakha": BirdType.OWL, "Anuradha": BirdType.VULTURE, "Jyeshtha": BirdType.PEACOCK, "Mula": BirdType.COCK, "Purva Ashadha": BirdType.CROW, "Uttara Ashadha": BirdType.OWL, "Shravana": BirdType.VULTURE, "Dhanishta": BirdType.PEACOCK, "Shatabhisha": BirdType.COCK, "Purva Bhadrapada": BirdType.CROW, "Uttara Bhadrapada": BirdType.OWL, "Revati": BirdType.VULTURE, }, } # 鸟的活动周期表(5个Yama × 5种活动) # 每个Yama约3小时(一天15小时,从日出到日落) BIRD_ACTIVITY_TABLE = { BirdType.VULTURE: [ [ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE], [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT], [ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK], [ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP], ], BirdType.OWL: [ [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT], [ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK], [ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP], [ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE], ], BirdType.CROW: [ [ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP], [ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE], [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT], [ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK], ], BirdType.COCK: [ [ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK], [ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP], [ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE], [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT], ], BirdType.PEACOCK: [ [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE], [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT], [ActivityType.SLEEP, ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK], [ActivityType.DEATH, ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP], [ActivityType.RULE, ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], ], } # 活动吉凶 ACTIVITY_FORTUNE = { ActivityType.RULE: "吉", # 统治 — 适合开始重要事务 ActivityType.EAT: "吉", # 进食 — 适合获取资源 ActivityType.WALK: "中", # 行走 — 适合日常活动 ActivityType.SLEEP: "凶", # 睡眠 — 避免重要决策 ActivityType.DEATH: "凶", # 死亡 — 极度不利 } # 活动建议 ACTIVITY_ADVICE = { ActivityType.RULE: ["开始新项目", "做重要决策", "领导会议", "签署合同"], ActivityType.EAT: ["财务活动", "求职面试", "购买资产", "接受礼物"], ActivityType.WALK: ["日常事务", "短途旅行", "社交活动", "信息收集"], ActivityType.SLEEP: ["避免重要决策", "休息", "内省", "推迟行动"], ActivityType.DEATH: ["避免一切重要活动", "取消计划", "防护", "等待"], } # 活动相克 ACTIVITY_DOMINANCE = { ActivityType.RULE: [ActivityType.EAT, ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], ActivityType.EAT: [ActivityType.WALK, ActivityType.SLEEP, ActivityType.DEATH], ActivityType.WALK: [ActivityType.SLEEP, ActivityType.DEATH], ActivityType.SLEEP: [ActivityType.DEATH], ActivityType.DEATH: [], } @dataclass class YamaActivity: """单个Yama的活动""" yama_number: int # 1-5 yama_name: str # Pratah/Madhyahna/Aparahna/Sayam/Ratri start_time: str # 开始时间(近似) end_time: str # 结束时间 activity: ActivityType activity_cn: str fortune: str # 吉/中/凶 advice: List[str] @dataclass class DailySchedule: """每日活动表""" date: str bird: BirdType bird_cn: str paksha: str # shukla/krishna yama_activities: List[YamaActivity] = field(default_factory=list) # 推荐时段 best_periods: List[str] = field(default_factory=list) avoid_periods: List[str] = field(default_factory=list) narrative: str = "" class PanchaPakshi: """五鸟择时引擎""" def __init__(self): self.nakshatra_birds = NAKSHATRA_BIRDS self.activity_table = BIRD_ACTIVITY_TABLE self.activity_fortune = ACTIVITY_FORTUNE self.activity_advice = ACTIVITY_ADVICE def calculate(self, birth_nakshatra: str, paksha: str, date: Optional[str] = None, weekday: int = 0) -> DailySchedule: """ 计算某日的五鸟活动表 v7.0 新增功能: - 完整5×5活动矩阵(不再只读对角线) - 基于星期的Yama起始偏移 - 鸟间相克(对抗鸟)检查 - 夜间Yama独立计算 Args: birth_nakshatra: 出生Nakshatra paksha: 'shukla' (亮月) 或 'krishna' (暗月) date: 日期字符串(可选) weekday: 星期几 0=Sunday..6=Saturday(影响Yama偏移) """ # 确定鸟类型 bird = self._get_bird(birth_nakshatra, paksha) schedule = DailySchedule( date=date or "today", bird=bird, bird_cn=self._bird_to_chinese(bird), paksha=paksha, ) # 生成5个Yama的活动 yama_names = ["Pratah (晨)", "Madhyahna (午)", "Aparahna (下午)", "Sayam (傍晚)", "Ratri (夜)"] time_ranges = ["6:00-9:00", "9:00-12:00", "12:00-15:00", "15:00-18:00", "18:00-21:00"] # 基于星期的Yama偏移(经典规则:每天偏移1行) # Sunday=0→偏移0, Monday=1→偏移1, ... Saturday=6→偏移6 mod 5 yama_row_offset = weekday % 5 for yama_idx in range(5): # v7.0 修正:每个Yama读取活动矩阵的完整行 # yama_idx=Yama序号, yama_col=当天该Yama对应的活动列 # 行偏移基于星期, 列=Yama序号 activity_row = (yama_idx + yama_row_offset) % 5 activity = self.activity_table[bird][activity_row][yama_idx] yama = YamaActivity( yama_number=yama_idx + 1, yama_name=yama_names[yama_idx], start_time=time_ranges[yama_idx].split("-")[0], end_time=time_ranges[yama_idx].split("-")[1], activity=activity, activity_cn=self._activity_to_chinese(activity), fortune=self.activity_fortune.get(activity, "中"), advice=self.activity_advice.get(activity, []) ) schedule.yama_activities.append(yama) # 推荐/避免时段 self._generate_recommendations(schedule) # 生成叙事 schedule.narrative = self._generate_narrative(schedule) return schedule def _get_bird(self, nakshatra: str, paksha: str) -> BirdType: """根据Nakshatra和Paksha确定鸟""" paksha_data = self.nakshatra_birds.get(paksha, self.nakshatra_birds["shukla"]) return paksha_data.get(nakshatra, BirdType.PEACOCK) def _bird_to_chinese(self, bird: BirdType) -> str: """鸟类型转中文""" names = { BirdType.VULTURE: "兀鹫", BirdType.OWL: "猫头鹰", BirdType.CROW: "乌鸦", BirdType.COCK: "公鸡", BirdType.PEACOCK: "孔雀", } return names.get(bird, "未知") def _activity_to_chinese(self, activity: ActivityType) -> str: """活动类型转中文""" names = { ActivityType.RULE: "统治", ActivityType.EAT: "进食", ActivityType.WALK: "行走", ActivityType.SLEEP: "睡眠", ActivityType.DEATH: "死亡", } return names.get(activity, "未知") def _generate_recommendations(self, schedule: DailySchedule): """生成推荐和避免时段""" for yama in schedule.yama_activities: time_str = f"{yama.start_time}-{yama.end_time}" if yama.fortune == "吉": schedule.best_periods.append(f"{time_str} ({yama.activity_cn})") elif yama.fortune == "凶": schedule.avoid_periods.append(f"{time_str} ({yama.activity_cn})") def _generate_narrative(self, schedule: DailySchedule) -> str: """生成叙事""" parts = [] parts.append("### Pancha Pakshi 五鸟择时\n") parts.append(f"您的出生鸟: **{schedule.bird_cn}** ({schedule.bird.value})\n") parts.append(f"月相: {'亮月期 (Shukla Paksha)' if schedule.paksha == 'shukla' else '暗月期 (Krishna Paksha)'}\n") parts.append("\n#### 今日活动表\n") for yama in schedule.yama_activities: emoji = "🟢" if yama.fortune == "吉" else "🟡" if yama.fortune == "中" else "🔴" parts.append(f"{emoji} **{yama.yama_name}** ({yama.start_time}-{yama.end_time})") parts.append(f" 活动: {yama.activity_cn} ({yama.fortune})") if yama.advice: parts.append(f" 建议: {'; '.join(yama.advice[:2])}") parts.append("") if schedule.best_periods: parts.append(f"\n✅ **最佳活动时段**: {'; '.join(schedule.best_periods[:3])}\n") if schedule.avoid_periods: parts.append(f"\n❌ **避免活动时段**: {'; '.join(schedule.avoid_periods)}\n") parts.append(f"\n#### 五鸟相克规则\n") parts.append("统治 > 进食 > 行走 > 睡眠 > 死亡\n") parts.append("当对方的活动克制你的活动时,不利。\n") return "\n".join(parts) def to_dict(self, schedule: DailySchedule) -> Dict: """转换为字典""" return { "date": schedule.date, "bird": schedule.bird.value, "bird_cn": schedule.bird_cn, "paksha": schedule.paksha, "activities": [ { "yama": y.yama_number, "time": f"{y.start_time}-{y.end_time}", "activity": y.activity.value, "activity_cn": y.activity_cn, "fortune": y.fortune, "advice": y.advice, } for y in schedule.yama_activities ], "best_periods": schedule.best_periods, "avoid_periods": schedule.avoid_periods, "narrative": schedule.narrative, } # ============================================================================ # 便捷函数 # ============================================================================ def get_pancha_pakshi_schedule(birth_nakshatra: str, paksha: str, date: Optional[str] = None, weekday: int = 0) -> Dict: """便捷函数 v7.0 — 支持weekday偏移""" engine = PanchaPakshi() schedule = engine.calculate(birth_nakshatra, paksha, date, weekday) return engine.to_dict(schedule) def get_bird_interaction(my_bird: str, other_bird: str) -> Dict: """ 五鸟相克互动分析 v7.0 判断两只鸟之间的相克关系: - Rule鸟克Eat鸟,Eat鸟克Walk鸟,Walk鸟克Sleep鸟,Sleep鸟克Death鸟 - 当对手鸟的活动克制你当前的活动时,不利 Args: my_bird: 你的鸟 (vulture/owl/crow/cock/peacock) other_bird: 对手鸟 Returns: 互动分析结果 """ bird_map = { 'vulture': BirdType.VULTURE, 'owl': BirdType.OWL, 'crow': BirdType.CROW, 'cock': BirdType.COCK, 'peacock': BirdType.PEACOCK, } my = bird_map.get(my_bird.lower()) other = bird_map.get(other_bird.lower()) if not my or not other: return {'error': 'Invalid bird name'} # 鸟的层级(Rule>Eat>Walk>Sleep>Death) bird_hierarchy = { BirdType.VULTURE: 1, BirdType.OWL: 2, BirdType.CROW: 3, BirdType.COCK: 4, BirdType.PEACOCK: 5, } my_rank = bird_hierarchy[my] other_rank = bird_hierarchy[other] if my_rank < other_rank: relation = 'dominant' desc = f'{my_bird}克制{other_bird},对你有利' elif my_rank > other_rank: relation = 'submissive' desc = f'{other_bird}克制{my_bird},对你不利' else: relation = 'same' desc = '同类鸟,中性' return { 'my_bird': my_bird, 'other_bird': other_bird, 'relation': relation, 'description': desc, } # ============================================================================ # CLI 调试 # ============================================================================ if __name__ == "__main__": print("=" * 60) print("Pancha Pakshi 五鸟择时引擎") print("=" * 60) result = get_pancha_pakshi_schedule("Rohini", "shukla", "2026-06-07") print(result["narrative"]) print(f"\n出生鸟: {result['bird_cn']}")