# 游戏系统

> 打卡、经济、称号三大核心玩法

---

## 打卡系统

### 正常打卡流程 (`/打卡`)

1. 验证消息包含图片
2. 获取当前周范围 (Mon 08:00 → next Mon 08:00)
3. 判断本周是否首次打卡
4. 插入 `checkin_records`（含 `message_id`）
5. 检查打卡幸运加成（商店 buff，10% 概率 +1）
6. 调用 `evaluate_and_unlock_titles()` 解锁条件称号
7. 发送解锁通知

### 积分奖励明细

| 奖励 | 条件 | 积分 | 重复保护 |
|------|------|------|---------|
| 当月全勤 | 该月每天打卡 | +1 | `full_month_weekly_check` |
| 打卡幸运 | 商店 buff，10% 概率 | +1 | buff 次数消耗 |
| 周常任务 | 3 个打卡任务（1/3/7次） | +1/+2/+3 | `quest_progress` |
| 周常任务 | 2 个抽奖任务（3/7次） | +1/+2 | `quest_progress` |

原"首次打卡 +1"和"自然周全勤 +1"已合并到周常任务系统的打卡任务中。

### 撤回打卡 (`/撤回打卡`)

- 删除本周最近一次打卡记录
- 回滚已领取的 attendance rewards（全勤/满月）
- 回滚周常任务进度（通过 `on_quest_rollback()` 回收已完成任务的积分）

### 打卡消息被撤回 (自动)

`checkin_recall.py` 监听 `notice_type == "group_recall"`，根据 `message_id` 查找并回滚打卡记录和奖励（含任务进度）。

### 补卡系统

| 指令 | 费用 | 年上限 | 效果 |
|------|------|--------|------|
| `/补卡 YYYY-MM-DD` | 6 积分 | 4 次/年 | 补该周一整周 |
| `/单日补卡 YYYY-MM-DD` | 2 积分 | 无 | 补单个日期 |
| `/超级补卡 YYYY-MM-DD [uid]` | 免费 | 无 | 管理员补卡 |

补卡记录 `content = "remedy_checkin"`，查询打卡图时排除。补卡**不会**计入周常任务进度。

### 周常任务系统

6 个硬编码任务，以 Monday 08:00 周为周期重置。定义在 `core/utils.py:QUEST_DEFS`。

| ID | 名称 | 触发类型 | 目标 | 奖励 |
|----|------|----------|------|------|
| 1 | 打个卡先 | checkin | 1次 | +1 |
| 2 | 三连打卡 | checkin | 3次 | +2 |
| 3 | 一周都打了 | checkin | 7次 | +3 |
| 4 | 随便抽抽 | lottery | 3次 | +1 |
| 5 | 猛猛上瘾 | lottery | 7次 | +2 |
| 6 | 抽卡享受者 | lottery | 15次 | +5 |

- **自动完成**: 打卡/抽奖后 `on_quest_trigger()` 自动检查并发放积分，打卡时显示完成通知，抽奖静默。
- **进度回滚**: 撤回打卡时 `on_quest_rollback()` 回退进度，若低于已完成任务目标则回收积分。
- **查看进度**: `/周常` 命令分任务显示进度条。
- **周重置**: `WeeklyQuestResetPlugin`（TimedHeartbeatPlugin，周一 08:00）清理过期数据。

---

## 经济系统

### 积分获取

- 周常任务（3个打卡 + 3个抽奖，合计最多 +14）
- 当月全勤 +1
- 打卡幸运 +1
- 抽奖随机获得
- 管理员 `/发金币` 统发

### 抽卡系统 (`/抽奖` `/抽卡`)

**成本:** 1 积分/次，每日首抽免费，商店"抽奖增强"30% 概率免单

**每日次数:**
- 今日打卡: 5 次 + 商店额外次数
- 今日未打卡: 2 次 + 商店额外次数

**概率表 (累计权重 100):**

| 概率 | 奖品 | 值 |
|------|------|-----|
| 40.0% | 积分 | 0 |
| 28.0% | 积分 | +1 |
| 10.0% | 积分 | +2 |
| 6.0% | 积分 | +3 |
| 3.0% | 积分 | +5 |
| 0.8% | 积分 | +8 |
| 0.2% | 积分 | +10 |
| 9.0% | 随机普通称号 | — |
| 2.0% | 随机稀有称号 | — |
| 1.0% | 随机传说称号 | — |

**重复称号退款:** 普通 +1, 稀有 +2, 传说 +3

**抽奖画像:** 追踪 `draw_count`, `duplicate_count`, `zero_streak`, `max_zero_streak`, `has_hit_ten`

### 仙人彩 (`/仙人彩` `下注 XXXX`)

- 投注: 周一 00:00 – 周五 23:59 (北京时间)
- 开奖: 周日 20:00 (北京时间)
- 每次投注消耗 1 积分，选 4 位数字
- 奖池分配: 1 等(4A) 60% / 2 等(3A) 25% / 3 等(2A) 15%
- 无人中奖则滚入下期累积池
- 每个群独立累积

### 积分商店 (`/商店 [product_id]`)

**每周一 08:00 自动刷新**

**轮换商品 (每周随机):**
- 随机 4 个称号
- 每个库存 2 个
- 定价: 普通 3 / 稀有 6 / 传说 10

**固定功能商品 (始终有货):**

| 商品 ID | 价格 | 描述 |
|---------|------|------|
| `fn_extra_draw_pack` | 6 | 额外抽卡包，7 日内每天 +2 次抽卡 |
| `fn_checkin_boost` | 2 | 打卡增强 10 次，每次 10% 概率 +1 积分 |
| `fn_lottery_boost` | 3 | 抽奖增强 10 次，每次 30% 概率免单 |
| `fn_lottery_refresh` | 1 | 清空今日抽卡次数 |

**交易安全:** 使用 `BEGIN IMMEDIATE` 原子事务

### 闹钟系统 (`/闹钟`)

**时间格式:**
- 相对: `X分钟后` `X小时后` `X天后` `X年后`
- 绝对: `YYYY-MM-DD HH:MM`
- 仅时间: `HH:MM`（默认今天）
- 最小提前 5 分钟

**循环类型 (recur_kind):**
- 0: 一次性
- 1: 每 N 日
- 2: 每周 (recur_a=星期几)
- 3: 每月 (recur_a=日)
- 4: 每年

**管理:** `/闹钟 一览` 查看 `/闹钟 取消 <编号>` 取消

---

## 谁是卧底

`who_is_spy` 插件，群+私聊协同的匿名文字游戏。

### 流程

| 步骤 | 位置 | 说明 |
|------|------|------|
| `/创建卧底 [人数]` | 群聊 | 创建房间，默认6人（4-10人），生成4位房间号 |
| `/加入卧底 <房间号>` | 私聊 | 加入房间，获得匿名代号 |
| `/开始卧底 <房间号>` | 群聊 | 房主开始游戏，私聊分配词条 |
| 描述阶段 | 私聊 | 存活玩家各发一句话描述词条，全部提交后匿名广播 |
| 投票阶段 | 私聊 | 存活玩家投票（发编号/①等），票最多者出局 |
| 游戏结束 | 群聊/私聊 | 合并转发记录到群聊，私聊发放称号 |

### 规则

- 词条从 `plugins/who_is_spy/words.json` 随机选取，避开最近10局用词
- 4-5人局1卧底，6-8人局随机1-2卧底，9-10人局2卧底
- 卧底≥平民时卧底胜，卧底全灭时平民胜
- 平票时随机淘汰未得票存活玩家，全员得票时随机平票者

### 称号

9 个累计成就称号，数据记录在 `user_game_stats` 表：

| ID | 名称 | 条件 | 稀有度 |
|----|------|------|--------|
| 301 | 玩家 | 累计参加10场游戏 | 普通 |
| 302 | 老手 | 累计参加50场游戏 | 稀有 |
| 303 | 达人 | 累计参加100场游戏 | 传说 |
| 304 | 常胜 | 累计获胜10场 | 稀有 |
| 305 | 不败 | 累计获胜50场 | 传说 |
| 306 | 🔦 | 平民方累计获胜10场 | 稀有 |
| 307 | 调查员 | 平民方累计获胜50场 | 传说 |
| 308 | 完美伪装 | 卧底方累计获胜10场 | 稀有 |
| 309 | 千面者 | 卧底方累计获胜50场 | 传说 |

---

## 称号系统

### 称号结构 (146 个)

| ID 范围 | 数量 | 稀有度 | 来源 |
|---------|------|--------|------|
| 1–40 | 40 | 普通 | 抽奖（通用梗/FF14 基础职业/Werwolf） |
| 41–59, 60-77 | 31 | 稀有/传说 | 抽奖（高阶职业/FF14 梗） |
| 78–91 | 14 | 普通 | 抽奖（工匠/采集职业） |
| 92–132 | 41 | 普通 | 抽奖（Werwolf 角色表） |
| 201–265 | 65 | 混合 | 条件解锁 |
| 301–309 | 9 | 混合 | 游戏累计成就 |

### 条件称号详情

**时段类:**
早起的鸟儿 (8-12)、下午茶 (14-16)、我下班了 (17:30-18:30)、熬夜冠军 (1-5)、压哨冲线 (周日 23:30-周一 8:00)、日界线 (23:59/00:00)、刚刚好 (00:00)

**日期类:**
劳动模范 (5-1)、愚者 (4-1)、小孩 (6-1)、程序员 (10-24)、Neko (2-22)、画画更重要 (2-14)、我在~ (8-11)、圆周率 (3-14)、回响 (MM=DD)、新年 (1-1)

**累计天数:**
规律作息 (≥30)、时间管理大师 (≥100)、打卡收藏家 (≥200)、不休息的板油 (≥365)

**称号收集:**
搜集 (≥10)、研究员 (≥20)、造物院 (≥30)、称号收藏家 (≥50)、称号大师 (≥100)、金色 (≥1 传说)、小金人 (3 传说全装)

**抽奖统计:**
重复观测 (≥1)、古典概型 (≥10)、正态分布 (≥100)、试试 (≥1)、玩 (≥10)、富有 (≥25)、上瘾 (≥50)、戒戒你好 (≥100)、沉迷抽卡 (≥200)、倾家荡产 (≥500)、无底深渊 (≥1000)、抽抽乐 (≥3)、抽卡成精 (≥75)、攒着抽 (≥150)、挥金如土 (≥300)、抽穿卡池 (≥2000)、大赚 (中 10)、BUG (连 3 次 0)、致命错误 (连 10 次 0)、非气初现 (≥1 次空)、连连看 (连 5 次 0)、非酋认证 (连 15 次 0)、天命之人 (连 30 次 0)

**累计空抽:**
空 (≥1)、酋长 (≥10)、空抽 (≥50)、黑黑 (≥100)、虚空行者 (≥300)

**周常任务:**
任务达人 (≥5)、勤勉板油 (≥15)、劳模奖章 (≥30)、任务狂人 (≥50)

**全清周常:**
周常全清 (≥1 周全清)、任务能手 (≥3 周)、全清达人 (≥5 周)、周常大师 (≥10 周)、任务终结者 (≥20 周)

### 称号管理指令

| 指令 | 功能 |
|------|------|
| `/称号` | 帮助 |
| `/称号 当前` | 查看已装备 |
| `/称号 <index>` | 装备 |
| `/称号 卸下` | 取消装备 |
| `/称号 详情 <index>` | 称号说明 |
| `/称号 随机` | 随机装备 |
| `/称号 查看 @用户` | 查看他人 |
| `/称号一览` | 已解锁列表 |

装备上限 **3 个**（slot 1-3）。

### 概率速算

- 抽卡预期收益 (不含称号): 0.874 积分/次
- 每日 5 次上限 + 首抽免费 = 净支出 ≤ 4 积分
- 打卡全勤 + 首周 + 满月 ≈ 获得 3 积分
- 长期结论: 纯打卡 > 纯抽卡，需靠商店 buff 和称号退款补贴
