Files
brainwave/docs/domain-rules.md
T

6.4 KiB
Raw Blame History

领域规则:三枚铜币与六爻

状态:MVP 强制规范 适用范围:所有起卦算法、显示模型、持久化模型和相关测试

本文件定义本项目唯一允许的计算规则。UI 文案、AI 输出和数据源都不能覆盖这些规则。

实现状态:coin-v1 纯 Kotlin 核心位于 app/src/main/java/net/opcapp/flash/domain/casting/;.\gradlew.bat :app:testDebugUnitTest 覆盖 8 种币面、4,096 种六爻、64 模式、已知夹具和 DTO 往返。记录时间与内容版本在确定性计算完成后附加。

1. 术语和类型

建议使用有语义的封闭类型,避免裸 Int 在层间传播:

enum class CoinSide(val value: Int) {
    CHARACTER(2), // 字面
    REVERSE(3),   // 背面
}

enum class LineValue(val sum: Int, val polarity: Polarity, val moving: Boolean) {
    OLD_YIN(6, Polarity.YIN, true),
    YOUNG_YANG(7, Polarity.YANG, false),
    YOUNG_YIN(8, Polarity.YIN, false),
    OLD_YANG(9, Polarity.YANG, true),
}

enum class Polarity { YIN, YANG }

代码片段只表达契约,最终实现的包名和细节以系统架构为准。

2. 铜币计值约定

MVP 固定采用:

  • 字面 CHARACTER 计 2;
  • 背面 REVERSE 计 3;
  • 每轮三枚相加,结果只可能是 6、7、8、9。

传统资料对“正/反”“阴/阳”与 2/3 的命名存在不同约定,因此界面不得只写含糊的“正面/反面”。首次使用和投币页必须始终显示当前计值:“字 2,背 3”。如果未来允许切换约定,约定必须在第一轮之前锁定并写入结果;不得在六轮中途改变。

3. 爻值映射

和值 名称 本卦爻形 是否动爻 之卦爻形
6 老阴 阴爻,断线 是 阳爻,实线
7 少阳 阳爻,实线 否 阳爻,实线
8 少阴 阴爻,断线 否 阴爻,断线
9 老阳 阳爻,实线 是 阴爻,断线

强制不变量:

  • 偶数 6、8 为阴;奇数 7、9 为阳。
  • 只有 6 和 9 为动爻。
  • 之卦只翻转动爻;静爻保持不变。
  • AI、网络、时间、问题文本和设备状态均不得影响上述映射。

4. 六次录入与顺序

数组和数据库中的标准顺序一律为 bottom-up:

数组索引 中文位置 投币轮次
0 初爻 1
1 二爻 2
2 三爻 3
3 四爻 4
4 五爻 5
5 上爻 6

绘制界面时可以从屏幕顶部先画上爻,但只能在展示适配层反转;领域对象、序列化数据和测试夹具不得改成 top-down。

一个有效投币过程必须满足:

  • 恰好六轮;
  • 每轮恰好三枚;
  • 每枚只能是 CHARACTER 或 REVERSE;
  • 生成结果后保留原始 18 枚输入,便于复核和审计。

5. 本卦与之卦

CastResult 至少包含:

methodVersion
coinConvention
rounds[6][3]
lineValuesBottomUp[6]
primaryPatternBottomUp[6]
movingLinePositions[]       // 1..6,升序
transformedPatternBottomUp[6]
primaryHexagramId           // 文王卦序 1..64
transformedHexagramId       // 文王卦序 1..64
contentVersion
createdAt                   // 只用于记录,不参与计算

卦号不能通过“二进制数 + 1”推断。文王卦序不是简单二进制顺序,必须使用经过校验的“上卦 × 下卦”映射表或完整六爻模式映射表。

算法顺序:

  1. 将每轮三枚计值相加为 LineValue。
  2. 按录入顺序形成 bottom-up 六爻。
  3. 从各爻阴阳形成本卦模式并查得本卦编号。
  4. 收集值为 6 或 9 的位置作为动爻。
  5. 仅翻转动爻阴阳,形成之卦模式并查得之卦编号。
  6. 先将全部原始输入和确定结果构造成不可变 CastComputation,再附加 methodVersion、coinConvention、contentVersion 与 createdAt 记录元数据,组成不可变 CastResult;元数据不得反向影响步骤 1~5。

6. 读取内容的产品规则

MVP 采用透明而不过度裁决的显示策略:

  • 始终显示本卦卦辞。
  • 无动爻:明确显示“无动爻”;之卦与本卦相同,可弱化重复内容。
  • 有动爻:按初爻到上爻显示本卦中所有实际动爻的爻辞,并显示之卦。
  • 多个动爻:不由算法擅自选出“唯一主爻”,也不隐藏其他动爻。
  • 乾卦六爻皆九、坤卦六爻皆六时,若采用的数据版本含“用九/用六”,应作为特殊文本额外展示;是否纳入 MVP 见决策记录。

AI 可以组织和解释这些材料,但不得改变显示集合。

7. 状态机

DRAFT(question)
  └─ start → CASTING(confirmedRounds = 0..5)
                  ├─ edit previous → CASTING
                  ├─ confirm sixth → SEALED(CastResult)
                  └─ cancel → DRAFT

SEALED
  ├─ request local explanation → EXPLAINED_LOCAL
  ├─ consent + request AI → EXPLAINING_AI → EXPLAINED_AI | AI_FAILED
  └─ explicit restart → DRAFT(newSessionId)

禁止从 EXPLAINING_AI 或 EXPLAINED_AI 回写 CastResult。重新起卦必须创建新的会话标识。

8. 必须存在的确定性测试

输入(初爻到上爻) 本卦 之卦 动爻
7,7,7,7,7,7 乾 1 乾 1 无
8,8,8,8,8,8 坤 2 坤 2 无
9,9,9,9,9,9 乾 1 坤 2 1–6
6,6,6,6,6,6 坤 2 乾 1 1–6
7,8,8,8,8,8 复 24 复 24 无
9,8,8,8,8,8 复 24 坤 2 初爻

此外必须:

  • 穷举 8 种三枚铜币排列,验证求和与 LineValue。
  • 穷举 4⁶ = 4,096 种六爻数值组合,验证长度、动爻和变换不变量。
  • 验证 64 种阴阳模式恰好映射到 64 个不重复卦号。
  • 验证序列化再反序列化不改变任何确定字段。

9. 版本规则

  • 初始算法版本建议为 coin-v1。
  • 改变字/背计值、动爻规则、顺序或卦号映射都属于破坏性领域变更,必须新增版本和决策记录,不能静默覆盖历史结果。
  • 内容措辞变化只提升 contentVersion,不得改变 methodVersion。

参考资料仅用于交叉核验;仓库内上述规则才是实现事实源: