API 目前处于 Early Preview 阶段, 可能存在诸多不完善与错误之处,欢迎加群交流反馈:加入官方交流群(1073434398)
MuseDash
Muse Dash 官方没有 rating 系统:本页说明社区 RL 口径、Best 30 桶规则,以及 profile / score 的统一字段与原生字段(native)。
Muse Dash 游戏内没有 rating 系统。 只有单局评级(金S / 银S / S / A / B / C / D,按准确率分档)
与单局分数(0~1,000,000 量级),没有跨曲汇总的「rating」。
本页的 rating / RL(Rating Level)全部是社区口径,不是官方数据,请勿对外表述为「官方 rating」。
机器可读版本
本页字段表与服务端 GET /v1/games/musedash/format 一一对应(profile.identityFields /
profile.fields / profile.nativeFields、score.keyFields / score.compareField /
score.ratingField / score.fields / score.nativeFields / score.buckets)。文档可能滞后,以端点返回为准。
Profile 格式
一张 Muse Dash 档案 = 一个 RankHub 用户在 Muse Dash 上的一张卡。对外主键是 profileId(uuid)。
身份字段(建档用)
| 字段 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
musedashUid | string | 是 | 存档信封里的玩家匿名 id。校验是 [0-9A-Za-z_-]、长度 1~32;真实存档值是 32 位十六进制 | "0a1b2c3d4e5f60718293a4b5c6d7e8f9" |
- 缺失/形状不合法 ⇒
400(文案见写入格式 §4);建档只落库。
统一字段(player)
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | null | 玩家名(原生 player_name),建档必填(可来自原生 Account.PlayerName) |
rating | number | null | 总评 RL(社区口径),取档案汇总里服务端算好的值,四舍五入到 3 位小数 |
rating只是排序键:建档时传的rating只是提示,返回的以服务端按成绩重算的值为准(没有成绩就是0);name也可以由原生Account.PlayerName提供(见原生数据(native))。
这个 rating 不是官方值
player.rating 是服务端按本平台口径重算的 Best 30 平均(见下文),
与社区查分站的 RL 也不是同一套汇总规则。把它当「本平台的排序键」用,不要当官方评分引用。
原生字段(player.native)
| 字段 | 类型 | 说明 |
|---|---|---|
uid | string | null | 32 位十六进制的玩家匿名 id(与身份字段同源) |
level | number | null | 等级。按 1 + floor(Exp / 100) 推导,官方公式未公开 |
bestCount | number | null | Best 30 里实际有几条 |
fullComboCount | number | null | FC 谱面数 |
没透出的原生字段:exp、language(在存档 Account 里,落库但不在 wire 上)。
Score 格式
成绩键与比较值
| 项 | 值 |
|---|---|
成绩键 keyFields | scoreId(wire 顶层没有能重建存储键的字段,见下) |
| 存储键(原生) | uid,形如 "{songUid}_{difficulty}"(如 0-28_3),落在 score.native.uid |
比较字段 compareField | score(原始单局得分) |
单曲评分字段 ratingField | rating(原生列 performance,社区单曲 RL) |
| tie-break | 无(单个比较值) |
- 存储键是
uid,不是songId:一条uid已经包含曲目与难度(如0-28_3), wire 顶层没有它(只在score.native.uid),所以端点keyFields只能退到scoreId; songUid自身含连字符(如43-53),拆键时不能简单split('_');- wire 上
songId是songUid(不含难度后缀),同曲不同难度是不同成绩,可同时进桶。
统一字段
| 字段 | 类型 | 说明 |
|---|---|---|
scoreId | string | 成绩行 id |
songId | string | 曲目 uid(原生 song_uid,如 0-28) |
songName | null | 恒 null:原生存档不带曲名 |
difficulty | string | null | 难度号字符串:"1" ~ "5" |
levelIndex | number | null | 难度号数字:1 ~ 5 |
level | string | null | 曲库给的显示等级,是字符串,可能是 "?" / "¿" / "a2" 这类占位符 |
achievements | number | null | 准确率,量纲 0~1 |
score | number | null | 单局得分(0 ~ 1,000,000 量级) |
rating | number | null | 单曲 performance(社区 RL) |
fc | string | null | 全连时为 "fc",否则 null |
native | object | null | 原生字段,见下表 |
恒为 null(原生没有或无映射):type、rank、dxScore、dxStar、fs、playTime。
难度号与难度名:1 萌新 / 2 高手 / 3 大触 / 4 隐藏 / 5 弹幕。
注意社区曲库里 difficulty 是 0-indexed(0~4),服务端归一入曲库时已经 +1,两者不要混用。
原生字段(score.native)
| 字段 | 类型 | 说明 |
|---|---|---|
uid | string | 成绩行 id:{songUid}_{difficulty}(成绩键) |
evaluate | number | null | 结算评级枚举。本服务注释到 0=D 1=C 2=B 3=A 4=S 5=银S;社区口径共 7 档(还缺「金S」) |
combo | number | null | 本次最大连击 |
clear | number | null | 通关标记(缺省 1);原生语义未公开 |
chartRl | number | null | 曲库给的相对难度 relative(diffdiff,不是官方定数);实测 1.03 ~ 12.5 |
failCount | number | null | 该谱面的失败次数(缺省 0) |
评分语义与量纲
单曲 performance(社区口径):
performance(acc, relative) =
1 , acc = 100
(f − f² + f⁴) × relative , 其它,f = acc / 100| 符号 | 含义 | 量纲 |
|---|---|---|
acc | 单局准确率 | 社区口径 0~100;本服务用 0~1(等价,f = acc/100) |
relative | 谱面「相对难度」(diffdiff) | 小数,实测 1.03 ~ 12.5;不是官方定数 |
| 结果 | 单曲 RL | 无量纲小数,随 relative 浮动 |
acc = 100 时 performance 恒为 1(与 relative 无关):performance 上限并不高,
单曲 RL 主要由玩家准确率决定,relative 只做难度缩放。
relative 是从排行榜数据反推的「等效等级」:按玩家间 accJudge 差值排难度序,再以「等级 10」为中心
按排名位置做正态插值,所以不能与游戏内显示的等级直接比较。另两条社区规则:
上线不足一周的曲子 relative 记 0(不参与 RL);使用加分角色/精灵的成绩被排除。
总评汇总 —— 两套口径,量级不同:
| 口径 | 公式 | 说明 |
|---|---|---|
| 社区 | RL = ( Σ vₖ × 0.8^(n−1−k) ) / 5 | 全谱面递减加权,分母恒为 5,无 top N 截断 |
| 本平台 | RL = ( Σ 前 30 条 performance ) / 30 | Best 30 算术平均,不足 30 条也除 30 |
同样一批成绩两者能差一个量级:只有 1 条 performance = 12 时,本平台 12/30 = 0.4、社区 12/5 = 2.4(6 倍)。
- 精度:两套公式都不做舍入;wire 上总评与桶合计四舍五入到 3 位小数。
- 上界的现实差距:写入守卫的
bounds.rating是[0, 1000],而实测社区 RL 值域在0 ~ 20附近 (头部约12.35)—— 上界宽松了 50 倍以上,不要把它当语义区间。
最佳成绩桶
GET /v1/games/musedash/profiles/{profileId}/bests 固定返回一个桶:
key | label | 成员规则 | totalsKeys |
|---|---|---|---|
best30 | Best 30 | 按谱面去重(uid = 曲目 + 难度,同曲不同难度可同时进桶)→ 排除曲库缺失(relative 不可得)的谱面 → performance 降序取前 30 | rl、bestCount |
totals.rl:总评(top30 之和 ÷ 30,四舍五入 3 位);totals.bestCount:桶里实际有几条;buckets[0].total:桶内各条rating的和,不是总评 RL(RL 是平均)。
写入(第三方)
请求体形状、idempotencyKey、批量上限、428/403 等通用规则见写入格式;
这里只写 Muse Dash 真正特殊的部分。
两种写形状
- RankHub 格式:直接给统一字段(
songId/difficulty/score/accuracy…); - 游戏原生格式(
native):player.native/scores[].native里放原生形状,服务端按唯一一套换算归一, 与顶层同名字段同时出现时native优先;不合法 ⇒400 common.invalidArgument(message指明键)。
本游戏的写入规则
- 必给:
songId+difficulty(缺失/非法直接400)+score+accuracy;rating缺失不报错(服务端会用曲库relative现算),但曲库查不到时算成0,所以真值请自己给。 accuracy收0~1或0~100:>1会被当成百分数自动除 100,落库统一成0~1。- 比较值是
score(原始得分),不是rating;同一uid只有分数更高才会覆盖。 - 谁算分:单曲
rating(performance)由调用方给(maimai / arcaea 之外的游戏都是调用方给, 只有那两者服务端算);不给时服务端按社区公式现算。总评 RL(Best 30 ÷ 30)由服务端重算, 与社区查分站的递减加权口径不同。 - 唯一键:
uid(={songUid}_{difficulty});同曲不同难度是两条成绩,可同时进桶。 - 可选但常用:
evaluate(0=D…5=银S,缺省0)、combo、cleared(false才写未通关)、fullCombo(落fc)、constant(曲库查不到时当relative参与算分)。playTime不读取。 - 通用上界(写入守卫开启时生效,默认
off):score/achievements越界400,rating/constant/accuracy越界或playTime晚于现在 1 小时422。
原生数据(native)
建档:原生对象里取身份与名字。
native 键 | 类型 | 换算 |
|---|---|---|
UserID | string,必填 | musedashUid |
Account | JSON 字符串或对象 | 取其中的 PlayerName → name;取不到时回落 UserID |
Achievement | — | 忽略(成绩逐条用 scores[].native 推) |
成绩:原生 highest 行是一条一条的。
native 键 | 类型 | 换算 |
|---|---|---|
uid | string,必填,形如 <songUid>_<1..5> | uid + songId(songUid)+ difficulty(1~5,数字) |
accuracy | number,必填,0~1 | accuracy(与统一字段同为 0~1 口径) |
score / combo / evaluate | 整数 0~100000000 | 同名统一字段 |
clear | 数字或布尔 | cleared(clear !== 0) |
- ❗
native.accuracy只收 0~1:超过1.000001直接400,不会帮你折算 (只有顶层accuracy才有>1 ⇒ /100的宽容); - 可写字段(
native,除身份与唯一键外全部):profile 侧Account.PlayerName(→name)、level、best_count、full_combo_count(建档或PATCH /v1/games/musedash/profiles/{profileId}的native); score 侧accuracy/score/combo/evaluate/clear。 - 不可改:身份
musedashUid(原生uid)——PATCH的native里给了不同的UserID⇒400,message=native.musedashUid cannot be changed (identity field);成绩唯一键uid顶层与 native 都给时必须一致,不一致以 native 为准(会写到另一张谱面上)。
示例(示意数据) —— 一条推成绩请求(原生格式):
curl -sS -X POST https://api.rankhub.cc/v1/games/musedash/profiles/$PROFILE_ID/scores \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scores": [
{
"native": { "uid": "0-28_3", "accuracy": 0.9842, "score": 302027, "combo": 612, "evaluate": 5, "clear": 1 },
"rating": 9.842
}
]
}'消费者注意事项
rating是社区口径,不是官方 rating:对外表述必须写清「社区 RL」。- 本平台总评与社区总评不是同一个数:本平台
Σ前30 / 30,社区递减加权Σ(v×0.8ᵏ) / 5; 直接对比会得到「差一个量级」的结论。 achievements是 0~1;score是单局得分(0~1,000,000量级),两者不是一回事。difficulty是"1"~"5"字符串、levelIndex是 1~5 数字;level是曲库显示串, 可能是"?"/"¿"/"a2",不能当数字解析。songName恒为null:曲名要自己接曲库。evaluate枚举不全:本服务只到5 = 银S,社区口径有 7 档(缺「金S」)。- 曲库缺失的谱面不进桶:
relative取不到时该条chartRl为null、不参与 RL。 - 推成绩时
rating优先:调用方给了就用;没给则按performance = (acc − acc² + acc⁴) × chartRl用曲库relative现算(曲库缺失则为0)。