API 目前处于 Early Preview 阶段, 可能存在诸多不完善与错误之处,欢迎加群交流反馈:加入官方交流群(1073434398)
Rizline
RIZLINE 的 RKS 单曲三分项、AH5 + Best 35 桶(可能退化为 Top 40),以及 profile / score 的统一字段与原生字段(native)。
RIZLINE 的原生评分叫 RKS(Ranking Score):单曲值是 hitrks + accrks + rizrks 三项之和,
总评是 40 项的算术平均。官方从未公开过任何 RKS 公式文档,本页所有公式均为社区口径。
机器可读版本
本页字段表与服务端 GET /v1/games/rizline/format 一一对应(profile.identityFields /
profile.fields / profile.nativeFields、score.keyFields / score.compareField /
score.ratingField / score.fields / score.nativeFields / score.buckets)。文档可能滞后,以端点返回为准。
Profile 格式
一张 RIZLINE 档案 = 一个 RankHub 用户在 RIZLINE 上的一张卡。对外主键是 profileId(uuid)。
身份字段(建档用)
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
playerId | string ≤128 | 是 | 存档里的玩家 id(原生 userId) | "7c1f0a94e2b34d58" |
- 缺失 ⇒
400(文案见写入格式 §4);服务端只落库; player.name必填(展示名),属于下面的统一字段;- 建档后
syncCapable必然为false(没有可用的同步凭据)。
统一字段(player)
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | null | 昵称(原生 username;入库时已剥掉 <>& 与控制字符),建档必填(可来自原生 username) |
rating | number | null | 总评 RKS,读 total_rks 列。这一列的来源会变:从存档导入时是存档原值,推过成绩之后被服务端重算值覆盖 —— 要分辨「我算的」与「存档里写的」,看 bests 的 totals |
原生字段(player.native)
| 字段 | 类型 | 说明 |
|---|---|---|
playerId | string | 存档玩家 id(与身份字段同源) |
avatarId | string | null | 名片头像 id(来自 rizcard.avatar_id) |
b40Mode | string | null | 桶模式:ah5_b35(AH5 + Best 35)或 rks_top40(元数据不全,退化为单一 Top 40) |
scoreCount | number | null | 档案里有多少条成绩 |
名片的背景 / 版式 / 两行签名与头像相对坐标不在 wire 上,只留在档案存储里。
Score 格式
成绩键与比较值
| 项 | 值 |
|---|---|
成绩键 keyFields | songId + difficulty(原生 track_id + difficulty;wire 上 trackId 就是 songId) |
比较字段 compareField | score(本次得分,无 tie-break) |
单曲评分字段 ratingField | rating(原生列 rks) |
| tie-break | 无(纯 score 比较) |
- 曲目 id 是资源 id(形如
track.xxx.N),服务端做track.前缀与 URL 解码的多变体匹配; difficulty固定 5 档:EZ/HD/IN/AT/SP;wire 上songId就是trackId;- 同曲不同难度是不同成绩,可同时进桶(AH5 与 Best 35 都按单曲
rks竞争,不区分难度)。
比较值只看 score,不看 rks
「只升不降」比的是 score(原始得分)。所以「得分更高但达成率更低」的成绩会被接受,
而 rks 可能反而下降 —— 这是 RIZLINE 与 maimai 那类「比达成率」的游戏的关键差异。
统一字段
| 字段 | 类型 | 说明 |
|---|---|---|
scoreId | string | 成绩行 id |
songId | string | 曲目资源 id(= trackId) |
songName | string | null | 曲名(原生存档不带,靠曲库补) |
difficulty | string | null | EZ / HD / IN / AT / SP |
achievements | number | null | 达成率 complete_rate,量纲 0~120(百分数,不是 0~100) |
score | number | null | 本次得分;满分是 1,000,000 + 100 × 完美命中数,可以 > 1,000,000 |
rating | number | null | 单曲 rks;元数据缺失时为 null |
fc | string | null | 全连时为 "fc",否则 null |
native | object | null | 原生字段,见下表 |
恒为 null(原生没有或无映射):type、levelIndex、level、rank、dxScore、dxStar、fs、playTime。
原生字段(score.native)
| 字段 | 类型 | 说明 |
|---|---|---|
artist | string | null | 曲师 |
constant | number | null | 谱面定数 C(曲库给,实测 1.0 ~ 15.2) |
cleared | boolean | null | 是否通关 |
maxHit | number | null | 该谱面的 max Hit(曲库给) |
rizHit | number | null | Riztime 时段的总 Hit 数(曲库给;缺字段时用 (满分 − 1,000,000)/100 兜底) |
metadataMissing | boolean | null | 曲库缺定数/命中数时为 true(该条不进 AH5,也不参与精确分桶) |
仅 bests 的 items 多两个字段
GET .../bests 返回的每个 item 在 native 里额外带 sourceRank(在最佳序列里的位次)与
ahStatus(confirmed / compatible / none,AH 判定状态,派生值);GET .../scores 的 items 没有这两个键。
评分语义与量纲
单曲 rks(社区口径):单曲rks = hitrks + accrks + rizrks
| 分项 | 含义 | 公式 / 取值 |
|---|---|---|
rizrks | Riztime 时段奖励 | C × min(mP, hH) / hH;mP 是 Riztime 内的「非 Early/Late」命中数,由分数反推 |
accrks | 达成率奖励(阶梯查表,不插值) | 按 completeRate 左闭取值:≥120 ⇒ 10.5、≥118 ⇒ 10.2、≥116 ⇒ 9.9、≥114 ⇒ 9.6、≥112 ⇒ 9.3、≥110 ⇒ 9.0、≥105 ⇒ 8.25、≥100 ⇒ 7.5、≥95 ⇒ 6.75、≥90 ⇒ 6.0、≥80 ⇒ 4.5、≥70 ⇒ 3.0、≥60 ⇒ 1.5、<60 ⇒ 0 |
hitrks | 命中奖励 | Hit ≤ mHit/2 ⇒ 0;否则 10 × C × (2×Hit − mHit) / mHit(全 hit 时 10C) |
- 理论上限:
单曲rks_max = 11C + 10.5(C = 13.4时约 157.9,C = 15.2时约 177.7); - 舍入:
hH向上取整、mP四舍五入;单曲 rks 与总 RKS 不做位舍入,比较时社区用 float32 容差(< 0.001)。
总评(社区口径):总RKS = ( Σ(AP5 的 5 首) + Σ(B35 的 35 首) ) / 40
「AP5」对应协议里的桶
ah5:只有能确认 All Perfect 的谱面才进这个桶,其余进best35。
- 先按单曲 rks 降序;从「已确认 All Perfect」的谱面里优先取最多 5 首构成 AP5;
- 其余谱面按 rks 降序取前 35 首构成 B35;分母恒为 40,不足 40 条时按 0 补齐(不是除以条数);
- 边界并列时社区工具会继续并入(桶可超 5/35 条,分母仍是 40),本平台硬切 5/35;
- 元数据缺失时退化为单一「RKS 前 40」桶,分母仍是 40。
量纲没有闭环
社区上限是 11C + 10.5(C 较大时远超 100),而写入守卫的 bounds.rating 写的是 [0, 100]。
两者不一致,属已知缺口:bounds 是硬上界、不是语义区间,但真实高值可能被拒。
最佳成绩桶
GET /v1/games/rizline/profiles/{profileId}/bests 返回 1 个或 2 个桶,由档案的 b40Mode 决定 ——
桶数量不是契约,按 key 渲染,不要按数组下标猜。
key | label | 成员规则 | totalsKeys |
|---|---|---|---|
ah5 | AH5 | 可确认 All Perfect 的谱面里,按单曲 rks 降序取最多 5 首 | rks、officialTotalRks |
best35 | Best 35 | 其余谱面按单曲 rks 降序取前 35 首 | rks、officialTotalRks |
top40 | Top 40 | 退化单桶:曲库元数据不全时不再拆 AH5,直接按 rks 取前 40 | rks、officialTotalRks |
totals.rks:服务端重算的总 RKS(四舍五入 3 位,ah5_b35模式下分母恒 40);totals.officialTotalRks:存档里上游自己写的totalRks(可能为null)—— 一个是「我算的」,一个是「存档里写的」,不要混用;buckets[].total:桶内各条rating的和,不是总 RKS。
写入(第三方)
请求体形状、idempotencyKey、批量上限、428/403 等通用规则见写入格式;
这里只写 RIZLINE 真正特殊的部分。
两种写形状
- RankHub 格式:直接给统一字段(
songId/difficulty/score/rating/accuracy…); - 游戏原生格式(
native):player.native/scores[].native里放原生形状,服务端按唯一一套换算归一, 与顶层同名字段同时出现时native优先;不合法 ⇒400 common.invalidArgument(message指明键)。
本游戏的写入规则
- 必给:
songId(或等价的trackId)+difficulty+score+rating+accuracy。score是这里唯一会硬失败的数值字段:缺失/NaN ⇒400 Rizline score is invalid(按「只升不降」判断,没有比较值就没法写)。 difficulty认名字也认下标:EZ/HD/IN/AT/SP,或数字0=EZ 1=HD 2=IN 3=AT 4=SP。- 比较值是
score,不是achievements(达成率 0~120)也不是rating; 所以「达成率更高但得分更低」的提交会被忽略。 - 谁算分:单曲
rating(rks)由调用方给(maimai / arcaea 之外的游戏都是调用方给,只有那两者服务端算); 总评 RKS 由服务端重算并回写档案。 - 唯一键:
songId+difficulty(原生track_id+difficulty)。可选兜底:constant/maxHit/rizHit在曲库缺失时参与分桶判定;fullCombo(也认fc的存在性)、cleared、artist只影响展示。 - 通用上界(写入守卫开启时生效,默认
off):score/achievements越界400,rating/constant/accuracy越界或playTime晚于现在 1 小时422。
原生数据(native)
建档:存档根对象里能取到身份、名字与总分提示。
native 键 | 类型 | 换算 |
|---|---|---|
userId | string,必填 | playerId |
username | string,必填 | name |
totalRks | number 0~1000 | rating(只是提示,服务端仍以落库汇总为准) |
rizcard / levelsRks / myBest | — | 忽略(名片不进统一字段;成绩逐条推) |
成绩:原生 myBest 的一行。
native 键 | 类型 | 换算 |
|---|---|---|
trackAssetId | string,必填 | trackId + songId |
difficultyClassName | EZ/HD/IN/AT/SP,必填(大小写自动归一) | difficulty |
score | 整数 0~100000000,必填 | score(比较值) |
completeRate | number 0~100 | accuracy 与 achievements(同一个值) |
isFullCombo | 布尔 | fullCombo;为 true 时同时给 fc: "fc" |
isClear | 布尔 | cleared |
rks | number 0~100 | rating(可选;不给不代算) |
- ❗
completeRate只收 0~100:超过 100 直接400,需要 100 以上的达成率请改用顶层accuracy(允许 0~120); - 可写字段(
native,除身份与唯一键外全部):profile 侧username(→name)、avatar_id、b40_mode、score_count、total_rks(建档或PATCH /v1/games/rizline/profiles/{profileId}的native); score 侧score/completeRate/isFullCombo/isClear/rks。 - 不可改:身份
playerId(原生userId)——PATCH的native里给了不同的userId⇒400,message=native.playerId cannot be changed (identity field);成绩唯一键trackAssetId+difficultyClassName顶层与 native 都给时必须一致,不一致以 native 为准(会写到另一张谱面上)。
示例(示意数据) —— 一条推成绩请求(原生格式):
curl -sS -X POST https://api.rankhub.cc/v1/games/rizline/profiles/$PROFILE_ID/scores \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scores": [
{
"native": {
"trackAssetId": "track.10023.2",
"difficultyClassName": "in",
"score": 1021500,
"completeRate": 98.5,
"isFullCombo": true,
"isClear": true,
"rks": 21.86
}
}
]
}'消费者注意事项
- 桶数量不是契约:可能 2 个(
ah5+best35)、也可能 1 个(top40)。按key分支渲染,未知key原样展示。 achievements是 0~120,不是 0~100 —— 达成率可以超过 100%,跨游戏归一必须先按游戏分支。score可以大于 1,000,000:满分是1,000,000 + 100 × 完美命中数,把score / 1e6当百分比是错的。totals有两个总评:rks(服务端重算)与officialTotalRks(存档里写的上游值,可能为null)。 要展示「官方值」用后者,要排序用前者;档案的player.rating读total_rks列,导入时是存档原值、推成绩后被重算值覆盖。rks可能为null:曲库元数据缺失时没有单曲评分,该条不进 AH5,也不参与精确分桶。native.ahStatus/native.sourceRank只在 bests 的 items 里,/scores的 items 没有。- 没有历史表:当前行就是唯一真值,拿不到「这条成绩以前是什么」。
- 公式是社区口径:官方无任何 RKS 文档,数值差异无法用官方口径裁决。
- 推成绩时:
rating就是单曲rks(服务端不代算);accuracy/achievements落到completeRate;fc/fullCombo落到full_combo;constant/maxHit/rizHit原样入库。