Files
cmr-mini/doc/gameplay/多赛道Variant五层设计草案.md

384 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 多赛道 Variant 五层设计草案
> 文档版本v0.1
> 最后更新2026-04-02 18:24:00
本文档用于定义“一个活动对应多版 KML / 多条赛道”时的推荐架构。
目标:
- 不从页面交互倒推系统结构
- 先把多赛道能力按平台层次拆清
- 让前端、后端、后台、恢复、结果页都围绕同一套事实工作
- 为后续“手动选择 / 随机指定 / 后端指定”留出统一伸缩空间
说明:
- 本文档是设计草案,不是最终接口契约
- 本文档优先定义分层、边界、事实和约束
- 具体页面表现、后台表单细节、字段命名可在后续实现阶段微调
---
## 1. 背景与核心判断
当前项目里,一场活动后续可能不止一版 KML。
常见需求包括:
- 同一活动下有 A / B / C 多条赛道
- 准备阶段允许玩家手动选择
- 准备阶段由系统随机分配
- 后续可能由后台或裁判端直接指定
这里最关键的判断是:
**赛道版本不是页面临时状态,而是 session 级事实。**
也就是说,一旦某局比赛绑定了某个赛道版本,这个事实必须贯穿:
- 准备阶段
- launch
- session start / finish
- 故障恢复
- result
- ongoing session
- 历史结果
如果这一点不先定住,后面多端、多页面、多恢复链会很快乱掉。
---
## 2. 总体原则
多赛道能力建议固定遵守下面 6 条原则:
1. 一局比赛只绑定一个赛道版本
2. 前端可以参与选择,但最终绑定以后端 session 为准
3. 客户端不应各自实现不同的随机分配规则
4. 恢复链必须记住赛道版本
5. 结果页、历史结果和 ongoing 摘要必须可追溯赛道版本
6. 扩展新分配模式时,不破坏现有分层
一句话总结:
**前端负责交互后端负责最终绑定session 负责真实落账。**
---
## 3. 五层模型
多赛道能力建议拆成 5 层。
### 3.1 资源层
职责:
- 只定义赛道素材本身
- 不讨论谁来选,不讨论 session
典型内容:
- KML 文件
- 赛道元数据
- 可选地图资源
- 可选赛道封面、说明图
这一层回答的是:
- 这个赛道版本本身是什么
- 它的原始素材和元信息是什么
建议约束:
- 每个赛道版本都应有稳定的 `variantId`
- 每个赛道版本都应能独立定位到自己的 KML / manifest 入口
- 资源层不应混入“本局随机到谁”这种运行时逻辑
### 3.2 活动编排层
职责:
- 定义一个活动下有哪些赛道版本可用
- 定义这些版本如何被分配
典型内容:
- `assignmentMode`
- `courseVariants[]`
- 权重
- 可选分组规则
- 可选活动级覆盖
这一层回答的是:
- 当前活动允许哪些赛道版本
- 当前活动按什么模式分配赛道
推荐至少支持 3 种模式:
1. `manual`
- 用户手选
2. `random`
- 系统随机指定
3. `server-assigned`
- 后端预先指定,前端只展示
后续可扩展模式:
- 按分组分配
- 按批次轮换
- 团队共用赛道
- 避免重复赛道
### 3.3 会话绑定层
职责:
- 真正决定“这局比赛到底绑定哪条赛道”
- 作为跨端、跨页面、跨恢复的一致事实
这一层回答的是:
- 当前 session 最终绑定的是哪个 `variantId`
- 这个绑定是手选、随机还是后端直接指定
这一层必须落账的最小事实建议包括:
- `sessionId`
- `eventId`
- `variantId`
- `assignmentMode`
- `assignedAt`
- 可选的 `assignmentSource`
核心约束:
- `variantId` 一旦绑定,不应在本局内漂移
- launch、恢复、结果、排行榜都要引用同一 `variantId`
- 客户端本地恢复快照必须保存 `variantId`
### 3.4 客户端呈现层
职责:
- 负责向玩家展示可选项或绑定结果
- 负责发起用户选择
- 负责消费最终绑定后的赛道配置
这一层回答的是:
- 准备页要不要展示赛道列表
- 是否允许点击手选
- 是否显示“本局随机分配结果”
- 地图页加载哪一个 manifest
推荐规则:
- `manual`:准备页展示赛道列表,允许选择
- `random`:准备页展示“随机分配”结果,不允许随意更改
- `server-assigned`:准备页只展示最终结果,不提供选择
强约束:
- 客户端不能把“页面选择结果”当成最终事实
- 客户端必须以后端返回的 `variantId` 为准
- 地图页只消费最终绑定后的 manifest / runtime profile
### 3.5 后台运营层
职责:
- 管理赛道版本
- 管理活动编排
- 管理发布与审计
这一层回答的是:
- 活动有哪些赛道版本
- 每个版本的素材、说明和发布状态是什么
- 当前活动采用哪种分配策略
- 某局最终是怎么绑定出来的
后台层建议逐步承担:
- 赛道版本管理
- 活动绑定多个 variant
- 权重配置
- 发布检查
- 历史审计
---
## 4. 多端协作边界
多赛道能力一旦牵涉多端,最容易出问题的地方是边界不清。
建议固定边界如下:
### 4.1 前端负责
- 展示赛道选择或展示赛道结果
- 发起选择请求或发起随机请求
- 消费 launch 返回的赛道绑定结果
- 在地图、恢复、结果页中显示当前 `variantId` 或赛道名
### 4.2 后端负责
- 最终确认本局绑定哪个 `variantId`
-`variantId` 写入 session
- 确保 launch 返回的 release / manifest 与 `variantId` 对应
- 确保 result / ongoing / recovery 均能反查 `variantId`
### 4.3 后台负责
- 管理活动可用的 variants
- 管理 assignment mode
- 管理发布、上下线和审计
约束:
- 不允许前端自己定义“随机分配算法”后直接当成最终结果
- 不允许某端私自改 `variantId` 但不落 session
- 不允许恢复链丢失 `variantId`
---
## 5. 配置与发布建议
多赛道不是只改一个 `kmlUrl`
它建议进入活动编排配置,而不是页面临时字段。
推荐抽象:
- 活动级:
- `assignmentMode`
- `courseVariants[]`
- variant 级:
- `id`
- `name`
- `kmlUrl`
- `weight`
- `overrides`
如果某些版本不仅 KML 不同,连分值、样式、规则也不同,推荐允许 variant 带局部覆盖。
推荐覆盖顺序:
`系统默认值 -> 玩法默认值 -> 活动默认值 -> variant 覆盖 -> 单点覆盖`
这样未来不会因为多赛道把既有继承体系打乱。
---
## 6. 恢复、结果与摘要约束
### 6.1 故障恢复
恢复快照中必须加入:
- `variantId`
- 可选 `variantName`
恢复原则:
- 恢复的是这局绑定的赛道事实
- 不重新随机
- 不重新询问选择
### 6.2 结果页
结果页建议至少展示:
- 活动名
- 赛道版本名或 `variantId`
- 本局结果摘要
### 6.3 ongoing / recent / 历史成绩
这些摘要建议都能反映:
- 本局属于哪个赛道版本
否则后续:
- 用户无法判断自己玩的哪版
- 运营无法解释同活动下不同赛道差异
- 排名、复盘、申诉都困难
---
## 7. 推荐实施顺序
这块不建议一上来就做全套复杂功能。
推荐分三期:
### 第一期:架构定型
目标:
- 定义 `courseVariants`
- 定义 `assignmentMode`
- 定义 session 绑定 `variantId`
- 明确恢复、结果、launch 必须带上 `variantId`
### 第二期:前后端最小闭环
目标:
- 支持 `manual`
- 支持 `random`
- 准备页可展示赛道选择或随机结果
- launch 能消费最终绑定结果
### 第三期:运营扩展
目标:
- 接后台编排
- 增加 `server-assigned`
- 扩展更多分配模式
- 做更完整的审计、排行榜和统计
---
## 8. 六层检查在多赛道能力中的应用
后续只要多赛道相关配置或契约有变更,建议继续执行当前约定的六层检查:
1. 文档
2. 配置源
3. 解析层
4. 编译层
5. 消费层
6. 发布与联调层
具体到多赛道能力,检查点通常包括:
- 文档是否同步 `assignmentMode / variants / variantId`
- 配置源是否新增或调整 variant 结构
- 解析层是否能读取多赛道结构
- 编译层是否能生成最终绑定后的 runtime profile
- 地图、结果页、恢复链是否都消费了 `variantId`
- launch / release / manifest 是否和最终 variant 绑定一致
---
## 9. 当前建议结论
当前阶段,建议把“多 KML / 多赛道”先当成**平台能力设计**,而不是页面功能。
当前最重要的不是先做某个选择 UI而是先定住以下 4 个事实:
1. 一个活动可以有多个 variants
2. 一个 session 只能绑定一个 `variantId`
3. 最终绑定以后端 session 为准
4. 恢复、结果、ongoing、历史结果都必须能追溯该 `variantId`
---
## 10. 一句话总结
**多赛道能力建议固定采用“资源层、活动编排层、会话绑定层、客户端呈现层、后台运营层”五层模型,先把 `variantId` 做成 session 级事实,再去实现准备页手选、随机分配和后台指定等具体交互。**