"""12개월 운세 흐름 — 월운(月運) + 일간 관계.""" from typing import List from .constants import ( HEAVENLY_STEMS, EARTHLY_BRANCHES, FIVE_ELEMENTS, SHENG_CYCLE, KE_CYCLE, ) # 寅월부터 시작 (1월=寅, 2월=卯, ..., 12월=丑) MONTH_BRANCHES = ["寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥", "子", "丑"] LIU_CHONG = { frozenset(["子", "午"]), frozenset(["丑", "未"]), frozenset(["寅", "申"]), frozenset(["卯", "酉"]), frozenset(["辰", "戌"]), frozenset(["巳", "亥"]), } LIU_HE = { frozenset(["子", "丑"]), frozenset(["寅", "亥"]), frozenset(["卯", "戌"]), frozenset(["辰", "酉"]), frozenset(["巳", "申"]), frozenset(["午", "未"]), } def _month_stem_for_year(year_stem: str, branch_idx: int) -> str: """월간(月干) — saju-web의 공식: (yearStemIdx * 2 + branchIdx) % 10.""" year_stem_idx = HEAVENLY_STEMS.index(year_stem) stem_idx = (year_stem_idx * 2 + branch_idx) % 10 return HEAVENLY_STEMS[stem_idx] def _label_for(score: int) -> str: if score >= 80: return "성장" if score >= 65: return "안정" if score >= 50: return "변동" if score >= 35: return "도전" return "정체" def calculate_monthly_flow(saju: dict, year: int) -> List[dict]: """12개월 운세 흐름.""" day_stem = saju["day_stem"] day_element = FIVE_ELEMENTS[day_stem] day_branch = saju["day"]["branch"] year_stem = saju["year"]["stem"] flow: List[dict] = [] for i, branch in enumerate(MONTH_BRANCHES): branch_idx = EARTHLY_BRANCHES.index(branch) stem = _month_stem_for_year(year_stem, branch_idx) stem_element = FIVE_ELEMENTS[stem] branch_element = FIVE_ELEMENTS[branch] score = 60 if SHENG_CYCLE.get(day_element) == stem_element: score += 5 elif SHENG_CYCLE.get(stem_element) == day_element: score += 10 elif KE_CYCLE.get(day_element) == stem_element: score += 8 elif KE_CYCLE.get(stem_element) == day_element: score -= 8 elif stem_element == day_element: score += 3 if frozenset([day_branch, branch]) in LIU_HE: score += 10 elif frozenset([day_branch, branch]) in LIU_CHONG: score -= 12 if SHENG_CYCLE.get(branch_element) == day_element: score += 4 elif KE_CYCLE.get(branch_element) == day_element: score -= 4 score = max(0, min(100, score)) flow.append({ "month": i + 1, "stem": stem, "branch": branch, "score": score, "label": _label_for(score), }) return flow