RankHub
各游戏

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)。

身份字段(建档用)

字段类型必填说明示例
playerIdstring ≤128是存档里的玩家 id(原生 userId)"7c1f0a94e2b34d58"
  • 缺失 ⇒ 400(文案见写入格式 §4);服务端只落库;
  • player.name 必填(展示名),属于下面的统一字段;
  • 建档后 syncCapable 必然为 false(没有可用的同步凭据)。

统一字段(player)

字段类型说明
namestring | null昵称(原生 username;入库时已剥掉 <>& 与控制字符),建档必填(可来自原生 username)
ratingnumber | null总评 RKS,读 total_rks 列。这一列的来源会变:从存档导入时是存档原值,推过成绩之后被服务端重算值覆盖 —— 要分辨「我算的」与「存档里写的」,看 bests 的 totals

原生字段(player.native)

字段类型说明
playerIdstring存档玩家 id(与身份字段同源)
avatarIdstring | null名片头像 id(来自 rizcard.avatar_id)
b40Modestring | null桶模式:ah5_b35(AH5 + Best 35)或 rks_top40(元数据不全,退化为单一 Top 40)
scoreCountnumber | null档案里有多少条成绩

名片的背景 / 版式 / 两行签名与头像相对坐标不在 wire 上,只留在档案存储里。

Score 格式

成绩键与比较值

项值
成绩键 keyFieldssongId + difficulty(原生 track_id + difficulty;wire 上 trackId 就是 songId)
比较字段 compareFieldscore(本次得分,无 tie-break)
单曲评分字段 ratingFieldrating(原生列 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 那类「比达成率」的游戏的关键差异。

统一字段

字段类型说明
scoreIdstring成绩行 id
songIdstring曲目资源 id(= trackId)
songNamestring | null曲名(原生存档不带,靠曲库补)
difficultystring | nullEZ / HD / IN / AT / SP
achievementsnumber | null达成率 complete_rate,量纲 0~120(百分数,不是 0~100)
scorenumber | null本次得分;满分是 1,000,000 + 100 × 完美命中数,可以 > 1,000,000
ratingnumber | null单曲 rks;元数据缺失时为 null
fcstring | null全连时为 "fc",否则 null
nativeobject | null原生字段,见下表

恒为 null(原生没有或无映射):type、levelIndex、level、rank、dxScore、dxStar、fs、playTime。

原生字段(score.native)

字段类型说明
artiststring | null曲师
constantnumber | null谱面定数 C(曲库给,实测 1.0 ~ 15.2)
clearedboolean | null是否通关
maxHitnumber | null该谱面的 max Hit(曲库给)
rizHitnumber | nullRiztime 时段的总 Hit 数(曲库给;缺字段时用 (满分 − 1,000,000)/100 兜底)
metadataMissingboolean | null曲库缺定数/命中数时为 true(该条不进 AH5,也不参与精确分桶)

仅 bests 的 items 多两个字段

GET .../bests 返回的每个 item 在 native 里额外带 sourceRank(在最佳序列里的位次)与 ahStatus(confirmed / compatible / none,AH 判定状态,派生值);GET .../scores 的 items 没有这两个键。

评分语义与量纲

单曲 rks(社区口径):单曲rks = hitrks + accrks + rizrks

分项含义公式 / 取值
rizrksRiztime 时段奖励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 渲染,不要按数组下标猜。

keylabel成员规则totalsKeys
ah5AH5可确认 All Perfect 的谱面里,按单曲 rks 降序取最多 5 首rks、officialTotalRks
best35Best 35其余谱面按单曲 rks 降序取前 35 首rks、officialTotalRks
top40Top 40退化单桶:曲库元数据不全时不再拆 AH5,直接按 rks 取前 40rks、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 键类型换算
userIdstring,必填playerId
usernamestring,必填name
totalRksnumber 0~1000rating(只是提示,服务端仍以落库汇总为准)
rizcard / levelsRks / myBest—忽略(名片不进统一字段;成绩逐条推)

成绩:原生 myBest 的一行。

native 键类型换算
trackAssetIdstring,必填trackId + songId
difficultyClassNameEZ/HD/IN/AT/SP,必填(大小写自动归一)difficulty
score整数 0~100000000,必填score(比较值)
completeRatenumber 0~100accuracy 与 achievements(同一个值)
isFullCombo布尔fullCombo;为 true 时同时给 fc: "fc"
isClear布尔cleared
rksnumber 0~100rating(可选;不给不代算)
  • ❗ 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
        }
      }
    ]
  }'

消费者注意事项

  1. 桶数量不是契约:可能 2 个(ah5 + best35)、也可能 1 个(top40)。按 key 分支渲染,未知 key 原样展示。
  2. achievements 是 0~120,不是 0~100 —— 达成率可以超过 100%,跨游戏归一必须先按游戏分支。
  3. score 可以大于 1,000,000:满分是 1,000,000 + 100 × 完美命中数,把 score / 1e6 当百分比是错的。
  4. totals 有两个总评:rks(服务端重算)与 officialTotalRks(存档里写的上游值,可能为 null)。 要展示「官方值」用后者,要排序用前者;档案的 player.rating 读 total_rks 列,导入时是存档原值、推成绩后被重算值覆盖。
  5. rks 可能为 null:曲库元数据缺失时没有单曲评分,该条不进 AH5,也不参与精确分桶。
  6. native.ahStatus / native.sourceRank 只在 bests 的 items 里,/scores 的 items 没有。
  7. 没有历史表:当前行就是唯一真值,拿不到「这条成绩以前是什么」。
  8. 公式是社区口径:官方无任何 RKS 文档,数值差异无法用官方口径裁决。
  9. 推成绩时:rating 就是单曲 rks(服务端不代算);accuracy / achievements 落到 completeRate; fc / fullCombo 落到 full_combo;constant / maxHit / rizHit 原样入库。

相关

本页内容

官方交流群二维码官方交流群问题反馈 · 版本资讯 · 成绩交流群号 1073434398