Files
cursor/plans/stats_init_重复分析_3fc8ad4b.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

7.4 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
Stats init 重复分析 已用生产数据确认auto_first 以 spin_source=1、prize_type=1、prize_amount_qf=init 落库,当前 statistics 会把同一笔开宝箱金额算两遍。修复方向是在 aggregateSpinStats 排除 spin_source=AUTO_FIRST保留 init + 手动 Spin 随机入账相加。
id content status
verify-auto-first-row 确认 slot_console 开宝箱 auto_first 记录的 prize_type / spin_source / prize_amount_qf 落库值 completed
id content status
exclude-auto-first-stats aggregateSpinStats 排除 spin_source=AUTO_FIRST并补 LuckyRewardSpinRecordModel 常量 completed
id content status
add-stats-test 补统计用例:仅开宝箱无手动 Spin 时 total_reward_amount_qf=init 总和,且 spin_total/random_hit_count=0 completed
false

LuckyRewardStatsLogic 统计口径分析

直接回答

不是。 $spinStats没有完整包含 $initAmountTotalQf,两者是刻意分开再相加的:

// backend/slot_admin/app/game/logic/LuckyRewardStatsLogic.php
$initAmountTotalQf = (int) (clone $playerQuery)->sum('p.init_amount_qf');
$spinStats = $this->aggregateSpinStats($playerQuery);
$prizeAmountTotalQf = (int) ($spinStats['prize_amount_total_qf'] ?? 0);
$totalRewardAmountQf = $initAmountTotalQf + $prizeAmountTotalQf;

$spinStats 返回的是 Spin 记录维度 的聚合,与 player 表上的 init_amount_qf 来源不同:

字段 数据来源 含义
$initAmountTotalQf lucky_reward_player.init_amount_qf 开宝箱命中初始金额汇总
$spinStats['prize_amount_total_qf'] lucky_reward_spin_record.prize_amount_qfprize_type=1 随机金额类 Spin 实际入账汇总
$spinStats['spin_total'] lucky_reward_spin_record 行数 命中次数/比率,不是金额

需求文档口径(02_管理后台方案.md §7.2

总奖励金额 = sum(player.init_amount_qf) + sum(spin_record.prize_amount_qf)(开宝箱初始 + Spin 随机入账 = 实际投放)

因此 $initAmountTotalQf 不能删total_reward_amount_qf 本应是「init + 手动 Spin 随机入账」,不应把 auto_first 展示记录算进 prize 部分。


生产数据已确认重复计数

用户提供的真实行:

INSERT INTO lucky_reward_spin_record
  (uid, cycle_id, spin_id, spin_source, prize_type, prize_amount_qf, my_amount_after_qf)
VALUES
  (1545906, 46, 'auto_first:1545906:46', 1, 1, 9603, 9603);

字段解读(与 DDL 一致):

字段 含义
spin_id auto_first:1545906:46 开宝箱自动首次 SpinRecord 展示)
spin_source 1 自动首次
prize_type 1 随机金额
prize_amount_qf 9603 player.init_amount_qf 相同

对 uid=1545906、cycle=46 若仅开宝箱、无手动 Spin

  • $initAmountTotalQf = 9603(来自 player
  • $spinStats['prize_amount_total_qf'] = 9603auto_first 被 prize_type=1 命中)
  • $totalRewardAmountQf = 19206(应为 9603

同时 spin_total / random_hit_count 也会把 auto_first 算进 Spin 次数与命中率,导致指标失真(每个参与用户天然 +1 次 Spin、+1 次 random 命中)。


spin_total 同样算错

是的。 $spinStats['spin_total']lucky_reward_spin_record 全表 count,没有任何 spin_source 过滤:

$spinTotal = (int) (clone $spinQuery)->count();  // 含 auto_first

对你给的 uid 1545906:只开宝箱、从未手动 Spin 时:

指标 当前错误值 修正后应为
spin_total 1auto_first 0
random_hit_count 1auto_first 且 prize_type=1 0
random_hit_rate 100% 0%

需求文档 02_管理后台方案.md §7.3 明细列 Spin 用的是 player.spin_used,注释为 「不含初始自动」;总览 spin_total 应与之一致,只统计真实消耗 Spin 次数的记录(spin_source 为每日/邀请/手动),不应含开宝箱 auto_first。

连带影响的字段(同一 $spinQuery 未过滤):

  • spin_total — 分母偏大
  • random_hit_count / random_hit_rate — 分子、分母都含 auto_first
  • cashout_hit_count / cashout_hit_rate — 若 auto_first 不会 prize_type=3通常不受影响但仍应统一排除
  • spin_prize_hit_count / spin_prize_hit_rate — 同上
  • prize_amount_total_qf — 金额重复(见上)

修复时在 $spinQuery 基查询一次性加 spin_source <> AUTO_FIRST,上述字段一并修正。


根因

aggregateSpinStats() 只按 prize_type=1 过滤金额/次数,未排除 spin_source=1auto_first

$prizeAmountTotalQf = (int) (clone $spinQuery)
    ->where('sr.prize_type', LuckyRewardSpinRecordModel::PRIZE_TYPE_RANDOM)
    ->sum('sr.prize_amount_qf');

C 端开宝箱写 auto_first 时为了 Record 展示使用了 prize_type=1 + prize_amount_qf=init,与 My Amount 入账无关admin 统计误将其当作「Spin 随机入账」。

需求 04_slot_console_活动主流程方案.mdauto_first 仅动画/Record不叠加金额

flowchart TD
  openBox[openBox 开宝箱]
  playerInit["player.init_amount_qf = 9603"]
  autoFirst["spin_record auto_first prize_amount_qf = 9603"]
  statsInit["initAmountTotalQf += 9603"]
  statsPrize["prize_amount_total_qf += 9603"]
  doubleCount["total_reward = 19206 重复"]
  openBox --> playerInit
  openBox --> autoFirst
  playerInit --> statsInit
  autoFirst --> statsPrize
  statsInit --> doubleCount
  statsPrize --> doubleCount

修复方案(待执行)

aggregateSpinStats() 中,所有 spin 记录聚合(次数与金额)统一排除 auto_first

  1. LuckyRewardSpinRecordModel 增加常量:
    • SPIN_SOURCE_AUTO_FIRST = 1
    • SPIN_SOURCE_DAILY = 2
    • SPIN_SOURCE_INVITE = 3(与 DDL 注释对齐)
  2. $spinQuery 基查询增加:->where('sr.spin_source', '<>', SPIN_SOURCE_AUTO_FIRST)
    • 影响:spin_totalrandom_hit_countcashout_hit_countspin_prize_hit_countprize_amount_total_qf
  3. 保持 $totalRewardAmountQf = $initAmountTotalQf + $prizeAmountTotalQf 不变
  4. 补测试:仅开宝箱用户 → total_reward_amount_qf === sum(init_amount_qf)auto_first 行存在但不计入 prize

不改 C 端落库auto_first 继续用于 Record 展示;仅修正 admin 统计过滤。

不建议删掉 $initAmountTotalQf 或改为只 sum spin_record。


小结

问题 答案
$spinStats 是否已包含 $initAmountTotalQf ;但 prize_amount_total_qf 对 auto_first 重复计入了同一份 init
两处相加是否合理? 公式合理;当前实现因未排除 auto_first 结果错误
生产数据是否证实? uid 1545906 示例9603 被算成 19206
spin_total 是否也算错? ;仅开宝箱用户会显示 spin_total=1、random_hit_rate=100%