RankHub

API 目前处于 Early Preview 阶段, 可能存在诸多不完善与错误之处,欢迎加群交流反馈:加入官方交流群(1073434398)

游戏数据格式总览

RankHub 的 10 个游戏共用一套 profile / score / bucket 形状:统一字段、空值语义、量纲边界,以及每个游戏的 native 字段去哪看。

本页是字段级总览:10 个游戏共用的 profile / score / bucket 形状、空值语义与量纲边界。 三层概念(各回答什么问题、为什么不能跨游戏比较)见概念; 每个游戏 native 里有什么、最佳桶怎么切,见各游戏格式页。

2. 统一 Profile 格式

一条 profile = 一个 RankHub 用户在一个游戏上的一张档案,主键是对外的 profileId(uuid), 不是游戏原生标识。

{
  "profileId": "8d1f4a0e-6c2b-4a1e-9d3f-2b7c5e9a0f11",
  "game": "maimai",
  "player": {
    "name": "Player",
    "rating": 15234,
    "native": { "userId": 10000001, "friendCode": "1234567890123", "courseRank": 0, "classRank": 0, "star": 12 }
  },
  "isPublic": true,
  "origin": "app",
  "createdByClientId": "cli_7Q2…",
  "syncCapable": false,
  "lastSyncedAt": null,
  "createdAt": "2026-10-21T18:40:00Z",
  "updatedAt": "2026-10-21T18:40:00Z"
}

Prop

Type

身份字段不归一:每个游戏建档时填的身份字段不同(maimai 的 friendCode/userId、 arcaea 的 arcaeaId、osu 的 osuUserId…),见各游戏格式页的「身份字段」表, 或 GET /v1/games/{game}/format 的 profile.identityFields。

3. 统一 Score 格式

一条成绩 = 一张谱面 + 一次(或最佳一次)游玩结果。字段全可空是刻意的: 不同游戏只填得上其中一部分,游戏特异的部分一律留在 native。

{
  "scoreId": "b1f0c2d3-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "songId": "1234",
  "songName": "Example Song",
  "type": "dx",
  "difficulty": null,
  "levelIndex": 3,
  "level": "13+",
  "achievements": 100.5125,
  "score": null,
  "rating": 320,
  "rank": "sss",
  "dxScore": 2500,
  "dxStar": 5,
  "fc": "ap",
  "fs": "fs",
  "playTime": "2026-10-01T12:00:00Z",
  "native": { "level_index": 3, "dx_score": 2500, "…": "…" }
}

Prop

Type

null 不是 0

null 的语义是「这个游戏没有这个概念」,不是 0、不是空串。 跨游戏渲染只用统一字段;游戏特异字段去读 native,不要从 native 反推统一字段。

4. 统一 Bucket(最佳成绩)格式

所有游戏的最佳成绩是一个端点、一个形状:

{
  "game": "maimai",
  "computedAt": "2026-10-24T02:10:00Z",
  "totals": { "total": 15234, "latest": 7234, "archive": 8000 },
  "buckets": [
    { "key": "latest", "label": "当期", "total": 7234, "items": [ /* 同 scores 的 items */ ] },
    { "key": "archive", "label": "往期", "total": 8000, "items": [ /* … */ ] }
  ]
}

Prop

Type

桶的成员怎么选、数量几个,全部由服务端决定:有的按版本切(maimai)、有的按评级 (phigros 的 ϕ)、有的按状态(rizline 的 AH)、有的直接来自上游分组(chunithm/orzmic)。 具体规则见各游戏格式页的「最佳成绩桶」表。

5. 跨游戏边界与写入

跨游戏只归一形状,不归数值语义(rating 同名不同义、difficulty 取值随游戏、只能按服务端排序、 没有跨游戏总榜)—— 这四条见概念 · 跨游戏归一化的边界。

写入只有两种形状(RankHub 格式 / 游戏原生格式 native),请求体、每游戏必填项、响应与 400/422/428 语义统一见写入格式;快速选择见 怎么传数据(速查)。

6. GET /v1/games/{game}/format

新增的格式端点:返回该游戏机器可读的 profile/score 格式,用来替代"猜 native 里有什么"。

curl -sS https://api.rankhub.cc/v1/games/maimai/format \
  -H "Authorization: Bearer $ACCESS_TOKEN"
{
  "code": "common.ok",
  "message": "ok",
  "data": {
    "game": "maimai",
    "rating": { "name": "DX Rating", "unit": "整数", "range": null, "description": "…" },
    "profile": {
      "identityFields": [
        { "name": "friendCode", "type": "string", "nullable": false, "required": true,
          "unit": null, "range": null, "example": "123456789012345", "description": "好友码(15 位)" }
      ],
      "fields": [
        { "name": "name", "type": "string", "nullable": true, "unit": null, "range": null, "description": "玩家显示名" },
        { "name": "rating", "type": "number", "nullable": true, "unit": "rating", "range": null, "description": "DX Rating" }
      ],
      "nativeFields": [ { "name": "courseRank", "type": "number", "…": "…" } ]
    },
    "score": {
      "keyFields": ["songId", "type", "levelIndex"],
      "compareField": "achievements",
      "ratingField": null,
      "fields": [ /* 该游戏 v1 成绩会填的统一字段 */ ],
      "nativeFields": [ { "name": "level_index", "type": "number", "…": "…" } ],
      "buckets": [
        { "key": "latest", "label": "当期", "rule": "谱面版本 ≥ 最新版本的谱面,按单曲 rating 取前 15", "totalsKeys": ["total", "latest", "archive"] },
        { "key": "archive", "label": "往期", "rule": "…", "totalsKeys": ["total", "latest", "archive"] }
      ]
    },
    "docsSlug": "maimai",
    "formatVersion": "1",
    "notes": ["…"]
  },
  "requestId": "…"
}
返回字段说明
rating原生评分体系名 / 单位 / 典型区间 / 一句话口径
profile.identityFields建档身份字段(required + example)
profile.fieldsplayer 上的统一字段(name、rating)
profile.nativeFieldsplayer.native 内的字段(原名)
score.keyFields成绩唯一键(统一字段名)
score.compareField"只升不降"比较字段
score.ratingField单曲评分字段;null = 服务端算或只在 native 里
score.fields该游戏成绩会填的统一字段
score.nativeFieldsscore.native 内的字段
score.buckets桶 key/label/成员规则/totals 键
formatVersion本格式描述的版本(不是游戏版本;破坏性变更 +1)
notes消费者必须知道的坑

7. 10 个游戏的格式索引

游戏原生评分体系量纲桶规则(现行)格式页
maimaiDX Rating整数(floor)新曲 15 + 旧曲 35(版本切桶)maimai
chunithmRating小数 2 位(向下截断)BEST30 + NEW20(50 张平均)chunithm
arcaeaPotential(PTT)小数 3 位v7.0 起 (B50+B10)/60arcaea
phigrosrks小数 2 位(四舍五入)(P1+P2+P3+b27)/30phigros
milthmReality小数前 20 平均(分母恒 20)milthm
notanoteNrk小数Best31 加权平均notanote
musedash无官方 rating(社区 RL)小数社区:递减加权(Σ(v×0.8ᵏ)/5)musedash
rizlineRKS小数(ΣAP5+ΣB35)/40(可退化为 top40)rizline
osupp浮点(无上限)Σpp·0.95ⁿ(Best 100)+ bonusosu
orzmicRating小数前 N 平均(社区口径)orzmic

表中"量纲/桶规则"是摘要;精确公式、边界、版本节点以各游戏格式页为准。 官方公式公开度不同(milthm/notanote/osu 有官方文档;musedash 无官方 rating;其余为社区口径), 各页会逐条标注证据等级。

8. 相关

从 LXNS(落雪咖啡屋)迁移? maimai / chunithm 两页各有一节「从 LXNS 迁移」: 认证、接口、Player/Score 字段、Best 桶与写入语义的逐项对照。

本页内容

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