""" 阴阳师抽卡插件 - 抽卡核心逻辑模块 实现抽卡核心算法,包括: - 多稀有度抽卡(R/SR/SSR/SP) - 子池支持 - 保底机制 - 成就检查 """ import random from typing import Dict, Tuple, List, Optional, Any import os from pathlib import Path from .config import Config from .data_manager import DataManager config = Config() data_manager = DataManager() class GachaSystem: """抽卡系统核心类,管理抽卡逻辑和数据""" def __init__(self): self.data_manager = data_manager async def draw(self, user_id: str) -> Dict[str, Any]: """执行一次抽卡""" # 检查抽卡限制 if not await self.data_manager.check_daily_limit(user_id): draws_left = await self.data_manager.get_draws_left(user_id) return { "success": False, "message": f"您今日的抽卡次数已用完,每日限制{config.DAILY_LIMIT}次,明天再来吧!" } # 抽取稀有度(传递用户ID) rarity = self._draw_rarity(user_id) # 从该稀有度中抽取式神 await self.data_manager.ensure_shikigami_data() shikigami_data = self.data_manager.shikigami_data.get(rarity, []) if not shikigami_data: return { "success": False, "message": f"系统错误:{rarity}稀有度下没有可用式神" } # 随机选择式神 shikigami = random.choice(shikigami_data) # xapi 只负责写入抽卡数据;奖励副作用仍由 nonebot handler 编排。 record_result = await self.data_manager.record_draw_result(user_id, rarity, shikigami) if not record_result.get("success"): return { "success": False, "message": record_result.get("message", "抽卡记录写入失败") } return { "success": True, "rarity": record_result.get("rarity", rarity), "name": record_result.get("name", shikigami["name"]), "image_url": record_result.get("image_url") or record_result.get("image_path") or shikigami["image_url"], "draws_left": record_result.get("draws_left", 0), "unlocked_achievements": record_result.get("unlocked_achievements", []) } def _draw_rarity(self, user_id: str = None) -> str: """按概率抽取稀有度""" # 检查是否是特殊概率用户 if user_id and user_id in config.SPECIAL_PROBABILITY_USERS: # 100%概率抽到SSR或SP,随机选择 return random.choice(["SSR", "SP"]) # 普通用户的概率逻辑 r = random.random() * 100 # 0-100的随机数 cumulative = 0 for rarity, prob in config.RARITY_PROBABILITY.items(): cumulative += prob if r < cumulative: return rarity # 默认返回R,理论上不会执行到这里 return "R" async def get_user_stats(self, user_id: str) -> Dict: """获取用户抽卡统计""" return await self.data_manager.get_user_stats(user_id) def get_probability_text(self) -> str: """获取概率展示文本""" probs = config.RARITY_PROBABILITY return f"--- 系统概率 ---\nR: {probs['R']}% | SR: {probs['SR']}% | SSR: {probs['SSR']}% | SP: {probs['SP']}%" async def get_rank_list(self) -> List[Tuple[str, Dict[str, int]]]: """获取抽卡排行榜数据""" items = await self.data_manager.get_rank(limit=10) return [(item["user_id"], item) for item in items] async def get_daily_stats(self) -> Dict: """获取今日抽卡统计""" return await self.data_manager.get_daily_stats() async def triple_draw(self, user_id: str) -> Dict: """执行三连抽""" # 检查是否有足够的抽卡次数 draws_left = await self.data_manager.get_draws_left(user_id) if draws_left < 3: return { "success": False, "message": f"抽卡次数不足,您今日还剩{draws_left}次抽卡机会,三连抽需要3次机会" } results = [] await self.data_manager.ensure_shikigami_data() # 执行三次本地概率抽取,统一提交 xapi 三连写入端点。 for i in range(3): # 抽取稀有度(传递用户ID) rarity = self._draw_rarity(user_id) # 从该稀有度中抽取式神 shikigami_data = self.data_manager.shikigami_data.get(rarity, []) if not shikigami_data: return { "success": False, "message": f"系统错误:{rarity}稀有度下没有可用式神" } # 随机选择式神 shikigami = random.choice(shikigami_data) results.append({ "id": shikigami["id"], "rarity": rarity, "name": shikigami["name"], "image_url": shikigami["image_url"] }) record_result = await self.data_manager.record_triple_draw_result(user_id, results) if not record_result.get("success"): return { "success": False, "message": record_result.get("message", "三连抽记录写入失败") } return { "success": True, "results": record_result.get("results", results), "draws_left": record_result.get("draws_left", 0), "unlocked_achievements": record_result.get("unlocked_achievements", []) } async def get_user_achievements(self, user_id: str) -> Dict: """获取用户成就信息""" achievement_data = await self.data_manager.get_user_achievements(user_id) if not achievement_data["unlocked"] and all(v == 0 for v in achievement_data["progress"].values()): return { "success": False, "message": "您还没有任何成就进度哦!快去抽卡吧!" } return { "success": True, "achievements": achievement_data["unlocked"], "progress": achievement_data["progress"] } async def get_daily_detailed_records(self, date: Optional[str] = None) -> Dict: """获取每日详细抽卡记录""" return await self.data_manager.get_daily_records(date)