fix(广告发奖): eCPM 过低单份金币四舍五入成 0 时兜底发 1,避免看了广告被记 too_short 零发 #205
Reference in New Issue
Block a user
Delete Branch "fix/ad-reward-min-one-coin"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景 / 问题
线上 record 4667:用户在比价等候期看满一条低 eCPM(¥0.43 CPM)的信息流广告(≥10s),
但单份金币按公式
0.43/1000 × 0.1(档位因子) × 1.0(LT因子) × 10000 = 0.43,四舍五入成 0。在
grant_feed_reward里unit_cap=0→coin<=0→ 记too_short零发。结果:用户看满了广告却什么都没拿到,还被标成"时长不足"。
改动
app/core/rewards.py的calculate_ad_reward_coin(发奖与后台审计对账的唯一口径):max(0, …)→max(1, …))。return 0—— 不凭空铸币、不破坏ecpm_missing语义。关键设计
if ecpm_yuan <= 0: return 0 是防铸币防线:没它的话 reward_video 路径 ecpm="0" 会被 floor 成 1。
不影响防刷:上限仍由 AD_ECPM_MAX_FEN(¥500 CPM)钳顶;LT 因子最低 1.0、从不归零,限流靠每日 500 次上限。
正常量级 eCPM 本就 ≥1,下限不改变其取值(纯回归保护)。
🤖 review-pr 深审结论
🟢 可合并 · 置信度 0.92 —— 金钱发奖修复正确、防铸币防线到位、测试充分(33 用例全过)。
改动:
calculate_ad_reward_coin(发奖 + 审计对账唯一口径)if ecpm_yuan <= 0: return 0(在 max 之前)——防铸币防线。max(0, …)→max(1, …)——有真实正 eCPM 时单份至少 1 金币。正确性核对(合并后)
ecpm<=0 → return 0,再对正 eCPMmax(1)。故低正 eCPM(0.43 四舍五入成 0)→ 1;eCPM 缺失/0/非法 → 0(不凭空铸币,保护reward_video回退ecpm="0"路径)。ad_feed_reward/ad_reward)与后台审计对账(ad_audit)同调此函数 → 改一处两边同源,对账仍自洽。AD_ECPM_MAX_FEN钳顶不变,防刷不受影响。rewards.py。构建/测试(实跑 .venv / py3.12 合并后)
test_ad_reward_coin_floor.py4 passed(低正→1 / 零·缺失·非法→0 / 正常回归 / 端到端grant_feed_rewardgranted+coin=1)test_ad_reward.py29 passed(现有发奖回归,正常 eCPM 不受下限影响)提示(info,不阻塞):历史
too_short(发 0)记录若纳入审计对账,新口径复算expected=1会显示「应发 1 / 实发 0」差异——属历史遗留(本就发错),非本 PR 引入;若审计只对granted记录则无影响。风险 🟢。
— 🤖 review-pr 自动深审 @guke