2026-08-04 17:09:52 +08:00
|
|
|
|
# 领域规则:三枚铜币与六爻
|
|
|
|
|
|
|
|
|
|
|
|
> 状态:MVP 强制规范
|
|
|
|
|
|
> 适用范围:所有起卦算法、显示模型、持久化模型和相关测试
|
|
|
|
|
|
|
|
|
|
|
|
本文件定义本项目唯一允许的计算规则。UI 文案、AI 输出和数据源都不能覆盖这些规则。
|
|
|
|
|
|
|
2026-08-07 18:00:38 +08:00
|
|
|
|
实现状态:`coin-v1` 纯 Kotlin 核心位于 `app/src/main/java/net/opcapp/flash/domain/casting/`;`.\gradlew.bat :app:testDebugUnitTest` 覆盖 8 种币面、4,096 种六爻、64 模式、已知夹具和 DTO 往返。记录时间与内容版本在确定性计算完成后附加。
|
2026-08-04 23:28:10 +08:00
|
|
|
|
|
2026-08-04 17:09:52 +08:00
|
|
|
|
## 1. 术语和类型
|
|
|
|
|
|
|
|
|
|
|
|
建议使用有语义的封闭类型,避免裸 `Int` 在层间传播:
|
|
|
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
|
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 }
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
代码片段只表达契约,最终实现的包名和细节以[系统架构](architecture.md)为准。
|
|
|
|
|
|
|
|
|
|
|
|
## 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` 至少包含:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
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. 仅翻转动爻阴阳,形成之卦模式并查得之卦编号。
|
2026-08-04 23:28:10 +08:00
|
|
|
|
6. 先将全部原始输入和确定结果构造成不可变 `CastComputation`,再附加 `methodVersion`、`coinConvention`、`contentVersion` 与 `createdAt` 记录元数据,组成不可变 `CastResult`;元数据不得反向影响步骤 1~5。
|
2026-08-04 17:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 6. 读取内容的产品规则
|
|
|
|
|
|
|
|
|
|
|
|
MVP 采用透明而不过度裁决的显示策略:
|
|
|
|
|
|
|
|
|
|
|
|
- 始终显示本卦卦辞。
|
|
|
|
|
|
- 无动爻:明确显示“无动爻”;之卦与本卦相同,可弱化重复内容。
|
|
|
|
|
|
- 有动爻:按初爻到上爻显示本卦中所有实际动爻的爻辞,并显示之卦。
|
|
|
|
|
|
- 多个动爻:不由算法擅自选出“唯一主爻”,也不隐藏其他动爻。
|
|
|
|
|
|
- 乾卦六爻皆九、坤卦六爻皆六时,若采用的数据版本含“用九/用六”,应作为特殊文本额外展示;是否纳入 MVP 见[决策记录](decisions.md#未决问题)。
|
|
|
|
|
|
|
|
|
|
|
|
AI 可以组织和解释这些材料,但不得改变显示集合。
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 状态机
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
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`。
|
|
|
|
|
|
|
|
|
|
|
|
参考资料仅用于交叉核验;仓库内上述规则才是实现事实源:
|
|
|
|
|
|
|
|
|
|
|
|
- [三枚铜币产生 6/7/8/9,并自下而上记录](https://uaya.org/learn/iching/using-the-oracle/casting-techniques/three-coins/understanding-results/)
|
|
|
|
|
|
- [三枚铜币法的爻值与动爻说明](https://www.ichingonline.net/instruction.php)
|