diff --git a/.vitepress/theme/style.css b/.vitepress/theme/style.css
index 335983d..1039ca3 100644
--- a/.vitepress/theme/style.css
+++ b/.vitepress/theme/style.css
@@ -354,14 +354,13 @@ kbd {
font-weight: 700;
}
-.rating.red { color: #dc3545; }
-.rating.yellow { color: #b38600; }
-.rating.green { color: #198754; }
-.rating.blue { color: #0aa2c0; }
-
-.dark .rating.yellow { color: #ffc107; }
-.dark .rating.green { color: #75b798; }
-.dark .rating.blue { color: #6edff6; }
+/* 与脚本中的用户名颜色一致,浅色和深色模式共用一套颜色 */
+.rating.red { color: #dc2f5a; }
+.rating.orange { color: #e8590c; }
+.rating.blue { color: #337cf2; }
+.rating.green { color: #2b9f4f; }
+.rating.cyan { color: #1798b0; }
+.rating.gray { color: #78828c; }
/* 页脚与大纲 */
.VPFooter {
diff --git a/features/index.md b/features/index.md
index 4a0eb6d..9ee2387 100644
--- a/features/index.md
+++ b/features/index.md
@@ -9,7 +9,7 @@
| 恢复讨论与短消息 | 恢复小明的OJ上关掉的讨论区和短消息,由 XMOJ-Script 的服务器提供。 |
| 讨论提醒、短消息提醒 | 有人回复、@你或者发短消息时弹出提醒。 |
| [粘贴发图](./image-hosting) | 在讨论区和短消息里直接粘贴截图。 |
-| [用户评分](./rating) | 按 AC 率显示分数和彩色用户名。 |
+| [用户评分](./rating) | 综合做题量、准确度和坚持度显示分数和彩色用户名。 |
| [徽章](../community/badges) | 用户名旁边的小标签。 |
| 设置云同步 | 把插件设置同步到云端,换电脑不用重新设置。 |
diff --git a/features/rating.md b/features/rating.md
index 5afb78f..02bed9c 100644
--- a/features/rating.md
+++ b/features/rating.md
@@ -2,18 +2,89 @@
开启「添加用户评分和用户名颜色」后,用户名会按评分显示颜色,个人主页上也会显示具体分数。
+评分范围是 0–3000,只根据用户个人主页上公开的数据计算:解决的题数、各种评测结果的次数,以及每天的提交数和 AC 数。不依赖当前时间,也不需要额外请求,所以同一个主页在任何人的浏览器里算出来都是同一个分数。
+
## 怎么算
-$$\text{评分} = \frac{\text{AC 的提交数}}{\text{全部提交数}} \times 1000$$
+评分由三部分组成:
+
+| 部分 | 权重 | 看什么 |
+|------|------|--------|
+| 做题量 | 57% | 解决了多少题 |
+| 准确度 | 33% | 评测过的提交里,有多少解决了新题 |
+| 坚持度 | 10% | 有提交记录的天数 |
+
+### 用到的数据
+
+全部来自个人主页:
+
+| 符号 | 含义 |
+|------|------|
+| $S$ | 解决的题数 |
+| $X$ | 失败的评测次数:格式错误、答案错误、时间超限、内存超限、输出超限、运行错误之和 |
+| $a_d$ | 提交统计图中第 $d$ 天的 AC 数 |
+| $D$ | 提交统计图中有提交的天数 |
+
+编译错误和「忽略」不计入 $X$。已解决题目旁括号里的数字是这道题的全部提交次数,包括 AC 之后的提交,所以评分不使用它。
+
+$S = 0$ 时评分为 0。
+
+### 做题量
+
+为了防止一天内大量粘贴代码刷题,每天的 AC 数超过 8 之后按对数增长。一天 AC 14 次折算成约 12.5 次,AC 120 次只折算成约 30 次:
+
+$$g(a) = \begin{cases} a & a \le 8 \\ 8 + 8 \ln\left(1 + \dfrac{a - 8}{8}\right) & a > 8 \end{cases} \qquad B = \frac{\sum_d g(a_d)}{\sum_d a_d}$$
+
+没有 AC 记录时 $B = 1$。$B$ 是一个 0–1 之间的折扣,正常练习和比赛时基本等于 1。
+
+$$\text{做题量} = 1 - e^{-S B / 350}$$
+
+做到几百题以后,继续刷题的收益会越来越小。要拿高分,还得靠准确度。
+
+### 准确度
+
+先算评测过的提交里解决新题的比例 $P$。分子分母都加了 40 次虚拟提交(其中 25% 成功),向普通水平收缩,所以只做了几道题、碰巧全对,并不会拿到高分:
+
+$$P = \frac{S + 10}{S + X + 40}$$
+
+AC 之后重复提交 AC 代码既不增加 $S$ 也不增加 $X$,对评分没有影响。
+
+真正的强者也会在难题上失败,所以 $P$ 在 40%–55% 时得到满分。高于这个范围反而减分:几百道题几乎从不失败,更像是复制的代码。
+
+$$\text{准确度} = \begin{cases} 0 & P < 0.15 \\ \dfrac{P - 0.15}{0.25} & 0.15 \le P < 0.4 \\ 1 & 0.4 \le P < 0.55 \\ \max\left(0.3,\ 1 - 2(P - 0.55)\right) & P \ge 0.55 \end{cases}$$
+
+题做得越多,准确度越可信,所以它还要乘上可信度:
+
+$$K = \frac{S}{S + 80}$$
+
+### 坚持度
+
+$$\text{坚持度} = 1 - e^{-D/250}$$
+
+### 合在一起
+
+$$\text{评分} = \operatorname{round}\left(3000 \times \left(0.57 \cdot \text{做题量} + 0.33 \cdot \text{准确度} \cdot K + 0.10 \cdot \text{坚持度}\right)^{0.9}\right)$$
+
+### 算一遍
+
+一个新用户解决了 2 道题,答案错误 12 次,没有其他失败。三天的 AC 数是 8、2、4,这三天都有提交:
+
+- 每天 AC 都不超过 8,所以 $B = 1$,做题量 $= 1 - e^{-2/350} \approx 0.00570$
+- $P = \frac{2 + 10}{2 + 12 + 40} \approx 0.2222$,准确度 $= \frac{0.2222 - 0.15}{0.25} \approx 0.2889$,$K = \frac{2}{82} \approx 0.0244$
+- 坚持度 $= 1 - e^{-3/250} \approx 0.0119$
+- 评分 $= 3000 \times (0.57 \times 0.00570 + 0.33 \times 0.2889 \times 0.0244 + 0.10 \times 0.0119)^{0.9} \approx 3000 \times 0.00677^{0.9} \approx 33$
-全部提交数包括 WA、TLE、CE 等所有结果。所以评分看的是命中率,不是做了多少题。
+## 例子
-| 用户 | 全部提交 | AC | 评分 |
-|------|---------|----|------|
-| A | 100 | 80 | 800 |
-| B | 200 | 90 | 450 |
-| C | 150 | 50 | 333 |
-| D | 100 | 20 | 200 |
+| 用户 | 情况 | 评分 |
+|------|------|------|
+| A | 解决 1500 题,平均每题失败 3 次 | 2358 |
+| B | 解决 400 题,平均每题失败 1.25 次 | 2166 |
+| C | 解决 600 题,平均每题失败 7 次 | 1672 |
+| D | 解决 300 题,从未失败(像是复制的) | 1431 |
+| E | 解决 150 题,平均每题失败 3 次 | 1024 |
+| F | 和 D 一样,但每天 AC 50 题 | 905 |
+| G | 新用户,解决 20 题,平均每题失败 3 次 | 246 |
评分在浏览器里缓存一天,所以今天的提交通常明天才会反映出来。
@@ -21,10 +92,12 @@ $$\text{评分} = \frac{\text{AC 的提交数}}{\text{全部提交数}} \times 1
| 颜色 | 评分 |
|------|------|
-| 红 | 高于 500 |
-| 黄 | 400–500 |
-| 绿 | 300–399 |
-| 蓝 | 低于 300 |
+| 红 | 2400 及以上 |
+| 橙 | 2000–2399 |
+| 蓝 | 1600–1999 |
+| 绿 | 1200–1599 |
+| 青 | 800–1199 |
+| 灰 | 低于 800 |
## 在哪里显示
@@ -35,4 +108,4 @@ $$\text{评分} = \frac{\text{AC 的提交数}}{\text{全部提交数}} \times 1
## 想提高评分?
-少交没把握的代码。提交前先在本地测好;没过的时候,用[获取测试点数据](./get-data)找到原因再改,别反复试。
+多做题,尤其是有挑战的题,并且减少失败的提交。提交前先在本地测好;没过的时候,用[获取测试点数据](./get-data)找到原因再改,别反复试。一天集中刷大量题目不会让评分涨得更快。
diff --git a/index.md b/index.md
index 23b7551..1cc3f9b 100644
--- a/index.md
+++ b/index.md
@@ -22,7 +22,7 @@ hero:
features:
- title: 用户评分
- details: 按 AC 率算出 0–1000 分,用户名按分数显示红、黄、绿、蓝四种颜色。
+ details: 综合做题量、准确度和坚持度算出 0–3000 分,难以刷分;用户名按分数显示六种颜色。
link: /features/rating
linkText: 怎么算的
- title: 粘贴就能发图