pmc 61e8374e6a fix(affinity-P1): WR-002~WR-009 + IN-001~IN-006 综合改进收尾
WR-002 UserLevelRewardGrant.device on_delete CASCADE → SET_NULL,加 device_snapshot_id,
  unique 改为 partial(device 非空时唯一),与 AffinityLog.device SET_NULL 对齐
WR-003 AffinityLog 删除 3 个低价值索引(user/rule_key/source -created_at 复合)
WR-004 event_id 改为 null=True,partial unique 用 isnull=False;RunPython '' → NULL
WR-005 seed 加 companion_30min 默认规则
WR-006 description 显式 default='';DEFAULT_LEVELS 全部补 description
WR-007 seed_affinity 每条 spec 独立事务,部分失败可重跑
WR-008 ParadiseUser.favorability 字段保留 + UserInfoSerializer 移除暴露 + [DEPRECATED] 标记
WR-009(见 Commit B:AffinityLevel.clean + save full_clean 多层兜底)
IN-001 5 个弃用字段 help_text 加 [DEPRECATED — 计划于 P2 完成后删除]
IN-002 DEFAULT_RULES/LEVELS/SETTING 抽到 userapp/affinity/defaults.py
IN-003 AffinitySetting.daily_cap RenameField → global_daily_cap(区分 AffinityRule.daily_cap)
IN-004 AffinityLog.__str__ 用 pk or 'new' 兜底 None
IN-005(见 Commit A:is_active → is_bound 改名)
IN-006(见 Commit C:0006 print 前缀改为 [migration 0006_...])

迁移 0009 手工修正:daily_cap 改名用 RenameField(保留数据),不是 Remove+Add;
event_id '' → NULL 数据兜底;UserLevelRewardGrant on_delete + conditional unique 重建。

详见 docs/REVIEW-affinity-P1.md WR-* / IN-* 与 FIX-REPORT.md。
2026-05-13 10:18:47 +08:00

141 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""好感度系统默认数据常量
供 seed_affinity management command、单元测试、P2 服务层fallback 配置)等共享。
与设计文档对应:
DEFAULT_RULES — 「好感度系统功能与规则设计.md」§4.2 互动规则
DEFAULT_LEVELS — 同文档 §6.2 等级表
DEFAULT_SETTING — 同文档 §3.2 全局参数 + §5.1 衰减字段
IN-002从 management/commands/seed_affinity.py 抽取,避免 management command
文件膨胀,且让测试代码 / P2 服务层可以正规 import
from userapp.affinity.defaults import DEFAULT_RULES, DEFAULT_LEVELS, DEFAULT_SETTING
"""
# 默认规则,与设计文档 §4.2 一致
# WR-005新增 1 条 trigger_type='companion_time' 规则(陪伴 30 分钟)
# WR-006所有 description 显式填写,不依赖 model blank=True 隐式默认
DEFAULT_RULES = [
{
'rule_key': 'card', 'name': '使用卡片', 'description': '用户使用洛天依卡片',
'trigger_type': 'action',
'min_change': 1, 'max_change': 3, 'single_cap': 3, 'daily_cap': 10,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'chat', 'name': '对话', 'description': '与洛天依进行对话',
'trigger_type': 'action',
'min_change': 1, 'max_change': 5, 'single_cap': 5, 'daily_cap': 15,
'cooldown_seconds': 30, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'feed', 'name': '喂食', 'description': '给洛天依喂食',
'trigger_type': 'action',
'min_change': 2, 'max_change': 8, 'single_cap': 8, 'daily_cap': 16,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'touch', 'name': '抚摸', 'description': '抚摸洛天依',
'trigger_type': 'action',
'min_change': 1, 'max_change': 3, 'single_cap': 3, 'daily_cap': 9,
'cooldown_seconds': 10, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'dress', 'name': '换装', 'description': '为洛天依更换服装',
'trigger_type': 'action',
'min_change': 2, 'max_change': 6, 'single_cap': 6, 'daily_cap': 12,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'prop', 'name': '使用道具', 'description': '使用互动道具',
'trigger_type': 'action',
'min_change': 1, 'max_change': 4, 'single_cap': 4, 'daily_cap': 12,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'gift', 'name': '送礼物', 'description': '赠送礼物给洛天依',
'trigger_type': 'action',
'min_change': 5, 'max_change': 15, 'single_cap': 15, 'daily_cap': 20,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
},
{
'rule_key': 'decay', 'name': '无互动衰减', 'description': '长时间不互动导致好感度下降',
'trigger_type': 'decay',
'min_change': -3, 'max_change': -1, 'single_cap': 3, 'daily_cap': 5,
'cooldown_seconds': 0, 'is_negative': True, 'is_enabled': True,
},
# WR-005陪伴时长类规则数值参考设计文档 §4.2,具体值可由运营在 admin 调整)
{
'rule_key': 'companion_30min', 'name': '陪伴 30 分钟',
'description': '与洛天依持续陪伴 30 分钟可获得好感度(数值待产品最终对齐,先用保守默认)',
'trigger_type': 'companion_time',
'min_change': 1, 'max_change': 2, 'single_cap': 2, 'daily_cap': 8,
'cooldown_seconds': 0, 'is_negative': False, 'is_enabled': True,
'min_continuous_minutes': 30, 'max_count_per_day': 4,
},
]
# 默认等级,与设计文档 §6.2 一致
# WR-006所有 description 显式填写
DEFAULT_LEVELS = [
{
'level': 1, 'name': '初识',
'description': '初次相识阶段,了解彼此的基础互动',
'min_affinity': 0, 'max_affinity': 20,
'unlock_content': '基础对话功能',
'reward_type': 'unlock', 'reward_currency': 0, 'reward_items': [],
'is_enabled': True,
},
{
'level': 2, 'name': '相识',
'description': '熟悉彼此个性,解锁基础道具与服装',
'min_affinity': 21, 'max_affinity': 40,
'unlock_content': '基础服装、道具使用',
'reward_type': 'unlock', 'reward_currency': 0, 'reward_items': [],
'is_enabled': True,
},
{
'level': 3, 'name': '熟悉',
'description': '互动深入,解锁更多内容',
'min_affinity': 41, 'max_affinity': 60,
'unlock_content': '更多服装、特殊对话',
'reward_type': 'unlock', 'reward_currency': 0, 'reward_items': [],
'is_enabled': True,
},
{
'level': 4, 'name': '亲密',
'description': '亲密互动阶段,解锁限定内容',
'min_affinity': 61, 'max_affinity': 80,
'unlock_content': '限定服装、特殊互动',
'reward_type': 'unlock', 'reward_currency': 0, 'reward_items': [],
'is_enabled': True,
},
{
'level': 5, 'name': '挚友',
'description': '最高亲密度,解锁专属剧情',
'min_affinity': 81, 'max_affinity': 100,
'unlock_content': '专属内容、特殊剧情',
'reward_type': 'unlock', 'reward_currency': 0, 'reward_items': [],
'is_enabled': True,
},
]
# 默认全局设置(用于 seed_affinity 在表为空时创建)
DEFAULT_SETTING = {
'initial_affinity': 10,
'max_affinity': 100,
'global_daily_cap': 20, # IN-003重命名 daily_cap → global_daily_cap
'decay_rate': 2,
'decay_threshold': 3,
'decay_min_decay': 1,
'decay_max_decay': 3,
'decay_cap': 5,
'decay_min_floor': 0,
'enable_notify': True,
'enable_rewards': True,
'notify_decay': True,
'timezone': 'Asia/Shanghai',
}