feat: 鎵╁睍鏁版嵁搴撴敮鎸佽疆鐩樺拰21鐐规父鎴?- 娣诲姞鍒楀瓨鍦ㄦ€ф鏌ヨ緟鍔╂柟娉?- 鎵╁睍casino_sessions鍜宑asino_bets琛ㄦ坊鍔犳柊瀛楁 - 鍒涘缓casino_blackjack_hands琛ㄥ瓨鍌?1鐐规墜鐗?- 淇敼create_casino_session鏀寔鍗曞満闄愬埗鍜屾柊瀛楁 - 鎵╁睍create_casino_bet鏀寔杞洏鍜?1鐐逛笓鐢ㄥ瓧娈?- 娣诲姞21鐐规墜鐗岀鐞嗘柟娉曢泦

This commit is contained in:
2025-10-31 11:46:29 +08:00
parent cc97374e98
commit 7962852685

View File

@@ -54,6 +54,37 @@ class Database:
raise
return self._conn
def _column_exists(self, table_name: str, column_name: str) -> bool:
"""检查表中列是否存在
Args:
table_name: 表名
column_name: 列名
Returns:
是否存在
"""
cursor = self.conn.cursor()
cursor.execute(f"PRAGMA table_info({table_name})")
columns = [row[1] for row in cursor.fetchall()]
return column_name in columns
def _add_column_if_not_exists(self, table_name: str, column_name: str, column_def: str):
"""安全地添加列(如果不存在)
Args:
table_name: 表名
column_name: 列名
column_def: 列定义(如 "INTEGER""TEXT DEFAULT ''"
"""
if not self._column_exists(table_name, column_name):
try:
cursor = self.conn.cursor()
cursor.execute(f"ALTER TABLE {table_name} ADD COLUMN {column_name} {column_def}")
logger.info(f"为表 {table_name} 添加列 {column_name}")
except Exception as e:
logger.warning(f"添加列失败: {e}")
def init_tables(self):
"""初始化数据库表"""
cursor = self.conn.cursor()
@@ -166,6 +197,20 @@ class Database:
)
""")
# 21点手牌表
cursor.execute("""
CREATE TABLE IF NOT EXISTS casino_blackjack_hands (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
hand_data TEXT NOT NULL,
hand_status TEXT DEFAULT 'playing',
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
FOREIGN KEY (session_id) REFERENCES casino_sessions(id)
)
""")
# 创建索引
cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_casino_bets
@@ -177,6 +222,21 @@ class Database:
ON casino_sessions(chat_id, game_type, status)
""")
cursor.execute("""
CREATE INDEX IF NOT EXISTS idx_casino_blackjack_hands
ON casino_blackjack_hands(session_id, user_id)
""")
# 兼容性检查为casino_sessions表添加新字段
self._add_column_if_not_exists('casino_sessions', 'current_phase', "TEXT DEFAULT 'betting'")
self._add_column_if_not_exists('casino_sessions', 'blackjack_multiplier', 'REAL DEFAULT 1.5')
# 兼容性检查为casino_bets表添加新字段轮盘和21点专用
self._add_column_if_not_exists('casino_bets', 'bet_category', "TEXT")
self._add_column_if_not_exists('casino_bets', 'bet_number', 'INTEGER')
self._add_column_if_not_exists('casino_bets', 'bet_value', "TEXT")
self._add_column_if_not_exists('casino_bets', 'hand_status', "TEXT")
logger.info("数据库表初始化完成")
# ===== 用户相关操作 =====
@@ -654,9 +714,31 @@ class Database:
# ===== 赌场相关操作 =====
def get_any_active_casino_session(self, chat_id: int) -> Optional[Dict]:
"""获取任意活跃的游戏会话(用于单场限制检查)
Args:
chat_id: 会话ID
Returns:
会话信息字典或None
"""
cursor = self.conn.cursor()
cursor.execute("""
SELECT * FROM casino_sessions
WHERE chat_id = ? AND status = 'open'
ORDER BY id DESC LIMIT 1
""", (chat_id,))
row = cursor.fetchone()
if row:
return dict(row)
return None
def create_casino_session(self, chat_id: int, game_type: str, banker_id: int,
min_bet: int, max_bet: int, multiplier: float,
house_fee: float = 0.05) -> int:
house_fee: float = 0.05, current_phase: str = 'betting',
blackjack_multiplier: float = 1.5) -> int:
"""创建新的赌场游戏会话
Args:
@@ -667,6 +749,8 @@ class Database:
max_bet: 最大下注金额
multiplier: 赔率
house_fee: 抽水率
current_phase: 当前阶段(默认'betting'
blackjack_multiplier: 21点黑杰克倍数默认1.5
Returns:
session_id
@@ -674,20 +758,28 @@ class Database:
cursor = self.conn.cursor()
current_time = int(time.time())
# 检查是否已有活跃的会话
# 检查是否已有活跃的会话单场限制同一chat_id只能有一个活跃游戏
existing = self.get_any_active_casino_session(chat_id)
if existing:
# 如果已有活跃游戏返回其ID保持向后兼容但实际应该在应用层阻止
return existing['id']
# 检查是否已有相同game_type的活跃会话向后兼容
cursor.execute("""
SELECT id FROM casino_sessions
WHERE chat_id = ? AND game_type = ? AND status = 'open'
""", (chat_id, game_type))
existing = cursor.fetchone()
if existing:
return existing['id']
existing_same_type = cursor.fetchone()
if existing_same_type:
return existing_same_type['id']
cursor.execute("""
INSERT INTO casino_sessions
(chat_id, game_type, banker_id, min_bet, max_bet, multiplier, house_fee, status, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, 'open', ?)
""", (chat_id, game_type, banker_id, min_bet, max_bet, multiplier, house_fee, current_time))
(chat_id, game_type, banker_id, min_bet, max_bet, multiplier, house_fee,
status, created_at, current_phase, blackjack_multiplier)
VALUES (?, ?, ?, ?, ?, ?, ?, 'open', ?, ?, ?)
""", (chat_id, game_type, banker_id, min_bet, max_bet, multiplier, house_fee,
current_time, current_phase, blackjack_multiplier))
return cursor.lastrowid
@@ -714,16 +806,22 @@ class Database:
return None
def create_casino_bet(self, chat_id: int, game_type: str, user_id: int,
bet_type: str, amount: int, multiplier: float) -> int:
bet_type: str, amount: int, multiplier: float,
bet_category: str = None, bet_number: int = None,
bet_value: str = None, hand_status: str = None) -> int:
"""创建下注记录
Args:
chat_id: 会话ID
game_type: 游戏类型
user_id: 用户ID
bet_type: 下注类型
bet_type: 下注类型(大小游戏:""/""21点"标准"等)
amount: 下注金额
multiplier: 赔率
bet_category: 下注类别(轮盘游戏:["数字"/"颜色"/"奇偶"/"大小"/"区间"]
bet_number: 数字下注轮盘游戏0-36
bet_value: 下注值(轮盘游戏:如"红色""奇数""1-12"等)
hand_status: 手牌状态21点游戏["playing"/"stood"/"busted"/"blackjack"]
Returns:
bet_id
@@ -733,9 +831,11 @@ class Database:
cursor.execute("""
INSERT INTO casino_bets
(chat_id, game_type, user_id, bet_type, amount, multiplier, status, created_at)
VALUES (?, ?, ?, ?, ?, ?, 'pending', ?)
""", (chat_id, game_type, user_id, bet_type, amount, multiplier, current_time))
(chat_id, game_type, user_id, bet_type, amount, multiplier, status, created_at,
bet_category, bet_number, bet_value, hand_status)
VALUES (?, ?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?, ?)
""", (chat_id, game_type, user_id, bet_type, amount, multiplier, current_time,
bet_category, bet_number, bet_value, hand_status))
return cursor.lastrowid
@@ -871,6 +971,107 @@ class Database:
WHERE chat_id = ? AND game_type = ? AND status = 'open'
""", (current_time, chat_id, game_type))
# ===== 21点手牌管理 =====
def create_blackjack_hand(self, session_id: int, user_id: int,
hand_data: List[int], hand_status: str = 'playing') -> int:
"""创建21点手牌记录
Args:
session_id: 会话ID
user_id: 用户ID0表示庄家
hand_data: 手牌列表
hand_status: 手牌状态
Returns:
hand_id
"""
cursor = self.conn.cursor()
current_time = int(time.time())
hand_data_json = json.dumps(hand_data)
cursor.execute("""
INSERT INTO casino_blackjack_hands
(session_id, user_id, hand_data, hand_status, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)
""", (session_id, user_id, hand_data_json, hand_status, current_time, current_time))
return cursor.lastrowid
def get_blackjack_hand(self, session_id: int, user_id: int) -> Optional[Dict]:
"""获取21点手牌
Args:
session_id: 会话ID
user_id: 用户ID
Returns:
手牌信息字典或None
"""
cursor = self.conn.cursor()
cursor.execute("""
SELECT * FROM casino_blackjack_hands
WHERE session_id = ? AND user_id = ?
ORDER BY id DESC LIMIT 1
""", (session_id, user_id))
row = cursor.fetchone()
if row:
hand_dict = dict(row)
hand_dict['hand_data'] = json.loads(hand_dict['hand_data'])
return hand_dict
return None
def update_blackjack_hand(self, session_id: int, user_id: int,
hand_data: List[int], hand_status: str):
"""更新21点手牌
Args:
session_id: 会话ID
user_id: 用户ID
hand_data: 手牌列表
hand_status: 手牌状态
"""
cursor = self.conn.cursor()
current_time = int(time.time())
hand_data_json = json.dumps(hand_data)
cursor.execute("""
UPDATE casino_blackjack_hands
SET hand_data = ?, hand_status = ?, updated_at = ?
WHERE session_id = ? AND user_id = ?
""", (hand_data_json, hand_status, current_time, session_id, user_id))
def get_all_blackjack_hands(self, session_id: int) -> Dict[int, Dict]:
"""获取所有21点手牌用于结算
Args:
session_id: 会话ID
Returns:
手牌字典 {user_id: {'cards': [...], 'status': ...}, ...}
"""
cursor = self.conn.cursor()
cursor.execute("""
SELECT * FROM casino_blackjack_hands
WHERE session_id = ?
ORDER BY user_id, id DESC
""", (session_id,))
rows = cursor.fetchall()
hands_dict = {}
for row in rows:
hand_dict = dict(row)
user_id = hand_dict['user_id']
# 只保留最新的手牌(每个用户)
if user_id not in hands_dict:
hands_dict[user_id] = {
'cards': json.loads(hand_dict['hand_data']),
'status': hand_dict['hand_status']
}
return hands_dict
def close(self):
"""关闭数据库连接"""
if self._conn: