from __future__ import annotations import json from functools import lru_cache from pathlib import Path from typing import Any TRIGRAM_NAMES = { (1, 1, 1): "乾", (1, 1, 0): "兑", (1, 0, 1): "离", (1, 0, 0): "震", (0, 1, 1): "巽", (0, 1, 0): "坎", (0, 0, 1): "艮", (0, 0, 0): "坤", } LINE_POSITIONS = ("初爻", "二爻", "三爻", "四爻", "五爻", "上爻") def from_lines(values: list[int], data_path: Path) -> dict[str, Any]: if len(values) != 6 or any(value not in {6, 7, 8, 9} for value in values): raise ValueError("六爻必须由六、七、八、九组成,且从初爻到上爻排列。") bits = tuple(1 if value % 2 else 0 for value in values) transformed_values = [7 if value == 6 else 8 if value == 9 else value for value in values] transformed_bits = tuple(1 if value % 2 else 0 for value in transformed_values) data = _load(data_path) primary = data.get(str(bits)) transformed = data.get(str(transformed_bits)) if not primary or not transformed: raise ValueError("卦象数据不完整。") line_texts = list(primary["lines"].values()) lines = [ { "position": index + 1, "position_name": LINE_POSITIONS[index], "value": value, "yin_yang": "阳" if value % 2 else "阴", "moving": value in {6, 9}, "line_name": line_texts[index]["name"], "text": line_texts[index]["text"], "image": line_texts[index].get("image") or "", } for index, value in enumerate(values) ] return { "name": primary["name"], "text": primary["text"], "image": primary.get("image") or "", "inner_trigram": TRIGRAM_NAMES[bits[:3]], "outer_trigram": TRIGRAM_NAMES[bits[3:]], "lines": lines, "moving_lines": [index + 1 for index, value in enumerate(values) if value in {6, 9}], "transformed": { "name": transformed["name"], "text": transformed["text"], "image": transformed.get("image") or "", "inner_trigram": TRIGRAM_NAMES[transformed_bits[:3]], "outer_trigram": TRIGRAM_NAMES[transformed_bits[3:]], }, } def line_for_score(score: float) -> int: if score >= 0.72: return 9 if score >= 0: return 7 if score <= -0.72: return 6 return 8 @lru_cache(maxsize=2) def _load(path: Path) -> dict[str, Any]: payload = json.loads(path.read_text(encoding="utf-8")) return payload.get("hexagrams", payload)