FMCRAFT 玩家活跃指数(Activity Index)解析
这是什么
活跃指数是一个 0 到 5 分的数字,用来回答一个问题:
这个玩家最近还活跃吗?
它只做一件事:把玩家最近 3 周的有效游戏时长,压缩成一个可以直接比较的分数,并贴上一个人类可读的标签("非常活跃"、"不活跃"等)。
分数越高 = 玩得越勤、越稳定;分数越低 = 玩得越少、越不规律。
核心思路:三条规则
理解这个指数,只需要记住三条规则。
规则一:只看最近 3 周
指数只统计最近 21 天的数据,超过 3 周的记录一律不看。
所以它是一个"滑动窗口"指标——3 周前爆肝 100 小时,今天玩 1 分钟,指数依然会很低。
规则二:AFK 时间不算
玩家的有效游戏时长 = 在线总时长 − 挂机(AFK)时长。
Plan 默认挂机超过 3 分钟不移动就判定为 AFK。挂机时间会被扣掉,所以"开着电脑睡觉"不会虚增指数。
可以在config.yml里调整Time.Thresholds.AFK_threshold。
规则三:连续性 > 爆发力
这是这个指数最重要的设计。同样的总时长,分摊到 3 周比集中在 1 周得分高得多。
后面有详细例子。
核心计算公式
完整公式
$$ \mathrm{Index} \;=\; 5 \;-\; \frac{5}{3}\left( \frac{1}{1 + \frac{\pi}{2}\cdot\frac{t_1}{T}} \;+\; \frac{1}{1 + \frac{\pi}{2}\cdot\frac{t_2}{T}} \;+\; \frac{1}{1 + \frac{\pi}{2}\cdot\frac{t_3}{T}} \right) $$
等价写法(把平均摊进系数里,更直观):
$$ \mathrm{Index} \;=\; 5 \;-\; 5 \times \frac{1}{3}\left[ S(t_1) + S(t_2) + S(t_3) \right] $$
其中 $\dfrac{\pi}{2} \approx 1.5708$。
符号说明
| 符号 | 含义 | 默认值 / 取值 |
|---|---|---|
| $\mathrm{Index}$ | 最终活跃指数 | 结果落在 $[0,\ 5)$ 区间 |
| $t_1$ | 最近 7 天的有效游戏时长 | $=\sum(\text{在线时长} - \text{AFK 时长})$ |
| $t_2$ | 往前第 2 个 7 天的有效游戏时长 | 同上 |
| $t_3$ | 往前第 3 个 7 天的有效游戏时长 | 同上 |
| $T$ | 一周活跃基准线 (Playtime_threshold) | 默认 $30$ 分钟 $= 1{,}800{,}000\ \text{ms}$ |
| $\dfrac{\pi}{2}$ | 曲线调节系数 | 固定 $\approx 1.5708$ |
三层结构
公式可以拆成三层来看:
第一层 —— 单周曲线(调和函数衰减)
$$ S(t) \;=\; \frac{1}{1 + \frac{\pi}{2}\cdot\frac{t}{T}} $$
性质:
$$ S(0) = 1, \qquad S(T) = \frac{1}{1+1.5708} \approx 0.389, \qquad S(2T) \approx 0.242, \qquad \lim_{t \to \infty} S(t) = 0 $$
- $S(0)=1$:一点没玩 → 满分惩罚
- $S(T)\approx 0.389$:玩满基准线 → 惩罚降到 39%
- $S(\infty)\to 0$:玩无限久 → 惩罚趋近于 0
- 单调递减、且凸(越往后越平)
第二层 —— 三周算术平均
$$ \bar{S} \;=\; \frac{S(t_1) + S(t_2) + S(t_3)}{3} $$
等权。没有"最近一周更重要"的加权。
第三层 —— 反向映射到 $0 \sim 5$
$$ \mathrm{Index} \;=\; 5 - 5\bar{S} \;=\; 5\left(1 - \bar{S}\right) $$
因为 $\bar{S} \in (0,\ 1]$,所以 $\mathrm{Index} \in [0,\ 5)$。
$$ \text{门槛} \iff \mathrm{Index} \geq x \iff \bar{S} \leq 1 - \frac{x}{5} $$
| $\bar{S}$ | $\mathrm{Index}$ | 含义 |
|---|---|---|
| $1.000$ | $0.00$ | 三周完全没玩 |
| $0.800$ | $1.00$ | 不规律门槛 |
| $0.600$ | $2.00$ | 常规门槛 |
| $0.400$ | $3.00$ | 活跃门槛 |
| $0.250$ | $3.75$ | 非常活跃门槛 |
| $0.000$ | $5.00$ | 理论极限,永不达到 |
关键边界结论(由公式直接推出)
只活跃 1 周时的理论上限:
设 $t_2 = t_3 = 0$,则 $S(t_2) = S(t_3) = 1$,于是:
$$ \mathrm{Index} \;=\; 5 - \frac{5}{3}\left( S(t_1) + 2 \right) $$
当 $t_1 \to \infty$ 时 $S(t_1) \to 0$,取极限得:
$$ \mathrm{Index}_{\max} \;=\; 5 - \frac{5}{3}\cdot 2 \;=\; \frac{5}{3} \;\approx\; 1.67 $$
无论第一周玩 1 小时还是 100 小时,只要另外两周零活跃,指数最高只能到 $1.67$(不规律)。
想突破 $2.00$(常规)这条线,至少需要两周有实际游戏。
达到"非常活跃"($\ge 3.75$)的条件:
$$ 3.75 \leq 5\left(1 - \bar{S}\right) \iff \bar{S} \leq 0.25 $$
三周均等时 $S(t) = 0.25$,反解得:
$$ \frac{1}{1 + \frac{\pi}{2}\cdot\frac{t}{T}} = \frac{1}{4} \iff \frac{\pi}{2}\cdot\frac{t}{T} = 3 \iff \frac{t}{T} = \frac{6}{\pi} \approx 1.910 $$
即每周需要 $t \geq 1.91\,T \approx 57.3$ 分钟(默认配置下约每天 8 分钟)。
怎么算的(逐步展开)
第 1 步:算出每周的有效时长
把最近 21 天切成 3 个 7 天的窗口,分别累加有效游戏时长:
$$ \begin{aligned} t_1 &= \text{最近 7 天的有效时长} \\ t_2 &= \text{往前第 2 个 7 天的有效时长} \\ t_3 &= \text{往前第 3 个 7 天的有效时长} \end{aligned} $$
第 2 步:每一周单独打一个"周分"
每一周用同一条曲线打分:
$$ S(t) \;=\; \frac{1}{1 + 1.5708 \cdot \frac{t}{T}} $$
其中 $T$ 是"一周活跃基准线",默认 $30$ 分钟(可在 config.yml 的 Time.Thresholds.Activity_index.Playtime_threshold 调整)。
这条曲线的形状是这样的:
| 这周玩了 | 周分 $S(t)$ | 含义 |
|---|---|---|
| $0$ 分钟 | $1.000$ | 这周完全没玩 |
| $10$ 分钟 | $0.656$ | 碰了一下 |
| $20$ 分钟 | $0.489$ | 玩了一会儿 |
| $30$ 分钟 $(=T)$ | $0.389$ | 达到基准线 |
| $60$ 分钟 $(=2T)$ | $0.242$ | 玩得比较多 |
| $120$ 分钟 | $0.137$ | 玩得很多 |
| $\infty$ | $\to 0$ | 趋近于 0 |
注意周分的走向是反的:玩得越少,周分越高。玩得越多,周分越低,并且越降越慢(曲线是平的)。
这就是"递减边际":从 0 分钟玩到 30 分钟,指数涨得飞快;从 60 分钟玩到 90 分钟,指数只挪动一点点。这样可以避免"在线时间一长就无限刷分"。
第 3 步:三周合并,反向放大
$$ \bar{S} = \frac{S(t_1) + S(t_2) + S(t_3)}{3} \qquad\qquad \mathrm{Index} = 5\left(1 - \bar{S}\right) $$
最后这一步把结果反过来,并拉伸到 $0 \sim 5$:
- 三周都没玩 $\Rightarrow S_i = 1 \Rightarrow \bar{S}=1 \Rightarrow \mathrm{Index} = 5-5 = \mathbf{0}$
- 三周都玩爆 $\Rightarrow S_i \to 0 \Rightarrow \bar{S}\to 0 \Rightarrow \mathrm{Index} \to \mathbf{5}$
分数对应什么标签
| 指数区间 | 标签 |
|---|---|
| $\mathrm{Index} \ge 3.75$ | 非常活跃 (Very Active) |
| $\mathrm{Index} \ge 3.00$ | 活跃 (Active) |
| $\mathrm{Index} \ge 2.00$ | 常规 (Regular) |
| $\mathrm{Index} \ge 1.00$ | 不规律 (Irregular) |
| $\mathrm{Index} < 1.00$ | 不活跃 (Inactive) |
理论上 5 分是"无限游戏时长"的极限,实际玩家几乎不可能达到 5 分。即使三周每周玩 2 小时(合计 42 小时),指数也只有 4.31 左右。
实际算例
假设基准线 T = 30 分钟(默认)。
例 1:稳定肝帝
| 最近 1 周 | 第 2 周 | 第 3 周 | |
|---|---|---|---|
| 有效时长 | 60 分 | 60 分 | 60 分 |
| 周分 | 0.242 | 0.242 | 0.242 |
$$ \bar{S} = \frac{0.242 + 0.242 + 0.242}{3} = 0.242 $$
$$ \mathrm{Index} = 5\left(1 - 0.242\right) = 3.79 $$
→ 非常活跃 (Very Active)
三周均匀发力,稳稳站上 Very Active 线。
例 2:刚好够到"活跃"
| 最近 1 周 | 第 2 周 | 第 3 周 | |
|---|---|---|---|
| 有效时长 | 30 分 | 30 分 | 30 分 |
| 周分 $S(t)$ | 0.389 | 0.389 | 0.389 |
$$ \bar{S} = \frac{0.389 \times 3}{3} = 0.389 $$
$$ \mathrm{Index} = 5\left(1 - 0.389\right) = 3.06 $$
→ 活跃 (Active)
这就是基准线的设计意图:一周有效玩 30 分钟,三周都玩,就该算"活跃"。
例 3:只玩了一周
同样只玩 60 分钟,但只集中在最近一周:
| 最近 1 周 | 第 2 周 | 第 3 周 | |
|---|---|---|---|
| 有效时长 | 60 分 | 0 分 | 0 分 |
| 周分 $S(t)$ | 0.242 | 1.000 | 1.000 |
$$ \bar{S} = \frac{0.242 + 1 + 1}{3} = 0.747 $$
$$ \mathrm{Index} = 5\left(1 - 0.747\right) = 1.26 $$
→ 不规律 (Irregular)
对比例 1:同样是 60 分钟/周 × 3 周(3.79,非常活跃)
差距 $3.79 - 1.26 = 2.53$ 分。这就是"连续性"的威力。
例 4:回归的老玩家
| 最近 1 周 | 第 2 周 | 第 3 周 | |
|---|---|---|---|
| 有效时长 | 180 分 | 0 分 | 0 分 |
$$ S(180) = \frac{1}{1 + 1.5708 \times \frac{180}{30}} = 0.096 $$
$$ \bar{S} = \frac{0.096 + 1 + 1}{3} = 0.699 $$
$$ \mathrm{Index} = 5\left(1 - 0.699\right) = 1.51 $$
→ 不规律 (Irregular)
玩了整整 3 小时仍然只有 1.51 分。
关键结论:只活跃 1 周,数学上的天花板就是 $\dfrac{5}{3} \approx 1.67$ 分(不规律)。
因为另外两周各贡献 $S=1$,$\bar{S}$ 被锁死在 $\frac{2}{3}$ 附近,无论你第一周玩多久都拉不上去。想让指数爬过 2 分(常规),至少要两周有实际游戏。
例 5:逐渐流失
同一个人,一步步掉活跃度:
| 场景 | 三周时长(分) | 指数 | 标签 |
|---|---|---|---|
| 三周前开始玩 | 10 / 10 / 10 | 1.72 | 不规律 |
| 第二周 | 20 / 20 / 20 | 2.56 | 常规 |
| 第三周 | 30 / 30 / 30 | 3.06 | 活跃 |
| 第四周(停一周) | 30 / 30 / 0 | 2.04 | 常规 |
| 第五周(再停一周) | 30 / 0 / 0 | 1.02 | 不规律 |
| 第六周(停三周) | 0 / 0 / 0 | 0.00 | 不活跃 |
指数滑落得非常平滑,不会出现断崖式跳变——这正是 1/(1+x) 这种"平滑递减"曲线带来的好处。每停一周大约掉 1 分左右(当周时长接近基准线时)。
例 6:低时长玩家的自洽性
一周只玩 5 分钟,零门槛玩家:
| 最近 1 周 | 第 2 周 | 第 3 周 | |
|---|---|---|---|
| 有效时长 | 5 分 | 5 分 | 5 分 |
| 周分 $S(t)$ | 0.793 | 0.793 | 0.793 |
$$ \bar{S} = \frac{0.793 \times 3}{3} = 0.793 $$
$$ \mathrm{Index} = 5\left(1 - 0.793\right) = 1.04 $$
→ 不规律 (Irregular)
即使一周只玩 5 分钟,只要坚持了三周,也能拿到 1.04 分,够到"不规律"的门槛($1.00$)。不活跃($<1.00$)基本只留给"三周内确实没怎么玩"的人。
常见误解
❌ "我挂机了一晚上,指数应该很高吧?"
不会。AFK 时间(默认超 3 分钟不动)被完全扣除。挂机只会被算成"没有活跃时长"。
❌ "我时间被偷走了 / 指数突然变低?"
如果你开启了 Remove_inactive_player_data_after(默认 3650 天,实际不触发),或者服务器更换导致历史 session 缺失,指数会回落。另外刚建档的新玩家因为历史数据不足,前几天指数天然偏低。
❌ "为什么我的分数看起来总是卡在 3.x 上不去?"
因为边际递减。三周从 30 分钟/周提到 57 分钟/周(+90% 的时间),指数才从 3.06 涨到 3.75。想要"非常活跃",稳定每天上线比偶尔肝一天有效得多。
❌ "分数是按天刷新的吗?"
不是。指数是实时计算的,没有缓存表,读取即重算最近 3 周的 session。所以任何时刻查看,结果都反映当下。
⚠️ 跨周的长挂机会重复计入
如果你有一次连续在线很多天的会话(且没有被判定为 AFK),它的完整时长会被同时算进它覆盖到的每一个周窗口。极端情况下会让指数偏高,这是已知的小瑕疵。
调整参数
两个阈值都在 config.yml 的 Time 段下:
| 配置项 | 默认值 | 说明 |
|---|---|---|
AFK_threshold | 3 分钟 | 挂机多久后不计入有效时长 |
Activity_index.Playtime_threshold | 30 分钟 | 一周活跃基准线 T |
关于 T 的调整建议:
- 调高 T(如 60 分钟)→ 曲线整体右移,同样的游戏时长会得到更高的指数,分组更容易达成。对休闲型服务器合适。
- 调低 T(如 15 分钟)→ 同样的时长得到更低的指数,只有真正肝度爆表才能到 Very Active。对硬核服合适。
⚠️ 调整 T 会让新旧数据不可比——今天调了配置,历史统计图上的曲线会整体平移,看起来像所有玩家同时变活跃/变不活跃。建议在固定的时间点调整,或调完配置后清空活跃相关的展示缓存再观察。
一句话总结
$$ \boxed{\;\mathrm{Index} \;=\; 5 \;-\; \frac{5}{3}\left( \frac{1}{1 + 1.5708\cdot\frac{t_1}{T}} + \frac{1}{1 + 1.5708\cdot\frac{t_2}{T}} + \frac{1}{1 + 1.5708\cdot\frac{t_3}{T}} \right)\;} $$
$t$ = 每周有效游戏时长(已扣 AFK) · $T$ = 一周基准线(默认 30 分钟) · 结果 $\in [0, 5)$
它奖励稳定出勤,惩罚一周爆发 + 两周消失,并把挂机时间当作零。
连续三周、每周 30 分钟有效游戏 $\approx 3.06$ 分(活跃)。
只玩一周,无论玩多久,上限 $\frac{5}{3} \approx 1.67$ 分(不规律)。
1 条评论
本文章为 AI 生成