✨ 新增在线查漏补缺功能
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import re
|
||||
from contextlib import asynccontextmanager
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import aiosqlite
|
||||
|
||||
@@ -103,9 +103,14 @@ class CSqlManager:
|
||||
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}";'
|
||||
|
||||
sql = (
|
||||
f'INSERT INTO "{tmpTable}" ({colsStr}) '
|
||||
f"SELECT {colsStr} "
|
||||
f'FROM "{tableName}";'
|
||||
)
|
||||
|
||||
await cls.m_pDB.execute(sql)
|
||||
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
||||
await cls.m_pDB.execute(
|
||||
f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";'
|
||||
|
||||
+46
-2
@@ -1,11 +1,13 @@
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
import os
|
||||
|
||||
import aiosqlite
|
||||
|
||||
from zhenxun.configs.config import Config
|
||||
from zhenxun.services.log import logger
|
||||
|
||||
from ..config import g_bIsDebug, g_sPlantPath
|
||||
from ..config import g_bIsDebug, g_sPlantPath, g_sResourcePath
|
||||
from ..request import g_pRequestManager
|
||||
|
||||
|
||||
class CPlantManager:
|
||||
@@ -247,3 +249,45 @@ class CPlantManager:
|
||||
except Exception as e:
|
||||
logger.warning("查询所有作物失败", e=e)
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
async def downloadPlant(cls) -> bool:
|
||||
"""遍历所有作物,下载各阶段图片及icon文件到指定文件夹
|
||||
|
||||
Returns:
|
||||
bool: 全部下载完成返回True,如有失败返回False
|
||||
"""
|
||||
success = True
|
||||
baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址")
|
||||
|
||||
baseUrl = baseUrl.rstrip("/") + ":8998/file"
|
||||
try:
|
||||
plants = await cls.listPlants()
|
||||
for plant in plants:
|
||||
name = plant["name"]
|
||||
phaseCount = await cls.getPlantPhaseNumberByName(name)
|
||||
saveDir = os.path.join(g_sResourcePath, "plant", name)
|
||||
begin = 0 if plant["general"] == 0 else 1
|
||||
|
||||
for idx in range(begin, phaseCount + 1):
|
||||
fileName = f"{idx}.png"
|
||||
fullPath = os.path.join(saveDir, fileName)
|
||||
|
||||
if os.path.exists(fullPath):
|
||||
continue
|
||||
|
||||
url = f"{baseUrl}/{name}/{idx}.png"
|
||||
if not await g_pRequestManager.download(url, saveDir, f"{idx}.png"):
|
||||
success = False
|
||||
|
||||
iconName = "icon.png"
|
||||
iconPath = os.path.join(saveDir, iconName)
|
||||
if not os.path.exists(iconPath):
|
||||
iconUrl = f"{baseUrl}/{name}/{iconName}"
|
||||
if not await g_pRequestManager.download(iconUrl, saveDir, iconName):
|
||||
success = False
|
||||
|
||||
return success
|
||||
except Exception as e:
|
||||
logger.warning(f"下载作物资源异常: {e}")
|
||||
return False
|
||||
|
||||
+4
-3
@@ -225,11 +225,11 @@ class CUserDB(CSqlManager):
|
||||
|
||||
@classmethod
|
||||
async def updateUserVipPointByUid(cls, uid: str, vipPoint: int) -> bool:
|
||||
"""根据用户Uid更新农场币数量
|
||||
"""根据用户Uid更新点券数量
|
||||
|
||||
Args:
|
||||
uid (str): 用户Uid
|
||||
vipPoint (int): 新农场币数量
|
||||
vipPoint (int): 新点券数量
|
||||
|
||||
Returns:
|
||||
bool: 是否更新成功
|
||||
@@ -300,7 +300,8 @@ class CUserDB(CSqlManager):
|
||||
uid (str): 用户Uid
|
||||
|
||||
Returns:
|
||||
tuple[int, int, int]: (当前等级, 升至下级还需经验, 当前等级已获经验),失败返回(-1, -1, -1)
|
||||
tuple[int, int, int]: 成功返回(当前等级, 升至下级还需经验, 当前等级已获经验)
|
||||
失败返回(-1, -1, -1)
|
||||
"""
|
||||
if not uid:
|
||||
return -1, -1, -1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import calendar
|
||||
import random
|
||||
from datetime import timedelta
|
||||
import random
|
||||
|
||||
from zhenxun.services.log import logger
|
||||
from zhenxun.utils._build_image import BuildImage
|
||||
@@ -22,7 +22,7 @@ class CUserSignDB(CSqlManager):
|
||||
"isSupplement": "TINYINT NOT NULL DEFAULT 0", # 是否补签
|
||||
"exp": "INT NOT NULL DEFAULT 0", # 当天签到经验
|
||||
"point": "INT NOT NULL DEFAULT 0", # 当天签到金币
|
||||
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 创建时间
|
||||
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 创建时间 # noqa: E501
|
||||
"PRIMARY KEY": "(uid, signDate)",
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class CUserSignDB(CSqlManager):
|
||||
"lastSignDate": "DATE DEFAULT NULL", # 上次签到日期
|
||||
"continuousDays": "INT NOT NULL DEFAULT 0", # 连续签到天数
|
||||
"supplementCount": "INT NOT NULL DEFAULT 0", # 补签次数
|
||||
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 更新时间
|
||||
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 更新时间 # noqa: E501
|
||||
}
|
||||
|
||||
await cls.ensureTableSchema("userSignLog", userSignLog)
|
||||
|
||||
+146
-4
@@ -67,6 +67,35 @@ class CUserSoilDB(CSqlManager):
|
||||
f"当前阶段{currentStage}, 阶段时间{phaseList[currentStage]}, 播种时间{t}, 收获时间{s}"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def matureNow(cls, uid: str, soilIndex: int):
|
||||
"""将指定地块的作物直接成熟
|
||||
|
||||
Args:
|
||||
uid (str): 用户ID
|
||||
soilIndex (int): 地块索引(从1开始)
|
||||
"""
|
||||
# 与 nextPhase 不同:无需调试模式检查,允许在任何模式下调用
|
||||
soilInfo = await cls.getUserSoil(uid, soilIndex)
|
||||
if not soilInfo:
|
||||
return
|
||||
|
||||
plantName = soilInfo.get("plantName")
|
||||
if not plantName:
|
||||
return
|
||||
|
||||
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
|
||||
if not plantInfo:
|
||||
return
|
||||
|
||||
currentTime = g_pToolManager.dateTime().now().timestamp()
|
||||
# 如果当前时间已经超过或等于成熟时间,则作物已成熟或可收获
|
||||
if currentTime >= soilInfo["matureTime"]:
|
||||
return
|
||||
|
||||
# 将作物成熟时间直接更新为当前时间,实现立即成熟
|
||||
await cls.updateUserSoilFields(uid, soilIndex, {"matureTime": currentTime})
|
||||
|
||||
@classmethod
|
||||
async def getUserFarmByUid(cls, uid: str) -> dict:
|
||||
"""获取指定用户的旧农场数据
|
||||
@@ -247,6 +276,25 @@ class CUserSoilDB(CSqlManager):
|
||||
columns = [description[0] for description in cursor.description]
|
||||
return dict(zip(columns, row))
|
||||
|
||||
@classmethod
|
||||
async def countSoilByLevel(cls, uid: str, soilLevel: int) -> int:
|
||||
"""统计指定用户在指定土地等级的土地数量
|
||||
|
||||
Args:
|
||||
uid (str): 用户ID
|
||||
soilLevel (int): 土地等级
|
||||
|
||||
Returns:
|
||||
int: 符合条件的土地数量
|
||||
"""
|
||||
async with cls._transaction():
|
||||
cursor = await cls.m_pDB.execute(
|
||||
"SELECT COUNT(*) FROM userSoil WHERE uid = ? AND soilLevel = ?",
|
||||
(uid, soilLevel),
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
return row[0] if row else 0
|
||||
|
||||
@classmethod
|
||||
async def updateUserSoil(cls, uid: str, soilIndex: int, field: str, value):
|
||||
"""更新指定用户土地的单个字段
|
||||
@@ -393,8 +441,8 @@ class CUserSoilDB(CSqlManager):
|
||||
bool: 播种成功返回 True,否则返回 False
|
||||
"""
|
||||
# 校验土地区是否已种植
|
||||
soilRecord = await cls.getUserSoil(uid, soilIndex)
|
||||
if soilRecord and soilRecord.get("plantName"):
|
||||
soilInfo = await cls.getUserSoil(uid, soilIndex)
|
||||
if not soilInfo:
|
||||
return False
|
||||
|
||||
# 获取植物配置
|
||||
@@ -404,11 +452,18 @@ class CUserSoilDB(CSqlManager):
|
||||
return False
|
||||
|
||||
nowTs = int(g_pToolManager.dateTime().now().timestamp())
|
||||
matureTs = nowTs + int(plantCfg.get("time", 0)) * 3600
|
||||
|
||||
time = int(plantCfg.get("time", 0))
|
||||
percent = await cls.getSoilLevelTime(soilInfo.get("soilLevel", 0))
|
||||
|
||||
# 处理土地等级带来的时间缩短
|
||||
time = time * (100 + percent) // 100
|
||||
|
||||
matureTs = nowTs + time * 3600
|
||||
|
||||
try:
|
||||
async with cls._transaction():
|
||||
prev = soilRecord or {}
|
||||
prev = soilInfo or {}
|
||||
await cls._deleteUserSoil(uid, soilIndex)
|
||||
await cls._insertUserSoil(
|
||||
{
|
||||
@@ -457,3 +512,90 @@ class CUserSoilDB(CSqlManager):
|
||||
status.append("缺水")
|
||||
|
||||
return ",".join(status)
|
||||
|
||||
@classmethod
|
||||
async def getSoilLevel(cls, level: int) -> str:
|
||||
"""获取土地等级英文文本
|
||||
|
||||
Args:
|
||||
level (int): 土地等级
|
||||
|
||||
Returns:
|
||||
str:
|
||||
"""
|
||||
if level == 1:
|
||||
return "red"
|
||||
elif level == 2:
|
||||
return "black"
|
||||
elif level == 3:
|
||||
return "gold"
|
||||
|
||||
return "default"
|
||||
|
||||
@classmethod
|
||||
async def getSoilLevelText(cls, level: int) -> str:
|
||||
"""获取土地等级中文文本
|
||||
|
||||
Args:
|
||||
level (int): 土地等级
|
||||
|
||||
Returns:
|
||||
str:
|
||||
"""
|
||||
if level == 1:
|
||||
return "红土地"
|
||||
elif level == 2:
|
||||
return "黑土地"
|
||||
elif level == 3:
|
||||
return "金土地"
|
||||
|
||||
return "草土地"
|
||||
|
||||
@classmethod
|
||||
async def getSoilLevelHarvestNumber(cls, level: int) -> int:
|
||||
"""获取土地等级收获数量增加比例
|
||||
|
||||
Args:
|
||||
level (int): 土地等级
|
||||
|
||||
Returns:
|
||||
int:
|
||||
"""
|
||||
if level == 2:
|
||||
return 20
|
||||
elif level == 3:
|
||||
return 28
|
||||
|
||||
return 10
|
||||
|
||||
@classmethod
|
||||
async def getSoilLevelHarvestExp(cls, level: int) -> int:
|
||||
"""获取土地等级收获经验增加比例
|
||||
|
||||
Args:
|
||||
level (int): 土地等级
|
||||
|
||||
Returns:
|
||||
int:
|
||||
"""
|
||||
if level == 3:
|
||||
return 28
|
||||
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
async def getSoilLevelTime(cls, level: int) -> int:
|
||||
"""获取土地等级播种减少时间消耗
|
||||
|
||||
Args:
|
||||
level (int): 土地等级
|
||||
|
||||
Returns:
|
||||
int:
|
||||
"""
|
||||
if level == 2:
|
||||
return 20
|
||||
elif level == 3:
|
||||
return 20
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user