90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from backend.features.heaven.engine import build_five_phase_field
|
|
|
|
|
|
class FivePhaseFrameworkTests(unittest.TestCase):
|
|
def test_public_field_uses_year_current_qi_day_contract(self):
|
|
field = build_five_phase_field("2026-06-15")
|
|
|
|
self.assertEqual(
|
|
field["framework"]["weights"],
|
|
{
|
|
"year_movement": 30,
|
|
"sitian_zaiquan": 20,
|
|
"sitian": 15,
|
|
"zaiquan": 5,
|
|
"host_qi": 20,
|
|
"guest_qi": 25,
|
|
"day": 5,
|
|
},
|
|
)
|
|
self.assertEqual(
|
|
[(layer["id"], layer["weight"]) for layer in field["framework"]["layers"]],
|
|
[("year", 50), ("current", 45), ("day", 5)],
|
|
)
|
|
self.assertEqual(sum(item["score"] for item in field["balance"]), 100)
|
|
|
|
def test_sitian_and_zaiquan_follow_half_year_dominance(self):
|
|
first_half = build_five_phase_field("2026-06-15")
|
|
second_half = build_five_phase_field("2026-08-20")
|
|
|
|
self.assertEqual(first_half["framework"]["weights"]["sitian"], 15)
|
|
self.assertEqual(first_half["framework"]["weights"]["zaiquan"], 5)
|
|
self.assertEqual(first_half["six_qi"]["ruling"], "司天")
|
|
self.assertEqual(second_half["framework"]["weights"]["sitian"], 5)
|
|
self.assertEqual(second_half["framework"]["weights"]["zaiquan"], 15)
|
|
self.assertEqual(second_half["six_qi"]["ruling"], "在泉")
|
|
|
|
def test_guest_host_relation_and_anchor_alignment_are_explicit(self):
|
|
third_qi = build_five_phase_field("2026-06-15")
|
|
final_qi = build_five_phase_field("2026-12-10")
|
|
controlled = build_five_phase_field("2025-02-10")
|
|
|
|
self.assertEqual(third_qi["framework"]["relations"]["guest_host"]["label"], "客主同气")
|
|
self.assertEqual(third_qi["six_qi"]["alignment"], "司天同位")
|
|
self.assertEqual(final_qi["framework"]["relations"]["guest_host"]["label"], "客生主")
|
|
self.assertEqual(final_qi["six_qi"]["alignment"], "在泉同位")
|
|
self.assertEqual(controlled["framework"]["relations"]["guest_host"]["order"], "客胜为从")
|
|
|
|
def test_tianfu_and_suihui_use_traditional_year_positions(self):
|
|
taiyi = build_five_phase_field("2038-06-15")
|
|
non_suihui = build_five_phase_field("2022-06-15")
|
|
|
|
self.assertEqual(
|
|
taiyi["framework"]["relations"]["annual_pattern"]["primary"],
|
|
"太乙天符",
|
|
)
|
|
self.assertFalse(
|
|
non_suihui["framework"]["relations"]["annual_pattern"]["is_suihui"]
|
|
)
|
|
|
|
def test_public_field_has_no_observation_hour(self):
|
|
field = build_five_phase_field("2026-07-18")
|
|
|
|
self.assertNotIn("time", field["pillars"])
|
|
self.assertNotIn("observation_time", field)
|
|
|
|
def test_sector_catalog_lists_all_rules_and_applies_manual_overrides(self):
|
|
field = build_five_phase_field(
|
|
"2026-07-18",
|
|
{"电力": "水", "低空经济": "木"},
|
|
)
|
|
groups = {item["element"]: item["industries"] for item in field["sector_catalog"]}
|
|
names = {
|
|
element: {item["name"]: item["classification_source"] for item in items}
|
|
for element, items in groups.items()
|
|
}
|
|
|
|
self.assertEqual(set(groups), {"木", "火", "土", "金", "水"})
|
|
self.assertNotIn("电力", names["火"])
|
|
self.assertEqual(names["水"]["电力"], "manual")
|
|
self.assertEqual(names["木"]["低空经济"], "manual")
|
|
self.assertEqual(sum(len(items) for items in groups.values()), 144)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|