from __future__ import annotations import unittest from backend.features.heaven.six_yao import ( _palace_map, build_six_yao_chart, ) class SixYaoEngineTests(unittest.TestCase): def test_eight_palaces_cover_every_hexagram_once(self): palaces = _palace_map() self.assertEqual(len(palaces), 64) self.assertEqual( {item["trigram"] for item in palaces.values()}, {"乾", "兑", "离", "震", "巽", "坎", "艮", "坤"}, ) self.assertEqual( {item["stage"] for item in palaces.values()}, {"本宫", "一世", "二世", "三世", "四世", "五世", "游魂", "归魂"}, ) def test_pure_qian_uses_standard_najia_and_self_response(self): chart = build_six_yao_chart( [7, 7, 7, 7, 7, 7], "2026-08-04T10:30:00+08:00", ) self.assertEqual(chart["palace"]["name"], "乾宫") self.assertEqual(chart["palace"]["stage"], "本宫") self.assertEqual(chart["palace"]["self_position"], 6) self.assertEqual(chart["palace"]["response_position"], 3) self.assertEqual( [(line["stem"], line["branch"]) for line in chart["lines"]], [("甲", "子"), ("甲", "寅"), ("甲", "辰"), ("壬", "午"), ("壬", "申"), ("壬", "戌")], ) self.assertEqual( [line["relative"] for line in chart["lines"]], ["子孙", "妻财", "父母", "官鬼", "兄弟", "父母"], ) self.assertEqual(chart["branch_pattern"], "六冲") def test_pure_kun_uses_standard_najia(self): chart = build_six_yao_chart( [8, 8, 8, 8, 8, 8], "2026-08-04T10:30:00+08:00", ) self.assertEqual(chart["palace"]["name"], "坤宫") self.assertEqual( [(line["stem"], line["branch"]) for line in chart["lines"]], [("乙", "未"), ("乙", "巳"), ("乙", "卯"), ("癸", "丑"), ("癸", "亥"), ("癸", "酉")], ) def test_cast_time_drives_day_void_and_six_spirits(self): chart = build_six_yao_chart( [7, 7, 7, 7, 7, 7], "2026-08-04T02:30:00Z", ) self.assertEqual(chart["cast_at"], "2026-08-04T10:30:00+08:00") self.assertEqual(chart["calendar"]["day"], "庚戌") self.assertEqual(chart["calendar"]["day_void"], "寅卯") self.assertEqual( [line["spirit"] for line in chart["lines"]], ["白虎", "玄武", "青龙", "朱雀", "勾陈", "螣蛇"], ) def test_moving_line_has_deterministic_transformation(self): chart = build_six_yao_chart( [6, 7, 8, 9, 7, 8], "2026-08-04T10:30:00+08:00", ) moving = [line for line in chart["lines"] if line["moving"]] self.assertEqual([line["position"] for line in moving], [1, 4]) self.assertTrue(all(line.get("transformation") for line in moving)) self.assertFalse(any(line.get("transformation") for line in chart["lines"] if not line["moving"])) if __name__ == "__main__": unittest.main()