📝 继续对数据库进行优化操作
This commit is contained in:
parent
b5334dfc01
commit
6b99ec427c
909
database.py
909
database.py
@ -1,909 +0,0 @@
|
|||||||
import math
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from contextlib import asynccontextmanager
|
|
||||||
from datetime import date, datetime, timedelta
|
|
||||||
from io import StringIO
|
|
||||||
from math import e
|
|
||||||
from typing import Any, Dict, List, Optional
|
|
||||||
|
|
||||||
import aiosqlite
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
|
|
||||||
from .config import g_pJsonManager, g_sDBFilePath, g_sDBPath
|
|
||||||
|
|
||||||
|
|
||||||
class CSqlManager:
|
|
||||||
def __init__(self):
|
|
||||||
g_sDBPath.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def cleanup(cls):
|
|
||||||
if cls.m_pDB:
|
|
||||||
await cls.m_pDB.close()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def init(cls) -> bool:
|
|
||||||
bIsExist = os.path.exists(g_sDBFilePath)
|
|
||||||
|
|
||||||
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
|
|
||||||
cls.m_pDB.row_factory = aiosqlite.Row
|
|
||||||
|
|
||||||
await cls.checkDB()
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@asynccontextmanager
|
|
||||||
async def _transaction(cls):
|
|
||||||
await cls.m_pDB.execute("BEGIN;")
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
except:
|
|
||||||
await cls.m_pDB.execute("ROLLBACK;")
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
await cls.m_pDB.execute("COMMIT;")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getTableInfo(cls, tableName: str) -> list:
|
|
||||||
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', tableName):
|
|
||||||
raise ValueError(f"Illegal table name: {tableName}")
|
|
||||||
try:
|
|
||||||
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
|
|
||||||
rows = await cursor.fetchall()
|
|
||||||
return [{"name": row[1], "type": row[2]} for row in rows]
|
|
||||||
except aiosqlite.Error:
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def ensureTableSchema(cls, tableName: str, columns: dict) -> bool:
|
|
||||||
"""由AI生成
|
|
||||||
创建表或为已存在表添加缺失字段。
|
|
||||||
返回 True 表示有变更(创建或新增列),False 则无操作
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tableName (_type_): 表名
|
|
||||||
columns (_type_): 字典
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
_type_: _description_
|
|
||||||
"""
|
|
||||||
|
|
||||||
info = await cls.getTableInfo(tableName)
|
|
||||||
existing = {col['name']: col['type'].upper() for col in info}
|
|
||||||
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
|
|
||||||
primaryKey = columns.get("PRIMARY KEY", "")
|
|
||||||
|
|
||||||
if not existing:
|
|
||||||
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
|
||||||
if primaryKey:
|
|
||||||
colsDef += f", PRIMARY KEY {primaryKey}"
|
|
||||||
await cls.m_pDB.execute(f'CREATE TABLE "{tableName}" ({colsDef});')
|
|
||||||
return True
|
|
||||||
|
|
||||||
toAdd = [k for k in desired if k not in existing]
|
|
||||||
toRemove = [k for k in existing if k not in desired]
|
|
||||||
typeMismatch = [k for k in desired if k in existing and existing[k] != desired[k]]
|
|
||||||
|
|
||||||
if toAdd and not toRemove and not typeMismatch:
|
|
||||||
for col in toAdd:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
async with cls._transaction():
|
|
||||||
tmpTable = f"{tableName}_new"
|
|
||||||
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
|
||||||
if primaryKey:
|
|
||||||
colsDef += f", PRIMARY KEY {primaryKey}"
|
|
||||||
await cls.m_pDB.execute(f'CREATE TABLE "{tmpTable}" ({colsDef});')
|
|
||||||
|
|
||||||
commonCols = [k for k in desired if k in existing]
|
|
||||||
if commonCols:
|
|
||||||
colsStr = ", ".join(f'"{c}"' for c in commonCols)
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
f'INSERT INTO "{tmpTable}" ({colsStr}) SELECT {colsStr} FROM "{tableName}";'
|
|
||||||
)
|
|
||||||
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
|
||||||
await cls.m_pDB.execute(f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";')
|
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def checkDB(cls) -> bool:
|
|
||||||
#1. 用户表
|
|
||||||
userInfo = {
|
|
||||||
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
||||||
"name": "TEXT NOT NULL",
|
|
||||||
"exp": "INTEGER DEFAULT 0",
|
|
||||||
"point": "INTEGER DEFAULT 0",
|
|
||||||
"soil": "INTEGER DEFAULT 3",
|
|
||||||
"stealing": "TEXT DEFAULT NULL"
|
|
||||||
}
|
|
||||||
#2. 土地表
|
|
||||||
userSoilInfo = {
|
|
||||||
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
||||||
**{f"soil{i}": "TEXT DEFAULT ''" for i in range(1, 31)}
|
|
||||||
}
|
|
||||||
#3. 用户作物明细表
|
|
||||||
userPlant = {
|
|
||||||
"uid": "INTEGER NOT NULL",
|
|
||||||
"plant": "TEXT NOT NULL",
|
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0",
|
|
||||||
#建联合主键保证每个品种一行
|
|
||||||
"PRIMARY KEY": "(uid, plant)"
|
|
||||||
}
|
|
||||||
#4. 用户种子明细表
|
|
||||||
userSeed = {
|
|
||||||
"uid": "INTEGER NOT NULL",
|
|
||||||
"seed": "TEXT NOT NULL",
|
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0",
|
|
||||||
"PRIMARY KEY": "(uid, seed)"
|
|
||||||
}
|
|
||||||
# 5. 用户道具明细表
|
|
||||||
userItem = {
|
|
||||||
"uid": "INTEGER NOT NULL",
|
|
||||||
"item": "TEXT NOT NULL",
|
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0",
|
|
||||||
"PRIMARY KEY": "(uid, item)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#建表(或增列)
|
|
||||||
await cls.ensureTableSchema("user", userInfo)
|
|
||||||
await cls.ensureTableSchema("soil", userSoilInfo)
|
|
||||||
await cls.ensureTableSchema("userPlant", userPlant)
|
|
||||||
await cls.ensureTableSchema("userSeed", userSeed)
|
|
||||||
await cls.ensureTableSchema("userItem", userItem)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def executeDB(cls, command: str) -> bool:
|
|
||||||
"""执行自定义SQL
|
|
||||||
|
|
||||||
Args:
|
|
||||||
command (str): SQL语句
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否执行成功
|
|
||||||
"""
|
|
||||||
if len(command) <= 0:
|
|
||||||
logger.warning("数据库语句长度为空!")
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(command)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning("数据库语句执行出错:" + command)
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def initUserInfoByUid(cls, uid: str, name: str = "", exp: int = 0, point: int = 500):
|
|
||||||
"""初始化用户信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
name (str): 农场名称
|
|
||||||
exp (int): 农场经验
|
|
||||||
point (int): 农场币
|
|
||||||
"""
|
|
||||||
|
|
||||||
#用户信息
|
|
||||||
userInfo = f"""
|
|
||||||
INSERT INTO user (uid, name, exp, point, soil, stealing) VALUES ({uid}, '{name}', {exp}, {point}, 3, '{date.today()}|5')
|
|
||||||
"""
|
|
||||||
|
|
||||||
#用户土地
|
|
||||||
userSoilInfo = f"""
|
|
||||||
INSERT INTO soil (uid) VALUES ({uid});
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not await cls.executeDB(userInfo):
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not await cls.executeDB(userSoilInfo):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return "开通农场成功"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserInfoByUid(cls, uid: str) -> dict:
|
|
||||||
"""根据用户Uid获取用户信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[dict]: 用户信息
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT * FROM user WHERE uid = ?", (uid,)
|
|
||||||
) as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
userDict = {
|
|
||||||
"uid": row[0],
|
|
||||||
"name": row[1],
|
|
||||||
"exp": row[2],
|
|
||||||
"point": row[3],
|
|
||||||
"soil": row[4],
|
|
||||||
"stealing": row[5]
|
|
||||||
}
|
|
||||||
|
|
||||||
return userDict
|
|
||||||
return {}
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"getUserInfoByUid查询失败: {e}")
|
|
||||||
return {}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserNameByUid(cls, uid: str) -> str:
|
|
||||||
"""根据用户uid查询用户名
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: 用户名,如果失败返回空字符串
|
|
||||||
"""
|
|
||||||
if not uid:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT name FROM user WHERE uid = ?",
|
|
||||||
(uid,)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
return row["name"] if row else ""
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场getUserNameByUid查询失败: {e}")
|
|
||||||
return ""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserNameByUid(cls, uid: str, name: str) -> bool:
|
|
||||||
"""根据用户uid修改用户名
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
name (str): 新用户名
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否更新成功
|
|
||||||
"""
|
|
||||||
if not uid or not name:
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE user SET name = ? WHERE uid = ?",
|
|
||||||
(name, uid)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场updateUserNameByUid失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserPointByUid(cls, uid: str) -> int:
|
|
||||||
"""根据用户Uid获取用户农场币
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: 用户农场币
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return -1
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(f"SELECT point FROM user WHERE uid = {uid}") as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
return int(row[0])
|
|
||||||
|
|
||||||
return -1
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"getUserPointByUid查询失败: {e}")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserPointByUid(cls, uid: str, point: int) -> int:
|
|
||||||
"""根据用户Uid修改用户农场币
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
point (int): 要更新的新农场币数量(需 ≥ 0)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: 更新后的农场币数量(成功时),-1(失败时)
|
|
||||||
"""
|
|
||||||
|
|
||||||
if len(uid) <= 0:
|
|
||||||
logger.warning("参数校验失败: uid为空或农场币值无效")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
try:
|
|
||||||
return await cls.executeDB(f"UPDATE user SET point = {point} WHERE uid = {uid}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"金币更新失败: {e}")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserExpByUid(cls, uid: str) -> int:
|
|
||||||
"""根据用户Uid获取用户经验
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: 用户经验值
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return -1
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(f"SELECT exp FROM user WHERE uid = {uid}") as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
return int(row[0])
|
|
||||||
|
|
||||||
return -1
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"getUserLevelByUid查询失败: {e}")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def UpdateUserExpByUid(cls, uid: str, exp: int) -> bool:
|
|
||||||
"""根据用户Uid刷新用户经验
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否成功
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
sql = f"UPDATE user SET exp = '{exp}' WHERE uid = {uid}"
|
|
||||||
|
|
||||||
return await cls.executeDB(sql)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserLevelByUid(cls, uid: str) -> tuple[int, int, int]:
|
|
||||||
"""根据用户Uid获取用户等级
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
tuple[int, int, int]: (当前等级, 下级所需经验, 当前等级剩余经验)
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return -1, -1, -1
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(f"SELECT exp FROM user WHERE uid = {uid}") as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
exp = int(row[0])
|
|
||||||
|
|
||||||
level = exp // 200
|
|
||||||
nextLevelExp = 200 * (level + 1)
|
|
||||||
|
|
||||||
currentLevelExp = level * 200
|
|
||||||
remainingExp = exp - currentLevelExp
|
|
||||||
|
|
||||||
return level, nextLevelExp, remainingExp
|
|
||||||
|
|
||||||
return -1, -1, -1
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"getUserLevelByUid查询失败: {e}")
|
|
||||||
return -1, -1, -1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserSoilByUid(cls, uid: str) -> int:
|
|
||||||
"""根据用户Uid获取解锁地块
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: 解锁几块地
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
async with cls.m_pDB.execute(f"SELECT soil FROM user WHERE uid = {uid}") as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
if not row[0]:
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
return int(row[0])
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserSoilStatusBySoilID(cls, uid: str, soil: str) -> tuple[bool, str]:
|
|
||||||
"""根据土地块获取用户土地状态
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
soil (str): 土地id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
tuple[bool, str]: [是否可以播种,土地信息]
|
|
||||||
"""
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return False, ""
|
|
||||||
|
|
||||||
async with cls.m_pDB.execute(f"SELECT {soil} FROM soil WHERE uid = {uid}") as cursor:
|
|
||||||
async for row in cursor:
|
|
||||||
if row[0] == None or len(row[0]) <= 0:
|
|
||||||
return True, ""
|
|
||||||
else:
|
|
||||||
return False, row[0]
|
|
||||||
|
|
||||||
return False, ""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserSoilStatusByPlantName(cls, uid: str, soil: str,
|
|
||||||
plant: str = "",
|
|
||||||
status: int = 0) -> bool:
|
|
||||||
"""根据种子名称使用户播种
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户Uid
|
|
||||||
soil (str): 土地id
|
|
||||||
plant (str): 种子名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否更新成功
|
|
||||||
"""
|
|
||||||
|
|
||||||
if len(uid) <= 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if len(plant) <= 0 and status == 4:
|
|
||||||
s = f",,,{status},"
|
|
||||||
elif len(plant) <= 0 and status != 4:
|
|
||||||
s = ""
|
|
||||||
else:
|
|
||||||
#获取种子信息 这里能崩我吃
|
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][plant]
|
|
||||||
|
|
||||||
currentTime = datetime.now()
|
|
||||||
newTime = currentTime + timedelta(hours=int(plantInfo['time']))
|
|
||||||
|
|
||||||
#0: 种子名称
|
|
||||||
#1: 种下时间
|
|
||||||
#2: 预计成熟时间
|
|
||||||
#3: 地状态:0:无 1:长草 2:生虫 3:缺水 4:枯萎
|
|
||||||
#4: 是否被偷 示例:QQ号-偷取数量|QQ号-偷取数量
|
|
||||||
#5: 土地等级 0:普通 1:红土地 2:黑土地 3:金土地 4:紫晶土地 5:蓝晶土地 6:黑晶土地
|
|
||||||
s = f"{plant},{int(currentTime.timestamp())},{int(newTime.timestamp())},{status},,"
|
|
||||||
|
|
||||||
sql = f"UPDATE soil SET {soil} = '{s}' WHERE uid = {uid}"
|
|
||||||
|
|
||||||
return await cls.executeDB(sql)
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def addUserSeedByUid(cls, uid: str, seed: str, count: int = 1) -> bool:
|
|
||||||
"""根据用户uid添加种子信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
seed (str): 种子名称
|
|
||||||
count (int): 数量
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否添加成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
#检查是否已存在该种子
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
|
||||||
(uid, seed)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
|
|
||||||
if row:
|
|
||||||
#如果种子已存在,则更新数量
|
|
||||||
newCount = row[0] + count
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
|
||||||
(newCount, uid, seed)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
#如果种子不存在,则插入新记录
|
|
||||||
newCount = count
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
|
||||||
(uid, seed, count)
|
|
||||||
)
|
|
||||||
|
|
||||||
#如果种子数量为 0,删除记录
|
|
||||||
if newCount <= 0:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
|
||||||
(uid, seed)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场addUserSeedByUid 失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserSeedByName(cls, uid: str, seed: str) -> Optional[int]:
|
|
||||||
"""根据种子名称获取种子数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
seed (str): 种子名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Optional[int]: 种子数量
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
|
||||||
(uid, seed)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
return row[0] if row else None
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场getUserSeedByName 查询失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserSeedByUid(cls, uid: str) -> dict:
|
|
||||||
"""根据用户Uid获取仓库全部种子信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: 种子信息
|
|
||||||
"""
|
|
||||||
|
|
||||||
cursor = await cls.m_pDB.execute(
|
|
||||||
"SELECT seed, count FROM userSeed WHERE uid=?",
|
|
||||||
(uid,)
|
|
||||||
)
|
|
||||||
rows = await cursor.fetchall()
|
|
||||||
return {row["seed"]: row["count"] for row in rows}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserSeedByName(cls, uid: str, seed: str, count: int) -> bool:
|
|
||||||
"""根据种子名称更新种子数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
seed (str): 种子名称
|
|
||||||
count (int): 种子数量
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if count <= 0:
|
|
||||||
return await cls.deleteUserSeedByName(uid, seed)
|
|
||||||
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
|
||||||
(count, uid, seed)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场updateUserSeedByName失败:{e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def deleteUserSeedByName(cls, uid: str, seed: str) -> bool:
|
|
||||||
"""根据种子名称从种子仓库中删除种子
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
seed (str): 种子名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
|
||||||
(uid, seed)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场deleteUserSeedByName 删除失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def addUserPlantByUid(cls, uid: str, plant: str, count: int = 1) -> bool:
|
|
||||||
"""根据用户uid添加作物信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
plant (str): 作物名称
|
|
||||||
count (int): 数量
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否添加成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
#检查是否已存在该作物
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
|
||||||
(uid, plant)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
|
|
||||||
if row:
|
|
||||||
#如果作物已存在,则更新数量
|
|
||||||
new_count = row[0] + count
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
|
||||||
(new_count, uid, plant)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
#如果作物不存在,则插入新记录
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
|
||||||
(uid, plant, count)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场addUserPlantByUid 失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserPlantByUid(cls, uid: str) -> Dict[str, int]:
|
|
||||||
"""根据用户uid获取全部作物信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict[str, int]: 作物名称和数量
|
|
||||||
"""
|
|
||||||
cursor = await cls.m_pDB.execute(
|
|
||||||
"SELECT plant, count FROM userPlant WHERE uid=?",
|
|
||||||
(uid,)
|
|
||||||
)
|
|
||||||
rows = await cursor.fetchall()
|
|
||||||
return {row["plant"]: row["count"] for row in rows}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserPlantByName(cls, uid: str, plant: str) -> Optional[int]:
|
|
||||||
"""根据作物名称获取用户的作物数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
plant (str): 作物名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Optional[int]: 作物数量
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
|
||||||
(uid, plant)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
return row[0] if row else None
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场getUserPlantByName 查询失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserPlantByName(cls, uid: str, plant: str, count: int) -> bool:
|
|
||||||
"""更新 userPlant 表中某个作物的数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
plant (str): 作物名称
|
|
||||||
count (int): 新的作物数量
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否更新成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if count <= 0:
|
|
||||||
return await cls.deleteUserPlantByName(uid, plant)
|
|
||||||
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
|
||||||
(count, uid, plant)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场updateUserPlantByName失败:{e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def deleteUserPlantByName(cls, uid: str, plant: str) -> bool:
|
|
||||||
"""从 userPlant 表中删除某个作物记录
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
plant (str): 作物名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否删除成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
|
||||||
(uid, plant)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场deleteUserPlantByName 失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserItemByName(cls, uid: str, item: str) -> Optional[int]:
|
|
||||||
"""根据道具名称查询某一项数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
item (str): 道具名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Optional[int]: 数量(不存在返回None)
|
|
||||||
"""
|
|
||||||
if not uid or not item:
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
|
||||||
(uid, item)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
return row[0] if row else None
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场getUserItemByName查询失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def getUserItemByUid(cls, uid: str) -> dict:
|
|
||||||
"""根据用户Uid获取全部道具信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: {itemName: count, ...}
|
|
||||||
"""
|
|
||||||
if not uid:
|
|
||||||
return {}
|
|
||||||
try:
|
|
||||||
cursor = await cls.m_pDB.execute(
|
|
||||||
"SELECT item, count FROM userItem WHERE uid = ?",
|
|
||||||
(uid,)
|
|
||||||
)
|
|
||||||
rows = await cursor.fetchall()
|
|
||||||
return {row["item"]: row["count"] for row in rows}
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场getUserItemByUid查询失败: {e}")
|
|
||||||
return {}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def deleteUserItemByName(cls, uid: str, item: str) -> bool:
|
|
||||||
"""根据道具名删除道具
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
item (str): 道具名称
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否删除成功
|
|
||||||
"""
|
|
||||||
if not uid or not item:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
|
||||||
(uid, item)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场deleteUserItemByName失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def updateUserItemByName(cls, uid: str, item: str, count: int) -> bool:
|
|
||||||
"""根据道具名直接更新道具数量
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
item (str): 道具名称
|
|
||||||
count (int): 要更新的新数量
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否更新成功
|
|
||||||
"""
|
|
||||||
if not uid or not item:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
if count <= 0:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
|
||||||
(uid, item)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
|
||||||
(count, uid, item)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场updateUserItemByName失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def addUserItemByUid(cls, uid: str, item: str, count: int = 1) -> bool:
|
|
||||||
"""根据用户uid添加道具信息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
uid (str): 用户uid
|
|
||||||
item (str): 道具名称
|
|
||||||
count (int, optional): 数量.Defaults to 1.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否添加成功
|
|
||||||
"""
|
|
||||||
if not uid or not item:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
async with cls._transaction():
|
|
||||||
async with cls.m_pDB.execute(
|
|
||||||
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
|
||||||
(uid, item)
|
|
||||||
) as cursor:
|
|
||||||
row = await cursor.fetchone()
|
|
||||||
|
|
||||||
if row:
|
|
||||||
newCount = row[0] + count
|
|
||||||
if newCount <= 0:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
|
||||||
(uid, item)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
|
||||||
(newCount, uid, item)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if count > 0:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
|
|
||||||
(uid, item, count)
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"真寻农场addUserItemByUid失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
g_pSqlManager = CSqlManager()
|
|
||||||
133
database/database.py
Normal file
133
database/database.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import math
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
from ..config import g_sDBFilePath, g_sDBPath
|
||||||
|
from ..dbService import g_pDBService
|
||||||
|
|
||||||
|
|
||||||
|
class CSqlManager:
|
||||||
|
def __init__(self):
|
||||||
|
g_sDBPath.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def cleanup(cls):
|
||||||
|
if cls.m_pDB:
|
||||||
|
await cls.m_pDB.close()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def init(cls) -> bool:
|
||||||
|
bIsExist = os.path.exists(g_sDBFilePath)
|
||||||
|
|
||||||
|
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
|
||||||
|
cls.m_pDB.row_factory = aiosqlite.Row
|
||||||
|
|
||||||
|
await g_pDBService.init()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@asynccontextmanager
|
||||||
|
async def _transaction(cls):
|
||||||
|
await cls.m_pDB.execute("BEGIN;")
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except:
|
||||||
|
await cls.m_pDB.execute("ROLLBACK;")
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
await cls.m_pDB.execute("COMMIT;")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getTableInfo(cls, tableName: str) -> list:
|
||||||
|
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', tableName):
|
||||||
|
raise ValueError(f"Illegal table name: {tableName}")
|
||||||
|
try:
|
||||||
|
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [{"name": row[1], "type": row[2]} for row in rows]
|
||||||
|
except aiosqlite.Error:
|
||||||
|
return []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def ensureTableSchema(cls, tableName: str, columns: dict) -> bool:
|
||||||
|
"""由AI生成
|
||||||
|
创建表或为已存在表添加缺失字段。
|
||||||
|
返回 True 表示有变更(创建或新增列),False 则无操作
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tableName (_type_): 表名
|
||||||
|
columns (_type_): 字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
|
|
||||||
|
info = await cls.getTableInfo(tableName)
|
||||||
|
existing = {col['name']: col['type'].upper() for col in info}
|
||||||
|
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
|
||||||
|
primaryKey = columns.get("PRIMARY KEY", "")
|
||||||
|
|
||||||
|
if not existing:
|
||||||
|
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
||||||
|
if primaryKey:
|
||||||
|
colsDef += f", PRIMARY KEY {primaryKey}"
|
||||||
|
await cls.m_pDB.execute(f'CREATE TABLE "{tableName}" ({colsDef});')
|
||||||
|
return True
|
||||||
|
|
||||||
|
toAdd = [k for k in desired if k not in existing]
|
||||||
|
toRemove = [k for k in existing if k not in desired]
|
||||||
|
typeMismatch = [k for k in desired if k in existing and existing[k] != desired[k]]
|
||||||
|
|
||||||
|
if toAdd and not toRemove and not typeMismatch:
|
||||||
|
for col in toAdd:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async with cls._transaction():
|
||||||
|
tmpTable = f"{tableName}_new"
|
||||||
|
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
||||||
|
if primaryKey:
|
||||||
|
colsDef += f", PRIMARY KEY {primaryKey}"
|
||||||
|
await cls.m_pDB.execute(f'CREATE TABLE "{tmpTable}" ({colsDef});')
|
||||||
|
|
||||||
|
commonCols = [k for k in desired if k in existing]
|
||||||
|
if commonCols:
|
||||||
|
colsStr = ", ".join(f'"{c}"' for c in commonCols)
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
f'INSERT INTO "{tmpTable}" ({colsStr}) SELECT {colsStr} FROM "{tableName}";'
|
||||||
|
)
|
||||||
|
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
||||||
|
await cls.m_pDB.execute(f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";')
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def executeDB(cls, command: str) -> bool:
|
||||||
|
"""执行自定义SQL
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): SQL语句
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否执行成功
|
||||||
|
"""
|
||||||
|
if len(command) <= 0:
|
||||||
|
logger.warning("数据库语句长度为空!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(command)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("数据库语句执行出错:" + command, e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
g_pSqlManager = CSqlManager()
|
||||||
400
database/user.py
Normal file
400
database/user.py
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
from datetime import date, datetime, timedelta
|
||||||
|
from typing import List, Union
|
||||||
|
|
||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class CUserDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
"""初始化用户表结构,确保user表存在且字段完整"""
|
||||||
|
# 用户Uid
|
||||||
|
# 农场名称
|
||||||
|
# 经验值
|
||||||
|
# 金币
|
||||||
|
# 解锁土地数量
|
||||||
|
# 偷菜时间字符串
|
||||||
|
# 剩余偷菜次数
|
||||||
|
userInfo = {
|
||||||
|
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
|
||||||
|
"name": "TEXT NOT NULL",
|
||||||
|
"exp": "INTEGER DEFAULT 0",
|
||||||
|
"point": "INTEGER DEFAULT 0",
|
||||||
|
"soil": "INTEGER DEFAULT 3",
|
||||||
|
"stealTime": "TEXT DEFAULT NULL",
|
||||||
|
"stealCount": "INTEGER DEFAULT 0"
|
||||||
|
}
|
||||||
|
await cls.ensureTableSchema("user", userInfo)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def initUserInfoByUid(cls, uid: str, name: str = "", exp: int = 0, point: int = 500) -> Union[bool, str]:
|
||||||
|
"""初始化用户信息,包含初始偷菜时间字符串与次数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
name (str): 农场名称
|
||||||
|
exp (int): 农场经验
|
||||||
|
point (int): 农场币
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Union[bool, str]: False 表示失败,字符串表示成功信息
|
||||||
|
"""
|
||||||
|
nowStr = date.today().strftime('%Y-%m-%d')
|
||||||
|
sql = (
|
||||||
|
f"INSERT INTO user (uid, name, exp, point, soil, stealTime, stealCount) "
|
||||||
|
f"VALUES ({uid}, '{name}', {exp}, {point}, 3, '{nowStr}', 5)"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(sql)
|
||||||
|
return "开通农场成功"
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("initUserInfoByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getAllUsers(cls) -> List[str]:
|
||||||
|
"""获取所有用户UID列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[str]: 用户UID列表
|
||||||
|
"""
|
||||||
|
cursor = await cls.m_pDB.execute("SELECT uid FROM user")
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [row[0] for row in rows]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserInfoByUid(cls, uid: str) -> dict:
|
||||||
|
"""获取指定用户完整信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含所有用户字段的字典
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT * FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
async for row in cursor:
|
||||||
|
return {
|
||||||
|
"uid": row[0],
|
||||||
|
"name": row[1],
|
||||||
|
"exp": row[2],
|
||||||
|
"point": row[3],
|
||||||
|
"soil": row[4],
|
||||||
|
"stealTime": row[5] or "",
|
||||||
|
"stealCount": int(row[6])
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserInfoByUid 查询失败!", e=e)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserNameByUid(cls, uid: str) -> str:
|
||||||
|
"""根据用户Uid获取用户名
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 用户名,失败返回空字符串
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return ""
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT name FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row["name"] if row else ""
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserNameByUid 查询失败!", e=e)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserNameByUid(cls, uid: str, name: str) -> bool:
|
||||||
|
"""根据用户Uid更新用户名
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
name (str): 新用户名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid or not name:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET name = ? WHERE uid = ?", (name, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("updateUserNameByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserPointByUid(cls, uid: str) -> int:
|
||||||
|
"""获取指定用户农场币
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 农场币数量,失败返回 -1
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return -1
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT point FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return int(row[0]) if row and row[0] is not None else -1
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserPointByUid 查询失败!", e=e)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserPointByUid(cls, uid: str, point: int) -> bool:
|
||||||
|
"""根据用户Uid更新农场币数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
point (int): 新农场币数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid or point < 0:
|
||||||
|
logger.warning("updateUserPointByUid 参数校验失败!")
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET point = ? WHERE uid = ?", (point, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("updateUserPointByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserExpByUid(cls, uid: str) -> int:
|
||||||
|
"""获取指定用户经验值
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 经验值,失败返回 -1
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return -1
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT exp FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return int(row[0]) if row and row[0] is not None else -1
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserExpByUid 查询失败!", e=e)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserExpByUid(cls, uid: str, exp: int) -> bool:
|
||||||
|
"""根据用户Uid更新经验值
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
exp (int): 新经验值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET exp = ? WHERE uid = ?", (exp, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("updateUserExpByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserLevelByUid(cls, uid: str) -> tuple[int, int, int]:
|
||||||
|
"""获取用户等级信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[int, int, int]: (当前等级, 下级所需经验, 当前等级剩余经验),失败返回(-1, -1, -1)
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return -1, -1, -1
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT exp FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
if row and row[0] is not None:
|
||||||
|
expVal = int(row[0])
|
||||||
|
level = expVal // 200
|
||||||
|
nextLevelExp = 200 * (level + 1)
|
||||||
|
currentLevelExp = level * 200
|
||||||
|
remainingExp = expVal - currentLevelExp
|
||||||
|
return level, nextLevelExp, remainingExp
|
||||||
|
return -1, -1, -1
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserLevelByUid 查询失败!", e=e)
|
||||||
|
return -1, -1, -1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserSoilByUid(cls, uid: str) -> int:
|
||||||
|
"""获取解锁土地数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 解锁土地块数,失败返回0
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return 0
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT soil FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return int(row[0]) if row and row[0] is not None else 0
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getUserSoilByUid 查询失败!", e=e)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserSoilByUid(cls, uid: str, soil: int) -> bool:
|
||||||
|
"""更新指定用户解锁土地数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
soil (int): 新土地数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 更新成功返回True,否则False
|
||||||
|
"""
|
||||||
|
if not uid or soil < 0:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET soil = ? WHERE uid = ?", (soil, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("updateUserSoilByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getStealTimeByUid(cls, uid: str) -> str:
|
||||||
|
"""根据用户Uid获取偷菜时间字符串
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 偷菜时间字符串,失败返回空字符串
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return ""
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT stealTime FROM user WHERE uid = ?", (uid,
|
||||||
|
)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] if row and row[0] else ""
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getStealTimeByUid 查询失败!", e=e)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateStealTimeByUid(cls, uid: str, stealTime: str) -> bool:
|
||||||
|
"""根据用户Uid更新偷菜时间字符串
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
stealTime (str): 新偷菜时间字符串
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid or not stealTime:
|
||||||
|
logger.warning("updateStealTimeByUid 参数校验失败!")
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET stealTime = ? WHERE uid = ?", (stealTime, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("updateStealTimeByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getStealCountByUid(cls, uid: str) -> int:
|
||||||
|
"""根据用户Uid获取剩余偷菜次数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 剩余偷菜次数,失败返回 -1
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return -1
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT stealCount FROM user WHERE uid = ?", (uid,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return int(row[0]) if row and row[0] is not None else 0
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("getStealCountByUid 查询失败!", e=e)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateStealCountByUid(cls, uid: str, stealCount: int) -> bool:
|
||||||
|
"""根据用户Uid更新剩余偷菜次数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
stealCount (int): 新剩余偷菜次数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid or stealCount < 0:
|
||||||
|
logger.warning("updateStealCountByUid 参数校验失败!")
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE user SET stealCount = ? WHERE uid = ?", (stealCount, uid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("updateStealCountByUid 事务执行失败!", e=e)
|
||||||
|
return False
|
||||||
168
database/userItem.py
Normal file
168
database/userItem.py
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class CUserItemDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
#用户Uid
|
||||||
|
#物品名称
|
||||||
|
#数量
|
||||||
|
userItem = {
|
||||||
|
"uid": "INTEGER NOT NULL",
|
||||||
|
"item": "TEXT NOT NULL",
|
||||||
|
"count": "INTEGER NOT NULL DEFAULT 0",
|
||||||
|
"PRIMARY KEY": "(uid, item)"
|
||||||
|
}
|
||||||
|
|
||||||
|
await cls.ensureTableSchema("userItem", userItem)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserItemByName(cls, uid: str, item: str) -> Optional[int]:
|
||||||
|
"""根据道具名称查询某一项数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
item (str): 道具名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[int]: 数量(不存在返回None)
|
||||||
|
"""
|
||||||
|
if not uid or not item:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
||||||
|
(uid, item)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] if row else None
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场getUserItemByName查询失败!", e=e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserItemByUid(cls, uid: str) -> dict:
|
||||||
|
"""根据用户Uid获取全部道具信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: {itemName: count, ...}
|
||||||
|
"""
|
||||||
|
if not uid:
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT item, count FROM userItem WHERE uid = ?",
|
||||||
|
(uid,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return {row["item"]: row["count"] for row in rows}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场getUserItemByUid查询失败!", e=e)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def deleteUserItemByName(cls, uid: str, item: str) -> bool:
|
||||||
|
"""根据道具名删除道具
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
item (str): 道具名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否删除成功
|
||||||
|
"""
|
||||||
|
if not uid or not item:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
||||||
|
(uid, item)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场deleteUserItemByName失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserItemByName(cls, uid: str, item: str, count: int) -> bool:
|
||||||
|
"""根据道具名直接更新道具数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
item (str): 道具名称
|
||||||
|
count (int): 要更新的新数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
if not uid or not item:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
if count <= 0:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
||||||
|
(uid, item)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
||||||
|
(count, uid, item)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场updateUserItemByName失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def addUserItemByUid(cls, uid: str, item: str, count: int = 1) -> bool:
|
||||||
|
"""根据用户uid添加道具信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
item (str): 道具名称
|
||||||
|
count (int, optional): 数量.Defaults to 1.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否添加成功
|
||||||
|
"""
|
||||||
|
if not uid or not item:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
||||||
|
(uid, item)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
newCount = row[0] + count
|
||||||
|
if newCount <= 0:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
||||||
|
(uid, item)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
||||||
|
(newCount, uid, item)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if count > 0:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
|
||||||
|
(uid, item, count)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场addUserItemByUid失败!", e=e)
|
||||||
|
return False
|
||||||
147
database/userPlant.py
Normal file
147
database/userPlant.py
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class CUserPlantDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
#用户UiD
|
||||||
|
#作物名称
|
||||||
|
#数量
|
||||||
|
userPlant = {
|
||||||
|
"uid": "INTEGER NOT NULL",
|
||||||
|
"plant": "TEXT NOT NULL",
|
||||||
|
"count": "INTEGER NOT NULL DEFAULT 0",
|
||||||
|
"PRIMARY KEY": "(uid, plant)"
|
||||||
|
}
|
||||||
|
|
||||||
|
await cls.ensureTableSchema("userPlant", userPlant)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def addUserPlantByUid(cls, uid: str, plant: str, count: int = 1) -> bool:
|
||||||
|
"""根据用户uid添加作物信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
count (int): 数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否添加成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
#检查是否已存在该作物
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
||||||
|
(uid, plant)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
#如果作物已存在,则更新数量
|
||||||
|
new_count = row[0] + count
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
||||||
|
(new_count, uid, plant)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
#如果作物不存在,则插入新记录
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
||||||
|
(uid, plant, count)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场addUserPlantByUid 失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserPlantByUid(cls, uid: str) -> Dict[str, int]:
|
||||||
|
"""根据用户uid获取全部作物信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict[str, int]: 作物名称和数量
|
||||||
|
"""
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT plant, count FROM userPlant WHERE uid=?",
|
||||||
|
(uid,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return {row["plant"]: row["count"] for row in rows}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserPlantByName(cls, uid: str, plant: str) -> Optional[int]:
|
||||||
|
"""根据作物名称获取用户的作物数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[int]: 作物数量
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
||||||
|
(uid, plant)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] if row else None
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场getUserPlantByName 查询失败!", e=e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserPlantByName(cls, uid: str, plant: str, count: int) -> bool:
|
||||||
|
"""更新 userPlant 表中某个作物的数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
count (int): 新的作物数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否更新成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if count <= 0:
|
||||||
|
return await cls.deleteUserPlantByName(uid, plant)
|
||||||
|
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
||||||
|
(count, uid, plant)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场updateUserPlantByName失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def deleteUserPlantByName(cls, uid: str, plant: str) -> bool:
|
||||||
|
"""从 userPlant 表中删除某个作物记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
plant (str): 作物名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否删除成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
||||||
|
(uid, plant)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场deleteUserPlantByName 失败!", e=e)
|
||||||
|
return False
|
||||||
157
database/userSeed.py
Normal file
157
database/userSeed.py
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class CUserSeedDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
#用户Uid
|
||||||
|
#种子名称
|
||||||
|
#数量
|
||||||
|
userSeed = {
|
||||||
|
"uid": "INTEGER NOT NULL",
|
||||||
|
"seed": "TEXT NOT NULL",
|
||||||
|
"count": "INTEGER NOT NULL DEFAULT 0",
|
||||||
|
"PRIMARY KEY": "(uid, seed)"
|
||||||
|
}
|
||||||
|
|
||||||
|
await cls.ensureTableSchema("userSeed", userSeed)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def addUserSeedByUid(cls, uid: str, seed: str, count: int = 1) -> bool:
|
||||||
|
"""根据用户uid添加种子信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
seed (str): 种子名称
|
||||||
|
count (int): 数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否添加成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
#检查是否已存在该种子
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
|
(uid, seed)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
#如果种子已存在,则更新数量
|
||||||
|
newCount = row[0] + count
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
|
(newCount, uid, seed)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
#如果种子不存在,则插入新记录
|
||||||
|
newCount = count
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
||||||
|
(uid, seed, count)
|
||||||
|
)
|
||||||
|
|
||||||
|
#如果种子数量为 0,删除记录
|
||||||
|
if newCount <= 0:
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
|
(uid, seed)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场addUserSeedByUid 失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserSeedByName(cls, uid: str, seed: str) -> Optional[int]:
|
||||||
|
"""根据种子名称获取种子数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
seed (str): 种子名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[int]: 种子数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
|
(uid, seed)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] if row else None
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场getUserSeedByName 查询失败!", e=e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserSeedByUid(cls, uid: str) -> dict:
|
||||||
|
"""根据用户Uid获取仓库全部种子信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 种子信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT seed, count FROM userSeed WHERE uid=?",
|
||||||
|
(uid,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return {row["seed"]: row["count"] for row in rows}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserSeedByName(cls, uid: str, seed: str, count: int) -> bool:
|
||||||
|
"""根据种子名称更新种子数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
seed (str): 种子名称
|
||||||
|
count (int): 种子数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if count <= 0:
|
||||||
|
return await cls.deleteUserSeedByName(uid, seed)
|
||||||
|
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
|
(count, uid, seed)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场updateUserSeedByName失败!", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def deleteUserSeedByName(cls, uid: str, seed: str) -> bool:
|
||||||
|
"""根据种子名称从种子仓库中删除种子
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
seed (str): 种子名称
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
|
(uid, seed)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场deleteUserSeedByName 删除失败!", e=e)
|
||||||
|
return False
|
||||||
261
database/userSoil.py
Normal file
261
database/userSoil.py
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
from datetime import date, datetime, timedelta
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
from ..config import g_pJsonManager
|
||||||
|
from ..dbService import g_pDBService
|
||||||
|
|
||||||
|
|
||||||
|
class CUserSoilDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
#用户Uid
|
||||||
|
#地块索引从1开始
|
||||||
|
#作物名称
|
||||||
|
#播种时间
|
||||||
|
#成熟时间
|
||||||
|
#土地等级 0=普通地,1=红土地,2=黑土地,3=金土地
|
||||||
|
#枯萎状态 0=未枯萎,1=枯萎
|
||||||
|
#施肥状态 0=未施肥,1=施肥
|
||||||
|
#虫害状态 0=无虫害,1=有虫害
|
||||||
|
#杂草状态 0=无杂草,1=有杂草
|
||||||
|
#缺水状态 0=不缺水,1=缺水
|
||||||
|
userSoil = {
|
||||||
|
"uid": "TEXT NOT NULL",
|
||||||
|
"soilIndex": "INTEGER NOT NULL",
|
||||||
|
"plantName": "TEXT DEFAULT ''",
|
||||||
|
"plantTime": "INTEGER DEFAULT 0",
|
||||||
|
"matureTime": "INTEGER DEFAULT 0",
|
||||||
|
"soilLevel": "INTEGER DEFAULT 0",
|
||||||
|
"wiltStatus": "INTEGER DEFAULT 0",
|
||||||
|
"fertilizerStatus": "INTEGER DEFAULT 0",
|
||||||
|
"bugStatus": "INTEGER DEFAULT 0",
|
||||||
|
"weedStatus": "INTEGER DEFAULT 0",
|
||||||
|
"waterStatus": "INTEGER DEFAULT 0",
|
||||||
|
"PRIMARY KEY": "(uid, soilIndex)"
|
||||||
|
}
|
||||||
|
|
||||||
|
await cls.ensureTableSchema("userSoil", userSoil)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserFarmByUid(cls, uid: str) -> dict:
|
||||||
|
"""获取指定用户的旧农场数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含字段名-值的字典; 若无数据则返回空字典
|
||||||
|
"""
|
||||||
|
cursor = await cls.m_pDB.execute("SELECT * FROM soil WHERE uid = ?", (uid,))
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
if not row:
|
||||||
|
return {}
|
||||||
|
columns = [description[0] for description in cursor.description]
|
||||||
|
return dict(zip(columns, row))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def migrateOldFarmData(cls):
|
||||||
|
"""迁移旧土地数据到新表 userSoil 并删除旧表
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
aiosqlite.Error: 数据库操作失败时抛出
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
async with cls._transaction():
|
||||||
|
users = await g_pDBService.user.getAllUsers()
|
||||||
|
for uid in users:
|
||||||
|
farmInfo = await cls.getUserFarmByUid(uid)
|
||||||
|
for i in range(1, 31):
|
||||||
|
soilName = f"soil{i}"
|
||||||
|
if soilName not in farmInfo:
|
||||||
|
continue
|
||||||
|
soilData = farmInfo[soilName]
|
||||||
|
if not soilData:
|
||||||
|
continue
|
||||||
|
|
||||||
|
fields = soilData.split(',')
|
||||||
|
if len(fields) < 6:
|
||||||
|
continue
|
||||||
|
|
||||||
|
plantName = fields[0]
|
||||||
|
plantTime = int(fields[1])
|
||||||
|
matureTime = int(fields[2])
|
||||||
|
soilLevel = int(fields[5])
|
||||||
|
|
||||||
|
# 构建新的土地数据
|
||||||
|
soilInfo = {
|
||||||
|
"uid": uid,
|
||||||
|
"soilIndex": i,
|
||||||
|
"plantName": plantName,
|
||||||
|
"plantTime": plantTime,
|
||||||
|
"matureTime": matureTime,
|
||||||
|
"soilLevel": soilLevel,
|
||||||
|
"wiltStatus":0,
|
||||||
|
"fertilizerStatus": 0,
|
||||||
|
"bugStatus": 0,
|
||||||
|
"weedStatus": 0,
|
||||||
|
"waterStatus": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
await cls.insertUserSoil(soilInfo)
|
||||||
|
|
||||||
|
# 彻底清除旧表
|
||||||
|
await cls.m_pDB.execute("DROP TABLE soil")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def insertUserSoil(cls, soilInfo: dict):
|
||||||
|
"""插入一条新的 userSoil 记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
soilInfo (dict): 新土地数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"INSERT INTO userSoil (uid, soilIndex, plantName, plantTime, matureTime, soilLevel, fertilizerStatus, bugStatus, weedStatus, waterStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
soilInfo["uid"],
|
||||||
|
soilInfo["soilIndex"],
|
||||||
|
soilInfo.get("plantName", ""),
|
||||||
|
soilInfo.get("plantTime", 0),
|
||||||
|
soilInfo.get("matureTime", 0),
|
||||||
|
soilInfo.get("soilLevel", 0),
|
||||||
|
soilInfo.get("fertilizerStatus", 0),
|
||||||
|
soilInfo.get("bugStatus", 0),
|
||||||
|
soilInfo.get("weedStatus", 0),
|
||||||
|
soilInfo.get("waterStatus", 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserSoil(cls, uid: str, soilIndex: int) -> Optional[dict]:
|
||||||
|
"""获取指定用户某块土地的详细信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
soilIndex (int): 土地索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[dict]: 记录存在返回字段-值字典,否则返回 None
|
||||||
|
"""
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT * FROM userSoil WHERE uid = ? AND soilIndex = ?",
|
||||||
|
(uid, soilIndex)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
if not row:
|
||||||
|
return None
|
||||||
|
columns = [description[0] for description in cursor.description]
|
||||||
|
return dict(zip(columns, row))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateUserSoil(cls, uid: str, soilIndex: int, field: str, value):
|
||||||
|
"""更新指定用户土地的单个字段
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
soilIndex (int): 土地索引
|
||||||
|
field (str): 需更新的字段名
|
||||||
|
value: 新值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
f"UPDATE userSoil SET {field} = ? WHERE uid = ? AND soilIndex = ?",
|
||||||
|
(value, uid, soilIndex)
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def deleteUserSoil(cls, uid: str, soilIndex: int):
|
||||||
|
"""删除指定用户的土地记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
soilIndex (int): 土地索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
"DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?",
|
||||||
|
(uid, soilIndex)
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def isSoilPlanted(cls, uid: str, soilIndex: int) -> bool:
|
||||||
|
"""判断指定用户的指定土地是否已种植
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
soilIndex (int): 土地索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 如果 plantName 不为空且 plantTime 大于 0,则视为已种植,返回 True;否则 False
|
||||||
|
"""
|
||||||
|
soilInfo = await cls.getUserSoil(uid, soilIndex)
|
||||||
|
if not soilInfo:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return bool(soilInfo.get("plantName")) and soilInfo.get("plantTime", 0) > 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def sowingByPlantName(cls, uid: str, soilIndex: int, plantName: str) -> bool:
|
||||||
|
"""播种指定作物到用户土地区
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户ID
|
||||||
|
soilIndex (int): 土地区索引
|
||||||
|
plantName (str): 植物名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 播种成功返回 True,否则返回 False
|
||||||
|
"""
|
||||||
|
# 校验土地区是否已种植
|
||||||
|
soilRecord = await cls.getUserSoil(uid, soilIndex)
|
||||||
|
if soilRecord and soilRecord.get("plantName"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 获取植物配置
|
||||||
|
plantCfg = g_pJsonManager.m_pPlant.get("plant", {}).get(plantName)
|
||||||
|
if not plantCfg:
|
||||||
|
logger.error(f"未知植物: {plantName}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
nowTs = int(datetime.now().timestamp())
|
||||||
|
matureTs = nowTs + int(plantCfg.get("time", 0)) * 3600
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
# 复用原有记录字段,保留土壤状态等信息
|
||||||
|
prev = soilRecord or {}
|
||||||
|
await cls.deleteUserSoil(uid, soilIndex)
|
||||||
|
await cls.insertUserSoil({
|
||||||
|
"uid": uid,
|
||||||
|
"soilIndex": soilIndex,
|
||||||
|
"plantName": plantName,
|
||||||
|
"plantTime": nowTs,
|
||||||
|
"matureTime": matureTs,
|
||||||
|
# 保留之前的土壤等级和状态字段,避免数据丢失
|
||||||
|
"soilLevel": prev.get("soilLevel", 0),
|
||||||
|
"wiltStatus": prev.get("wiltStatus", 0),
|
||||||
|
"fertilizerStatus": prev.get("fertilizerStatus", 0),
|
||||||
|
"bugStatus": prev.get("bugStatus", 0),
|
||||||
|
"weedStatus": prev.get("weedStatus", 0),
|
||||||
|
"waterStatus": prev.get("waterStatus", 0)
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"真寻农场播种失败!", e=e)
|
||||||
|
return False
|
||||||
228
database/userSteal.py
Normal file
228
database/userSteal.py
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
from database import CSqlManager
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class CUserStealDB(CSqlManager):
|
||||||
|
@classmethod
|
||||||
|
async def initDB(cls):
|
||||||
|
# 被偷用户Uid
|
||||||
|
# 被偷的地块索引 从1开始
|
||||||
|
# 偷菜用户Uid
|
||||||
|
# 被偷数量
|
||||||
|
# 被偷时间
|
||||||
|
userSteal = {
|
||||||
|
"uid": "TEXT NOT NULL",
|
||||||
|
"soilIndex": "INTEGER NOT NULL",
|
||||||
|
"stealerUid": "TEXT NOT NULL",
|
||||||
|
"stealCount": "INTEGER NOT NULL",
|
||||||
|
"stealTime": "INTEGER NOT NULL",
|
||||||
|
"PRIMARY KEY": "(uid, soilIndex, stealerUid)"
|
||||||
|
}
|
||||||
|
await cls.ensureTableSchema("userSteal", userSteal)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def addStealRecord(cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int) -> bool:
|
||||||
|
"""添加偷菜记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
stealerUid (str): 偷菜用户Uid
|
||||||
|
stealCount (int): 被偷数量
|
||||||
|
stealTime (int): 被偷时间(时间戳)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 操作是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
'INSERT INTO "userSteal"(uid, soilIndex, stealerUid, stealCount, stealTime) VALUES(?, ?, ?, ?, ?);',
|
||||||
|
(uid, soilIndex, stealerUid, stealCount, stealTime)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("添加偷菜记录失败", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getStealRecordsByUid(cls, uid: str) -> list:
|
||||||
|
"""根据用户Uid获取所有偷菜记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: 偷菜记录字典列表,每条包含 soilIndex, stealerUid, stealCount, stealTime
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
'SELECT soilIndex, stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=?;',
|
||||||
|
(uid,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"uid": uid,
|
||||||
|
"soilIndex": row[0],
|
||||||
|
"stealerUid": row[1],
|
||||||
|
"stealCount": row[2],
|
||||||
|
"stealTime": row[3]
|
||||||
|
}
|
||||||
|
for row in rows
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("获取偷菜记录失败", e=e)
|
||||||
|
return []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getStealRecord(cls, uid: str, soilIndex: int) -> list:
|
||||||
|
"""获取指定地块的所有偷菜记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: 偷菜记录字典列表,每条包含 stealerUid, stealCount, stealTime
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
'SELECT stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
|
(uid, soilIndex)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"uid": uid,
|
||||||
|
"soilIndex": soilIndex,
|
||||||
|
"stealerUid": row[0],
|
||||||
|
"stealCount": row[1],
|
||||||
|
"stealTime": row[2]
|
||||||
|
}
|
||||||
|
for row in rows
|
||||||
|
]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("获取单地块偷菜记录失败", e=e)
|
||||||
|
return []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getTotalStolenCount(cls, uid: str, soilIndex: int) -> int:
|
||||||
|
"""计算指定地块被偷的总数量(所有用户偷取数量之和)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 被偷的总数量,如果无记录则返回 0
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
'SELECT SUM(stealCount) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
|
(uid, soilIndex)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] or 0 # type: ignore
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("计算总偷菜数量失败", e=e)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getStealerCount(cls, uid: str, soilIndex: int) -> int:
|
||||||
|
"""计算指定地块被多少人偷过(不同偷菜用户数量)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 偷菜者总数,如果无记录则返回 0
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
'SELECT COUNT(DISTINCT stealerUid) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
|
(uid, soilIndex)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return row[0] or 0 # type: ignore
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("计算偷菜者数量失败", e=e)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def hasStealed(cls, uid: str, soilIndex: int, stealerUid: str) -> bool:
|
||||||
|
"""判断指定用户是否曾偷取过该地块
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
stealerUid (str): 偷菜用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 若存在记录返回 True,否则返回 False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
'SELECT 1 FROM "userSteal" WHERE uid=? AND soilIndex=? AND stealerUid=? LIMIT 1;',
|
||||||
|
(uid, soilIndex, stealerUid)
|
||||||
|
)
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
return bool(row)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("检查偷菜记录失败", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def updateStealRecord(cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int) -> bool:
|
||||||
|
"""更新偷菜记录的数量和时间
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
stealerUid (str): 偷菜用户Uid
|
||||||
|
stealCount (int): 新的偷菜数量
|
||||||
|
stealTime (int): 新的偷菜时间(时间戳)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 操作是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
'UPDATE "userSteal" SET stealCount=?, stealTime=? WHERE uid=? AND soilIndex=? AND stealerUid=?;',
|
||||||
|
(stealCount, stealTime, uid, soilIndex, stealerUid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("更新偷菜记录失败", e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def deleteStealRecord(cls, uid: str, soilIndex: int, stealerUid: str) -> bool:
|
||||||
|
"""删除指定偷菜记录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 被偷用户Uid
|
||||||
|
soilIndex (int): 被偷地块索引
|
||||||
|
stealerUid (str): 偷菜用户Uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 删除是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
async with cls._transaction():
|
||||||
|
await cls.m_pDB.execute(
|
||||||
|
'DELETE FROM "userSteal" WHERE uid=? AND soilIndex=? AND stealerUid=?;',
|
||||||
|
(uid, soilIndex, stealerUid)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("删除偷菜记录失败", e=e)
|
||||||
|
return False
|
||||||
29
dbService.py
Normal file
29
dbService.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from .database.user import CUserDB
|
||||||
|
from .database.userItem import CUserItemDB
|
||||||
|
from .database.userPlant import CUserPlantDB
|
||||||
|
from .database.userSeed import CUserSeedDB
|
||||||
|
from .database.userSoil import CUserSoilDB
|
||||||
|
from .database.userSteal import CUserStealDB
|
||||||
|
|
||||||
|
|
||||||
|
class CDBService:
|
||||||
|
def __init__(self):
|
||||||
|
user: Optional["CUserDB"] = None
|
||||||
|
userSoil: Optional["CUserSoilDB"] = None
|
||||||
|
userPlant: Optional["CUserPlantDB"] = None
|
||||||
|
userSeed: Optional["CUserSeedDB"] = None
|
||||||
|
userItem: Optional["CUserItemDB"] = None
|
||||||
|
userSteal: Optional["CUserStealDB"] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def init(cls):
|
||||||
|
cls.user = CUserDB()
|
||||||
|
cls.userSoil = CUserSoilDB()
|
||||||
|
cls.userPlant = CUserPlantDB()
|
||||||
|
cls.userSeed = CUserSeedDB()
|
||||||
|
cls.userItem = CUserItemDB()
|
||||||
|
cls.userSteal = CUserStealDB()
|
||||||
|
|
||||||
|
g_pDBService = CDBService()
|
||||||
103
event/event.py
Normal file
103
event/event.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Signal:
|
||||||
|
def __init__(self):
|
||||||
|
self._slots = [] #绑定的槽函数列表
|
||||||
|
self._onceSlots = [] #只触发一次的槽函数列表
|
||||||
|
|
||||||
|
def connect(self, slot, priority=0):
|
||||||
|
if callable(slot) and not any(s[0] == slot for s in self._slots):
|
||||||
|
self._slots.append((slot, priority))
|
||||||
|
self._slots.sort(key=lambda x: -x[1])
|
||||||
|
|
||||||
|
def connectOnce(self, slot, priority=0):
|
||||||
|
if callable(slot) and not any(s[0] == slot for s in self._onceSlots):
|
||||||
|
self._onceSlots.append((slot, priority))
|
||||||
|
self._onceSlots.sort(key=lambda x: -x[1])
|
||||||
|
|
||||||
|
def disconnect(self, slot):
|
||||||
|
self._slots = [s for s in self._slots if s[0] != slot]
|
||||||
|
self._onceSlots = [s for s in self._onceSlots if s[0] != slot]
|
||||||
|
|
||||||
|
async def emit(self, *args, **kwargs):
|
||||||
|
slots = list(self._slots)
|
||||||
|
onceSlots = list(self._onceSlots)
|
||||||
|
self._onceSlots.clear()
|
||||||
|
|
||||||
|
for slot, _ in slots + onceSlots:
|
||||||
|
startTime = time.time()
|
||||||
|
try:
|
||||||
|
if asyncio.iscoroutinefunction(slot):
|
||||||
|
await slot(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
slot(*args, **kwargs)
|
||||||
|
duration = (time.time() - startTime) * 1000
|
||||||
|
logger.debug(f"事件槽 {slot.__name__} 执行完成,耗时 {duration:.2f} ms")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"事件槽 {slot.__name__} 触发异常: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FarmEventManager:
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.m_beforePlant = Signal()
|
||||||
|
"""播种前信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
name (str): 播种种子名称
|
||||||
|
num (int): 播种数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_afterPlant = Signal()
|
||||||
|
"""播种后信号 每块地播种都会触发该信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
name (str): 播种种子名称
|
||||||
|
soilIndex (int): 播种地块索引 从1开始
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_beforeHarvest = Signal()
|
||||||
|
"""收获前信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_afterHarvest = Signal()
|
||||||
|
"""收获后信号 每块地收获都会触发该信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
name (str): 收获作物名称
|
||||||
|
num (int): 收获数量
|
||||||
|
soilIndex (int): 收获地块索引 从1开始
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_beforeEradicate = Signal()
|
||||||
|
"""铲除前信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_afterEradicate = Signal()
|
||||||
|
"""铲除后信号 每块地铲除都会触发该信号
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户Uid
|
||||||
|
soilIndex (index): 铲除地块索引 从1开始
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.m_beforeExpand = Signal()
|
||||||
|
self.m_afterExpand = Signal()
|
||||||
|
self.m_beforeSteal = Signal()
|
||||||
|
self.m_afterSteal = Signal()
|
||||||
|
|
||||||
|
g_pEventManager = FarmEventManager()
|
||||||
380
farm/farm.py
380
farm/farm.py
@ -5,8 +5,6 @@ from datetime import date, datetime
|
|||||||
from io import StringIO
|
from io import StringIO
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
from numpy import number
|
|
||||||
|
|
||||||
from zhenxun.configs.config import Config
|
from zhenxun.configs.config import Config
|
||||||
from zhenxun.models.user_console import UserConsole
|
from zhenxun.models.user_console import UserConsole
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
@ -16,7 +14,8 @@ from zhenxun.utils.image_utils import ImageTemplate
|
|||||||
from zhenxun.utils.platform import PlatformUtils
|
from zhenxun.utils.platform import PlatformUtils
|
||||||
|
|
||||||
from ..config import g_pJsonManager, g_sResourcePath
|
from ..config import g_pJsonManager, g_sResourcePath
|
||||||
from ..database import g_pSqlManager
|
from ..dbService import g_pDBService
|
||||||
|
from ..event.event import g_pEventManager
|
||||||
|
|
||||||
|
|
||||||
class CFarmManager:
|
class CFarmManager:
|
||||||
@ -38,15 +37,15 @@ class CFarmManager:
|
|||||||
if user.gold < deduction:
|
if user.gold < deduction:
|
||||||
return f"你的金币不足或不足承担手续费。当前手续费为{fee}"
|
return f"你的金币不足或不足承担手续费。当前手续费为{fee}"
|
||||||
|
|
||||||
await UserConsole.reduce_gold(uid, num, GoldHandle.PLUGIN , 'zhenxun_plugin_farm')
|
await UserConsole.reduce_gold(uid, num, GoldHandle.PLUGIN , 'zhenxun_plugin_farm') # type: ignore
|
||||||
await UserConsole.reduce_gold(uid, fee, GoldHandle.PLUGIN , 'zhenxun_plugin_farm')
|
await UserConsole.reduce_gold(uid, fee, GoldHandle.PLUGIN , 'zhenxun_plugin_farm') # type: ignore
|
||||||
|
|
||||||
point = num * pro
|
point = num * pro
|
||||||
|
|
||||||
p = await g_pSqlManager.getUserPointByUid(uid)
|
p = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
number = point + p
|
number = point + p
|
||||||
|
|
||||||
await g_pSqlManager.updateUserPointByUid(uid, int(number))
|
await g_pDBService.user.updateUserPointByUid(uid, int(number))
|
||||||
|
|
||||||
return f"充值{point}农场币成功,手续费{tax}金币,当前农场币:{number}"
|
return f"充值{point}农场币成功,手续费{tax}金币,当前农场币:{number}"
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ class CFarmManager:
|
|||||||
|
|
||||||
soilPos = g_pJsonManager.m_pSoil['soil']
|
soilPos = g_pJsonManager.m_pSoil['soil']
|
||||||
|
|
||||||
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
soilUnlock = int(userInfo['soil'])
|
soilUnlock = int(userInfo['soil'])
|
||||||
|
|
||||||
x = 0
|
x = 0
|
||||||
@ -89,7 +88,7 @@ class CFarmManager:
|
|||||||
if index < soilUnlock:
|
if index < soilUnlock:
|
||||||
await img.paste(soil, (x, y))
|
await img.paste(soil, (x, y))
|
||||||
|
|
||||||
isPlant, plant, isRipe= await cls.drawSoilPlant(uid, f"soil{str(index + 1)}")
|
isPlant, plant, isRipe= await cls.drawSoilPlant(uid, index + 1)
|
||||||
|
|
||||||
if isPlant:
|
if isPlant:
|
||||||
await img.paste(plant, (x + soilSize[0] // 2 - plant.width // 2,
|
await img.paste(plant, (x + soilSize[0] // 2 - plant.width // 2,
|
||||||
@ -134,7 +133,7 @@ class CFarmManager:
|
|||||||
await img.paste(nameImg, (300, 92))
|
await img.paste(nameImg, (300, 92))
|
||||||
|
|
||||||
#经验值
|
#经验值
|
||||||
level = await g_pSqlManager.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
beginX = 309
|
beginX = 309
|
||||||
endX = 627
|
endX = 627
|
||||||
@ -171,57 +170,59 @@ class CFarmManager:
|
|||||||
return img.pic2bytes()
|
return img.pic2bytes()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def drawSoilPlant(cls, uid: str, soilid: str) -> tuple[bool, BuildImage, bool]:
|
async def drawSoilPlant(cls, uid: str, soilIndex: int) -> tuple[bool, BuildImage, bool]:
|
||||||
"""绘制植物资源
|
"""绘制植物资源
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
uid (str): 用户Uid
|
uid (str): 用户Uid
|
||||||
soilid (str): 土地id
|
soilIndex (int): 土地索引 从1开始
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
tuple[bool, BuildImage]: [绘制是否成功,资源图片, 是否成熟]
|
tuple[bool, BuildImage]: [绘制是否成功,资源图片, 是否成熟]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plant = None
|
plant = None
|
||||||
soilStatus, soilInfo = await g_pSqlManager.getUserSoilStatusBySoilID(uid, soilid)
|
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
|
||||||
|
|
||||||
if soilStatus == True:
|
if not soilInfo or not soilInfo.get("plantName"):
|
||||||
return False, None, False
|
return False, None, False #type: ignore
|
||||||
|
|
||||||
|
#是否枯萎
|
||||||
|
if int(soilInfo.get("wiltStatus", 0)) == 1:
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/basic/9.png")
|
||||||
|
await plant.resize(0, 150, 212)
|
||||||
|
return True, plant, False
|
||||||
|
|
||||||
|
#获取作物详细信息
|
||||||
|
plantInfo = g_pJsonManager.m_pPlant['plant'][soilInfo['plantName']]
|
||||||
|
|
||||||
|
currentTime = datetime.now()
|
||||||
|
matureTime = datetime.fromtimestamp(int(soilInfo['matureTime']))
|
||||||
|
|
||||||
|
#如果当前时间大于成熟时间 说明作物成熟
|
||||||
|
if currentTime >= matureTime:
|
||||||
|
phase = int(plantInfo['phase'])
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase - 1}.png")
|
||||||
|
|
||||||
|
return True, plant, True
|
||||||
else:
|
else:
|
||||||
soilInfo = soilInfo.split(',')
|
#如果没有成熟 则根据当前阶段进行绘制
|
||||||
|
plantedTime = datetime.fromtimestamp(int(soilInfo['plantTime']))
|
||||||
|
|
||||||
if int(soilInfo[3]) == 4:
|
elapsedTime = currentTime - plantedTime
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/basic/9.png")
|
elapsedHour = elapsedTime.total_seconds() / 3600
|
||||||
await plant.resize(0, 150, 212)
|
|
||||||
return True, plant, False
|
|
||||||
|
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][soilInfo[0]]
|
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
|
||||||
|
|
||||||
currentTime = datetime.now()
|
if currentStage <= 0:
|
||||||
matureTime = datetime.fromtimestamp(int(soilInfo[2]))
|
if plantInfo['general'] == False:
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/0.png")
|
||||||
if currentTime >= matureTime:
|
|
||||||
phase = int(plantInfo['phase'])
|
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/{phase - 1}.png")
|
|
||||||
|
|
||||||
return True, plant, True
|
|
||||||
else:
|
|
||||||
plantedTime = datetime.fromtimestamp(int(soilInfo[1]))
|
|
||||||
|
|
||||||
elapsedTime = currentTime - plantedTime
|
|
||||||
elapsedHour = elapsedTime.total_seconds() / 60 / 60
|
|
||||||
|
|
||||||
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
|
|
||||||
|
|
||||||
if currentStage <= 0:
|
|
||||||
if plantInfo['general'] == False:
|
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/0.png")
|
|
||||||
else:
|
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png")
|
|
||||||
|
|
||||||
await plant.resize(0, 35, 58)
|
|
||||||
else:
|
else:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/{currentStage}.png")
|
plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png")
|
||||||
|
|
||||||
|
await plant.resize(0, 35, 58)
|
||||||
|
else:
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{currentStage}.png")
|
||||||
|
|
||||||
return True, plant, False
|
return True, plant, False
|
||||||
|
|
||||||
@ -241,8 +242,8 @@ class CFarmManager:
|
|||||||
"是否可以上架交易行"
|
"是否可以上架交易行"
|
||||||
]
|
]
|
||||||
|
|
||||||
# 从数据库获取结构化数据
|
#从数据库获取结构化数据
|
||||||
seedRecords = await g_pSqlManager.getUserSeedByUid(uid) or {}
|
seedRecords = await g_pDBService.userSeed.getUserSeedByUid(uid) or {}
|
||||||
|
|
||||||
if not seedRecords:
|
if not seedRecords:
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
@ -295,54 +296,57 @@ class CFarmManager:
|
|||||||
str: 返回结果
|
str: 返回结果
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 获取用户的种子数量
|
#获取用户的种子数量
|
||||||
count = await g_pSqlManager.getUserSeedByName(uid, name)
|
count = await g_pDBService.userSeed.getUserSeedByName(uid, name)
|
||||||
if count is None:
|
if count is None:
|
||||||
count = 0 # 如果返回 None,则视为没有种子
|
count = 0 #如果返回 None,则视为没有种子
|
||||||
|
|
||||||
if count <= 0:
|
if count <= 0:
|
||||||
return f"没有在你的仓库发现{name}种子,快去买点吧!"
|
return f"没有在你的仓库发现{name}种子,快去买点吧!"
|
||||||
|
|
||||||
# 如果播种数量超过仓库种子数量
|
#如果播种数量超过仓库种子数量
|
||||||
if count < num and num != -1:
|
if count < num and num != -1:
|
||||||
return f"仓库中的{name}种子数量不足,当前剩余{count}个种子"
|
return f"仓库中的{name}种子数量不足,当前剩余{count}个种子"
|
||||||
|
|
||||||
# 获取用户土地数量
|
#获取用户土地数量
|
||||||
soilNumber = await g_pSqlManager.getUserSoilByUid(uid)
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
|
|
||||||
# 如果播种数量为 -1,表示播种所有可播种的土地
|
#如果播种数量为 -1,表示播种所有可播种的土地
|
||||||
if num == -1:
|
if num == -1:
|
||||||
num = count
|
num = count
|
||||||
|
|
||||||
# 记录是否成功播种
|
#发送播种前信号
|
||||||
|
await g_pEventManager.m_beforePlant.emit(uid=uid, name=name, num=num)
|
||||||
|
|
||||||
|
#记录是否成功播种
|
||||||
successCount = 0
|
successCount = 0
|
||||||
for i in range(1, soilNumber + 1):
|
for i in range(1, soilNumber + 1):
|
||||||
if count > 0 and num > 0:
|
if count > 0 and num > 0:
|
||||||
soilName = f"soil{i}"
|
success = await g_pDBService.userSoil.sowingByPlantName(uid, i, name)
|
||||||
success, message = await g_pSqlManager.getUserSoilStatusBySoilID(uid, soilName)
|
|
||||||
if success:
|
if success:
|
||||||
# 更新种子数量
|
#更新种子数量
|
||||||
num -= 1
|
num -= 1
|
||||||
count -= 1
|
count -= 1
|
||||||
|
|
||||||
# 记录种子消耗数量
|
#记录种子消耗数量
|
||||||
successCount += 1
|
successCount += 1
|
||||||
|
|
||||||
# 更新数据库
|
#发送播种后信号
|
||||||
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soilName, name)
|
await g_pEventManager.m_afterPlant.emit(uid=uid, name=name, soilIndex=i)
|
||||||
|
|
||||||
# 确保用户仓库数量更新
|
|
||||||
|
#确保用户仓库数量更新
|
||||||
if successCount > 0:
|
if successCount > 0:
|
||||||
await g_pSqlManager.updateUserSeedByName(uid, name, count)
|
await g_pDBService.userSeed.updateUserSeedByName(uid, name, count)
|
||||||
|
|
||||||
# 根据播种结果给出反馈
|
#根据播种结果给出反馈
|
||||||
if num == 0:
|
if num == 0:
|
||||||
return f"播种{name}成功!仓库剩余{count}个种子"
|
return f"播种{name}成功!仓库剩余{count}个种子"
|
||||||
else:
|
else:
|
||||||
return f"播种数量超出开垦土地数量,已将可播种土地成功播种{name}!仓库剩余{count}个种子"
|
return f"播种数量超出开垦土地数量,已将可播种土地成功播种{name}!仓库剩余{count}个种子"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"播种操作失败: {e}")
|
logger.warning(f"播种操作失败!", e=e)
|
||||||
return "播种失败,请稍后重试!"
|
return "播种失败,请稍后重试!"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -355,61 +359,66 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
str: 返回
|
str: 返回
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
|
await g_pEventManager.m_beforeHarvest.emit(uid=uid)
|
||||||
|
|
||||||
isStealingPlant = 0
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
|
|
||||||
|
|
||||||
soilNames = [f"soil{i + 1}" for i in range(soilUnlock)]
|
harvestRecords = [] #收获日志记录
|
||||||
soilStatuses = await asyncio.gather(*[
|
experience = 0 #总经验值
|
||||||
g_pSqlManager.getUserSoilStatusBySoilID(uid, name)
|
harvestCount = 0 #成功收获数量
|
||||||
for name in soilNames
|
|
||||||
])
|
|
||||||
|
|
||||||
harvestRecords: List[str] = []
|
for i in range(1, soilNumber + 1):
|
||||||
experience = 0
|
#如果没有种植
|
||||||
|
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
||||||
|
continue
|
||||||
|
|
||||||
for (soil_name, (status, info)) in zip(soilNames, soilStatuses):
|
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, i)
|
||||||
if len(info) <= 0:
|
if not soilInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
soilInfo = info.split(',')
|
#如果是枯萎状态
|
||||||
if int(soilInfo[3]) == 4:
|
if soilInfo.get("wiltStatus", 1) == 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
plantId = soilInfo[0]
|
plantInfo = g_pJsonManager.m_pPlant.get("plant", {}).get(soilInfo['plantName'])
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][plantId]
|
currentTime = datetime.now()
|
||||||
|
matureTime = datetime.fromtimestamp(int(soilInfo['matureTime']))
|
||||||
|
|
||||||
currentTime = datetime.now()
|
if currentTime >= matureTime:
|
||||||
matureTime = datetime.fromtimestamp(int(soilInfo[2]))
|
number = plantInfo['harvest']
|
||||||
|
|
||||||
if currentTime >= matureTime:
|
#处理偷菜扣除数量
|
||||||
number = plantInfo['harvest']
|
stealNum = g_pDBService.userSteal.getTotalStolenCount(uid, i)
|
||||||
|
|
||||||
#判断该土地作物是否被透过
|
number -= stealNum
|
||||||
if len(soilInfo[4]) > 0:
|
|
||||||
stealingStatus = soilInfo[4].split('|')
|
|
||||||
for isUser in stealingStatus:
|
|
||||||
user = isUser.split('-')
|
|
||||||
number -= int(user[1])
|
|
||||||
|
|
||||||
isStealingPlant += 1
|
if number <= 0:
|
||||||
|
continue
|
||||||
|
|
||||||
experience += plantInfo['experience']
|
harvestCount += 1
|
||||||
harvestRecords.append(f"收获作物:{plantId},数量为:{number},经验为:{plantInfo['experience']}")
|
experience += plantInfo['experience']
|
||||||
|
|
||||||
#更新数据库操作
|
harvestRecords.append(f"收获作物:{soilInfo['plantName']},数量为:{number},经验为:{plantInfo['experience']}")
|
||||||
await g_pSqlManager.addUserPlantByUid(uid, plantId, number)
|
|
||||||
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soil_name, "", 4)
|
|
||||||
|
|
||||||
if experience > 0:
|
await g_pDBService.userPlant.addUserPlantByUid(uid, soilInfo['plantName'], number)
|
||||||
harvestRecords.append(f"\t累计获得经验:{experience}")
|
await g_pDBService.userSoil.updateUserSoil(uid, i, "wiltStatus", 1)
|
||||||
exp = await g_pSqlManager.getUserExpByUid(uid)
|
|
||||||
await g_pSqlManager.UpdateUserExpByUid(uid, exp + experience)
|
|
||||||
|
|
||||||
if isStealingPlant <= 0:
|
await g_pEventManager.m_afterHarvest.emit(uid=uid, name=soilInfo['plantName'], num=number, soilIndex=i)
|
||||||
return "没有可收获的作物哦~ 不要试图拔苗助长"
|
|
||||||
else:
|
if experience > 0:
|
||||||
return "\n".join(harvestRecords)
|
exp = await g_pDBService.user.getUserExpByUid(uid)
|
||||||
|
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
||||||
|
harvestRecords.append(f"\t累计获得经验:{experience}")
|
||||||
|
|
||||||
|
if harvestCount <= 0:
|
||||||
|
return "没有可收获的作物哦~ 不要试图拔苗助长"
|
||||||
|
else:
|
||||||
|
return "\n".join(harvestRecords)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"收获操作失败!", e=e)
|
||||||
|
return "收获失败,请稍后重试!"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def eradicate(cls, uid: str) -> str:
|
async def eradicate(cls, uid: str) -> str:
|
||||||
@ -421,28 +430,34 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
str: 返回
|
str: 返回
|
||||||
"""
|
"""
|
||||||
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
|
|
||||||
soilUnlock = await g_pSqlManager.getUserSoilByUid(uid)
|
await g_pEventManager.m_beforeEradicate.emit(uid=uid)
|
||||||
|
|
||||||
soilNames = [f"soil{i + 1}" for i in range(soilUnlock)]
|
|
||||||
soilStatuses = await asyncio.gather(*[
|
|
||||||
g_pSqlManager.getUserSoilStatusBySoilID(uid, name)
|
|
||||||
for name in soilNames
|
|
||||||
])
|
|
||||||
|
|
||||||
experience = 0
|
experience = 0
|
||||||
for (soil_name, (status, info)) in zip(soilNames, soilStatuses):
|
for i in range(1, soilNumber + 1):
|
||||||
if info:
|
#如果没有种植
|
||||||
soilInfo = info.split(',')
|
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
||||||
if int(soilInfo[3]) == 4:
|
continue
|
||||||
experience += 3
|
|
||||||
|
|
||||||
#批量更新数据库操作
|
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, i)
|
||||||
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soil_name, "", 0)
|
if not soilInfo:
|
||||||
|
continue
|
||||||
|
|
||||||
|
#如果不是枯萎状态
|
||||||
|
if soilInfo.get("wiltStatus", 0) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
experience += 3
|
||||||
|
|
||||||
|
#批量更新数据库操作
|
||||||
|
await g_pDBService.userSoil.deleteUserSoil(uid, i)
|
||||||
|
|
||||||
|
await g_pEventManager.m_afterEradicate.emit(uid=uid, soilIndex=i)
|
||||||
|
|
||||||
if experience > 0:
|
if experience > 0:
|
||||||
exp = await g_pSqlManager.getUserExpByUid(uid)
|
exp = await g_pDBService.user.getUserExpByUid(uid)
|
||||||
await g_pSqlManager.UpdateUserExpByUid(uid, exp + experience)
|
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
||||||
|
|
||||||
return f"成功铲除荒废作物,累计获得经验:{experience}"
|
return f"成功铲除荒废作物,累计获得经验:{experience}"
|
||||||
else:
|
else:
|
||||||
@ -468,7 +483,7 @@ class CFarmManager:
|
|||||||
"是否可以上架交易行"
|
"是否可以上架交易行"
|
||||||
]
|
]
|
||||||
|
|
||||||
plant = await g_pSqlManager.getUserPlantByUid(uid)
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
||||||
|
|
||||||
if plant is None:
|
if plant is None:
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
@ -525,121 +540,83 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
str: 返回
|
str: 返回
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#用户信息
|
#用户信息
|
||||||
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
#用户可偷次数
|
|
||||||
userStealing = userInfo["stealing"].split('|')
|
|
||||||
|
|
||||||
if userStealing[0] == '':
|
stealTime = userInfo['stealTime']
|
||||||
userStealing[0] = date.today().strftime('%Y-%m-%d')
|
stealCount = int(userInfo['stealCount'])
|
||||||
userStealing.append(5)
|
|
||||||
elif date.fromisoformat(userStealing[0]) != date.today():
|
|
||||||
userStealing[0] = date.today().strftime('%Y-%m-%d')
|
|
||||||
userStealing[1] = 5
|
|
||||||
|
|
||||||
if int(userStealing[1]) <= 0:
|
if stealTime == '':
|
||||||
|
stealTime = date.today().strftime('%Y-%m-%d')
|
||||||
|
stealCount = 5
|
||||||
|
elif date.fromisoformat(stealTime) != date.today():
|
||||||
|
stealTime = date.today().strftime('%Y-%m-%d')
|
||||||
|
stealCount = 5
|
||||||
|
|
||||||
|
if stealCount <= 0:
|
||||||
return "你今天可偷次数到达上限啦,手下留情吧"
|
return "你今天可偷次数到达上限啦,手下留情吧"
|
||||||
|
|
||||||
#获取用户解锁地块数量
|
#获取用户解锁地块数量
|
||||||
soilUnlockNum = int(userInfo["soil"])
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
plant = {}
|
|
||||||
|
|
||||||
#根据解锁土地,获取每块土地状态信息
|
|
||||||
soilNames = [f"soil{i + 1}" for i in range(soilUnlockNum)]
|
|
||||||
soilStatuses = await asyncio.gather(*[
|
|
||||||
g_pSqlManager.getUserSoilStatusBySoilID(target, name)
|
|
||||||
for name in soilNames
|
|
||||||
])
|
|
||||||
|
|
||||||
isStealing = False
|
|
||||||
harvestRecords: List[str] = []
|
harvestRecords: List[str] = []
|
||||||
isStealingNumber = 0
|
isStealingNumber = 0
|
||||||
isStealingPlant = 0
|
isStealingPlant = 0
|
||||||
|
|
||||||
for (soilName, (status, info)) in zip(soilNames, soilStatuses):
|
for i in range(1, soilNumber + 1):
|
||||||
isStealing = False
|
#如果没有种植
|
||||||
|
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
||||||
if not info:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
soilInfo = info.split(',')
|
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, i)
|
||||||
if int(soilInfo[3]) == 4:
|
if not soilInfo:
|
||||||
|
continue
|
||||||
|
|
||||||
|
#如果是枯萎状态
|
||||||
|
if soilInfo.get("wiltStatus", 1) == 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#作物ID
|
|
||||||
plantId = soilInfo[0]
|
|
||||||
#作物信息
|
#作物信息
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][plantId]
|
plantInfo = g_pJsonManager.m_pPlant.get("plant", {}).get(soilInfo['plantName'])
|
||||||
|
|
||||||
currentTime = datetime.now()
|
currentTime = datetime.now()
|
||||||
matureTime = datetime.fromtimestamp(int(soilInfo[2]))
|
matureTime = datetime.fromtimestamp(int(soilInfo['matureTime']))
|
||||||
|
|
||||||
#偷窃状态
|
|
||||||
stealingStatus: list[str] = []
|
|
||||||
#偷窃数量
|
|
||||||
stealingNumber = 0
|
|
||||||
if currentTime >= matureTime:
|
if currentTime >= matureTime:
|
||||||
if soilInfo[4]:
|
|
||||||
#先获取用户是否偷过该土地
|
|
||||||
stealingStatus = soilInfo[4].split('|')
|
|
||||||
|
|
||||||
for isUser in stealingStatus:
|
|
||||||
user = isUser.split('-')
|
|
||||||
|
|
||||||
if user[0] == uid:
|
|
||||||
isStealing = True
|
|
||||||
isStealingNumber += 1
|
|
||||||
break
|
|
||||||
|
|
||||||
stealingNumber -= int(user[1])
|
|
||||||
|
|
||||||
#如果偷过,则跳过该土地
|
#如果偷过,则跳过该土地
|
||||||
if isStealing:
|
if await g_pDBService.userSteal.hasStealed(target, i, uid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
stealingNumber += plantInfo['harvest']
|
stealingNumber = plantInfo['harvest'] - await g_pDBService.userSteal.getTotalStolenCount(target, i)
|
||||||
randomNumber = random.choice([1, 2])
|
randomNumber = random.choice([1, 2])
|
||||||
randomNumber = min(randomNumber, stealingNumber)
|
randomNumber = min(randomNumber, stealingNumber)
|
||||||
|
|
||||||
logger.info(f"{randomNumber}")
|
|
||||||
|
|
||||||
if randomNumber > 0:
|
if randomNumber > 0:
|
||||||
await g_pSqlManager.addUserPlantByUid(uid, plantId, randomNumber)
|
await g_pDBService.userPlant.addUserPlantByUid(uid, soilInfo['plantName'], randomNumber)
|
||||||
|
|
||||||
harvestRecords.append(f"成功偷到作物:{plantId},数量为:{randomNumber}")
|
harvestRecords.append(f"成功偷到作物:{soilInfo['plantName']},数量为:{randomNumber}")
|
||||||
stealingStatus.append(f"{uid}-{randomNumber}")
|
|
||||||
|
|
||||||
isStealingPlant += 1
|
isStealingPlant += 1
|
||||||
|
|
||||||
#如果将作物偷完,就直接更新状态 并记录用户偷取过
|
#如果将作物偷完,就直接更新状态 并记录用户偷取过
|
||||||
if plantInfo['harvest'] - randomNumber + stealingNumber == 0:
|
if plantInfo['harvest'] - randomNumber + stealingNumber == 0:
|
||||||
sql = f"UPDATE soil SET {soilName} = ',,,4,{'|'.join(stealingStatus)}' WHERE uid = '{target}'"
|
await g_pDBService.userSoil.updateUserSoil(target, i, "wiltStatus", 1)
|
||||||
else:
|
else:
|
||||||
sql = f"UPDATE soil SET {soilName} = '{soilInfo[0]},{soilInfo[1]},{soilInfo[2]},{soilInfo[3]},{'|'.join(stealingStatus)}' WHERE uid = '{target}'"
|
await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(datetime.now().timestamp()))
|
||||||
|
|
||||||
await g_pSqlManager.executeDB(sql)
|
|
||||||
|
|
||||||
if isStealingPlant <= 0 and isStealingNumber <= 0:
|
if isStealingPlant <= 0 and isStealingNumber <= 0:
|
||||||
return "目标没有作物可以被偷"
|
return "目标没有作物可以被偷"
|
||||||
elif isStealingPlant <= 0 and isStealingNumber > 0:
|
elif isStealingPlant <= 0 and isStealingNumber > 0:
|
||||||
return "你已经偷过目标啦,请手下留情"
|
return "你已经偷过目标啦,请手下留情"
|
||||||
else:
|
else:
|
||||||
userStealing[1] = int(userStealing[1]) - 1
|
stealCount -= 1
|
||||||
# 转换所有元素为字符串
|
|
||||||
userStealing_str = [str(item) for item in userStealing]
|
|
||||||
|
|
||||||
sql = f"UPDATE user SET stealing = '{userStealing[0]}|{userStealing[1]}' WHERE uid = {uid}"
|
await g_pDBService.user.updateStealCountByUid(uid, stealCount)
|
||||||
|
|
||||||
#更新用户每日偷取次数
|
|
||||||
await g_pSqlManager.executeDB(sql)
|
|
||||||
|
|
||||||
return "\n".join(harvestRecords)
|
return "\n".join(harvestRecords)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reclamationCondition(cls, uid: str) -> str:
|
async def reclamationCondition(cls, uid: str) -> str:
|
||||||
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
rec = g_pJsonManager.m_pLevel["reclamation"]
|
rec = g_pJsonManager.m_pLevel['reclamation']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if userInfo['soil'] >= 30:
|
if userInfo['soil'] >= 30:
|
||||||
@ -663,10 +640,10 @@ class CFarmManager:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reclamation(cls, uid: str) -> str:
|
async def reclamation(cls, uid: str) -> str:
|
||||||
userInfo = await g_pSqlManager.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
level = await g_pSqlManager.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
rec = g_pJsonManager.m_pLevel["reclamation"]
|
rec = g_pJsonManager.m_pLevel['reclamation']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if userInfo['soil'] >= 30:
|
if userInfo['soil'] >= 30:
|
||||||
@ -678,18 +655,15 @@ class CFarmManager:
|
|||||||
point = rec['point']
|
point = rec['point']
|
||||||
item = rec['item']
|
item = rec['item']
|
||||||
|
|
||||||
logger.info(f"{level[0]}")
|
|
||||||
|
|
||||||
if level[0] < levelFileter:
|
if level[0] < levelFileter:
|
||||||
return f"当前用户等级{level[0]},升级所需等级为{levelFileter}"
|
return f"当前用户等级{level[0]},升级所需等级为{levelFileter}"
|
||||||
|
|
||||||
if userInfo['point'] < point:
|
if userInfo['point'] < point:
|
||||||
return f"当前用户农场币不足,升级所需农场币为{point}"
|
return f"当前用户农场币不足,升级所需农场币为{point}"
|
||||||
|
|
||||||
#TODO 缺少判断需要的Item
|
#TODO 缺少判断消耗的item
|
||||||
sql = f"UPDATE user SET point = '{userInfo['point'] - point}', soil = '{userInfo['soil'] + 1}' WHERE uid = {uid}"
|
await g_pDBService.user.updateUserPointByUid(uid, userInfo['point'] - point)
|
||||||
|
await g_pDBService.user.updateUserSoilByUid(uid, userInfo['soil'] + 1)
|
||||||
await g_pSqlManager.executeDB(sql)
|
|
||||||
|
|
||||||
return "开垦土地成功!"
|
return "开垦土地成功!"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
20
farm/shop.py
20
farm/shop.py
@ -6,7 +6,7 @@ from zhenxun.utils._build_image import BuildImage
|
|||||||
from zhenxun.utils.image_utils import ImageTemplate
|
from zhenxun.utils.image_utils import ImageTemplate
|
||||||
|
|
||||||
from ..config import g_pJsonManager, g_sResourcePath
|
from ..config import g_pJsonManager, g_sResourcePath
|
||||||
from ..database import g_pSqlManager
|
from ..dbService import g_pDBService
|
||||||
|
|
||||||
|
|
||||||
class CShopManager:
|
class CShopManager:
|
||||||
@ -102,12 +102,12 @@ class CShopManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return "购买出错!请检查需购买的种子名称!"
|
return "购买出错!请检查需购买的种子名称!"
|
||||||
|
|
||||||
level = await g_pSqlManager.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
if level[0] < int(plantInfo['level']):
|
if level[0] < int(plantInfo['level']):
|
||||||
return "你的等级不够哦,努努力吧"
|
return "你的等级不够哦,努努力吧"
|
||||||
|
|
||||||
point = await g_pSqlManager.getUserPointByUid(uid)
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
total = int(plantInfo['buy']) * num
|
total = int(plantInfo['buy']) * num
|
||||||
|
|
||||||
logger.debug(f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}")
|
logger.debug(f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}")
|
||||||
@ -115,9 +115,9 @@ class CShopManager:
|
|||||||
if point < total:
|
if point < total:
|
||||||
return "你的农场币不够哦~ 快速速氪金吧!"
|
return "你的农场币不够哦~ 快速速氪金吧!"
|
||||||
else:
|
else:
|
||||||
await g_pSqlManager.updateUserPointByUid(uid, point - total)
|
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
||||||
|
|
||||||
if await g_pSqlManager.addUserSeedByUid(uid, name, num) == False:
|
if await g_pDBService.userSeed.addUserSeedByUid(uid, name, num) == False:
|
||||||
return "购买失败,执行数据库错误!"
|
return "购买失败,执行数据库错误!"
|
||||||
|
|
||||||
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
||||||
@ -135,7 +135,7 @@ class CShopManager:
|
|||||||
if not isinstance(name, str) or name.strip() == "":
|
if not isinstance(name, str) or name.strip() == "":
|
||||||
name = ""
|
name = ""
|
||||||
|
|
||||||
plant = await g_pSqlManager.getUserPlantByUid(uid)
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
||||||
if not plant:
|
if not plant:
|
||||||
return "你仓库没有可以出售的作物"
|
return "你仓库没有可以出售的作物"
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ class CShopManager:
|
|||||||
for plantName, count in plant.items():
|
for plantName, count in plant.items():
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][plantName]
|
plantInfo = g_pJsonManager.m_pPlant['plant'][plantName]
|
||||||
point += plantInfo['price'] * count
|
point += plantInfo['price'] * count
|
||||||
await g_pSqlManager.updateUserPlantByName(uid, plantName, 0)
|
await g_pDBService.userPlant.updateUserPlantByName(uid, plantName, 0)
|
||||||
else:
|
else:
|
||||||
if name not in plant:
|
if name not in plant:
|
||||||
return f"出售作物{name}出错:仓库中不存在该作物"
|
return f"出售作物{name}出错:仓库中不存在该作物"
|
||||||
@ -155,12 +155,12 @@ class CShopManager:
|
|||||||
sellAmount = available if isAll else min(available, num)
|
sellAmount = available if isAll else min(available, num)
|
||||||
if sellAmount <= 0:
|
if sellAmount <= 0:
|
||||||
return f"出售作物{name}出错:数量不足"
|
return f"出售作物{name}出错:数量不足"
|
||||||
await g_pSqlManager.updateUserPlantByName(uid, name, available - sellAmount)
|
await g_pDBService.userPlant.updateUserPlantByName(uid, name, available - sellAmount)
|
||||||
totalSold = sellAmount
|
totalSold = sellAmount
|
||||||
|
|
||||||
totalPoint = point if name == "" else totalSold * g_pJsonManager.m_pPlant['plant'][name]['price']
|
totalPoint = point if name == "" else totalSold * g_pJsonManager.m_pPlant['plant'][name]['price']
|
||||||
currentPoint = await g_pSqlManager.getUserPointByUid(uid)
|
currentPoint = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
await g_pSqlManager.updateUserPointByUid(uid, currentPoint + totalPoint)
|
await g_pDBService.user.updateUserPointByUid(uid, currentPoint + totalPoint)
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
|
return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user