5.7 KiB
5.7 KiB
多赛道 Variant 前后端最小契约
文档版本:v0.1 最后更新:2026-04-02 18:33:00
本文档用于定义“多 KML / 多赛道 variant”第一阶段联调所需的最小前后端契约。
目标:
- 先定最小可联调字段,不一开始追求大而全
- 保证准备页、launch、地图、恢复、结果页能围绕同一
variantId工作 - 避免前端从页面交互反推后端字段
说明:
- 本文档只定义最小契约建议
- 不等同于最终后台配置模型
- 不等同于最终数据库模型
- 本文档优先服务前后端第一阶段联调
1. 最小联调目标
第一阶段只解决下面 4 件事:
- 一个活动可声明多个
variant - 准备页能知道当前活动是否允许手选 / 随机 / 后端指定
launch能明确返回本局最终绑定的variantIdresult / ongoing / recovery能持续追溯同一个variantId
一句话目标:
让 variantId 成为贯穿一局的稳定事实。
2. 契约原则
2.1 session 绑定优先
- 前端可参与选择
- 最终绑定以后端 session 为准
2.2 launch 是最终真相
- 前端准备页即便做了手选或随机请求
- 地图页真正消费的仍应是
launch返回的最终绑定结果
2.3 恢复不重新分配
- 恢复链只恢复既有
variantId - 不重新随机
- 不重新提示选择
2.4 结果必须可追溯
- 结果页
- ongoing session
- 历史成绩
都建议能反查:
variantId- 可选
variantName
3. 活动级最小字段建议
建议活动可玩信息中增加一个最小赛道编排块,例如在 play 返回里体现:
3.1 assignmentMode
含义:
- 当前活动的赛道分配模式
建议最小取值:
manualrandomserver-assigned
3.2 courseVariants
含义:
- 当前活动可用赛道版本列表
建议最小字段:
idnamedescriptionrouteCodeselectable
备注:
- 第一阶段不一定要在
play里返回所有复杂资源 - 只要足够准备页展示选择即可
推荐最小形态示意:
{
"play": {
"assignmentMode": "manual",
"courseVariants": [
{
"id": "variant_a",
"name": "A 线",
"description": "适合首次体验",
"routeCode": "A",
"selectable": true
},
{
"id": "variant_b",
"name": "B 线",
"description": "稍长路线",
"routeCode": "B",
"selectable": true
}
]
}
}
4. launch 最小字段建议
launch 必须承担“最终绑定本局赛道”的责任。
建议在现有 launch 返回中增加一个明确的 variant 绑定块。
4.1 建议字段
launch.variant.idlaunch.variant.namelaunch.variant.routeCodelaunch.variant.assignmentMode
如需保守,也可挂到 business 下,但建议语义上单独成块,避免和 release/session 混淆。
4.2 前端输入建议
如果是手选模式,前端建议向 launch 传:
variantId
如果是随机模式,前端可以:
- 不传,由后端分配
- 或显式传一个
assign=random请求意图
4.3 输出约束
无论前端是否传入 variantId,launch 返回都必须给出最终绑定结果。
因为地图页只应消费:
- 最终
variantId - 对应 manifest / config
不应再依赖准备页上的临时选择状态。
推荐最小形态示意:
{
"launch": {
"variant": {
"id": "variant_b",
"name": "B 线",
"routeCode": "B",
"assignmentMode": "manual"
},
"resolvedRelease": {
"releaseId": "rel_xxx",
"manifestUrl": "https://..."
},
"business": {
"sessionId": "ses_xxx",
"sessionToken": "..."
}
}
}
5. session / result 最小字段建议
5.1 session 摘要
建议在以下位置都可见:
ongoingSessionrecentSessionsession detail
最小补充:
variantIdvariantNamerouteCode
5.2 result
建议 GET /sessions/{sessionPublicID}/result 至少返回:
result.session.variantIdresult.session.variantNameresult.session.routeCode
这样前端单局结果页和历史结果页都能统一展示。
6. 前端第一阶段落点
前端第一阶段建议只做下面几件事:
6.1 准备页
- 读取
assignmentMode - 读取
courseVariants[] - 在
manual下展示可选赛道列表 - 在
random下展示“随机分配” - 在
server-assigned下只展示结果
6.2 launch 适配层
- 将
launch.variant.*写入GameLaunchEnvelope - 将
variantId一起进入地图页和恢复快照
6.3 结果与历史页
- 显示本局
variantName / routeCode
6.4 故障恢复
- 快照中补
variantId - 恢复时继续使用既有
variantId
7. 第一阶段后端落点
后端第一阶段建议只做下面几件事:
7.1 play
- 返回
assignmentMode - 返回
courseVariants[]
7.2 launch
- 接收可选
variantId - 返回最终绑定后的
variant信息
7.3 session / result
- 在 session 摘要和结果里带出
variantId
这样就足够完成第一阶段联调。
8. 和现有体系的关系
这份最小契约不替代现有六层检查,后续一旦开始实现,仍建议按六层检查推进:
- 文档
- 配置源
- 解析层
- 编译层
- 消费层
- 发布与联调层
特别是:
- 配置层后续如果引入
courseVariants - 解析层如果开始读取多 variant 结构
- 编译层如果开始按
variantId产出 runtime profile
这三层都不能跳。
9. 一句话结论
多赛道第一阶段联调只需要先定住 assignmentMode、courseVariants[]、launch.variant.*、session/result.variant* 这四组最小字段,让 variantId 成为贯穿一局的稳定事实。