rebuild(stage-11): deliver deterministic heaven workflows

This commit is contained in:
leefer
2026-07-30 07:08:13 +08:00
parent aa3f02bd59
commit 35ae079de7
49 changed files with 7208 additions and 39 deletions
+77
View File
@@ -0,0 +1,77 @@
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)