From ca6eb3343ff704ddde0b76b248fd3fd43710e0a9 Mon Sep 17 00:00:00 2001 From: Art_Sakura <1754798088@qq.com> Date: Wed, 19 Mar 2025 01:16:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=98=BE=E7=A4=BA=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=86=9C=E5=9C=BA=E5=9B=BE=E7=89=87=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=83=A8=E5=88=86JSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __init__.py | 6 -- config/item.json | 16 ++-- config/level.json | 7 +- config/plant.json | 30 ++++---- config/soil.json | 121 +++++++++++++++--------------- database.py | 184 +++++++++++++++++++++++++++++++++++++++++++--- drawImage.py | 18 ++--- farm/farm.py | 41 +++++++++++ farm/shop.py | 24 ++++++ 9 files changed, 335 insertions(+), 112 deletions(-) diff --git a/__init__.py b/__init__.py index c26b52a..48a306c 100644 --- a/__init__.py +++ b/__init__.py @@ -31,17 +31,11 @@ driver = get_driver() @driver.on_startup async def start(): # 初始化数据库 - # await g_pSqlManager.init() - await g_pSqlManager.init() # 初始化读取Json - # await g_pJsonManager.init() await g_pJsonManager.init() - # await g_pDrawImage.drawMyFarm("11223") - await g_pDrawImage.drawMyFarm("22") - # 析构函数 @driver.on_shutdown async def shutdown(): diff --git a/config/item.json b/config/item.json index 6056e4a..cfcc39d 100644 --- a/config/item.json +++ b/config/item.json @@ -1,14 +1,14 @@ { + "zhuShi": + [ + "name: 名称", + "level: 等级", + "price: 单价", + "icon: 显示图片", + "sell: 是否可以上架交易行" + ], "item": { - "zhuShi": - [ - "name: 名称", - "level: 等级", - "price: 单价", - "icon: 显示图片", - "sell: 是否可以上架交易行" - ], "muBan": { "name": "木板", diff --git a/config/level.json b/config/level.json index 44863c1..7ec4659 100644 --- a/config/level.json +++ b/config/level.json @@ -2,9 +2,10 @@ "level": { "1": 0, - "2": 3000, - "3": 7500 + "2": 500, + "3": 1250, + "4": 3000 }, - "soil":[1, 5, 10, 15, 25, 35], + "soil":[1, 1, 1, 5, 10, 15, 25], "point":[0, 2000, 5000, 10000, 30000, 50000] } diff --git a/config/plant.json b/config/plant.json index 2e25184..e1793f4 100644 --- a/config/plant.json +++ b/config/plant.json @@ -1,21 +1,21 @@ { + "zhuShi": + [ + "name: 名称", + "level: 解锁等级", + "limit: 限制等级 0:普通土地 1:红土地 2:黄土地 3:黑土地", + "experience: 收获经验", + "harvest: 收获数量", + "price: 单价", + "time: 成熟时间 单位:分钟", + "crop: 作物可以收几次", + "again: 再次成熟时间 单位:分钟", + "phase: 阶段 目前为 成熟时间 / 阶段 来显示每阶段图片", + "general: 第一阶段是否为通用阶段素材", + "sell: 是否可以上架交易行" + ], "plant": { - "zhuShi": - [ - "name: 名称", - "level: 解锁等级", - "limit: 限制等级 0:普通土地 1:红土地 2:黄土地 3:黑土地", - "experience: 收获经验", - "harvest: 收获数量", - "price: 单价", - "time: 成熟时间 单位:分钟", - "crop: 作物可以收几次", - "again: 再次成熟时间 单位:分钟", - "phase: 阶段 目前为 成熟时间 / 阶段 来显示每阶段图片", - "general: 第一阶段是否为通用阶段素材", - "sell: 是否可以上架交易行" - ], "daBaiCai": { "name": "大白菜", diff --git a/config/soil.json b/config/soil.json index 3008dfa..4197087 100644 --- a/config/soil.json +++ b/config/soil.json @@ -1,155 +1,156 @@ { + "size":[234.378, 156.252], "soil": { "1": { - "x": 1341, - "y": 571 + "x": 1352, + "y": 552 }, "2": { - "x": 1455, - "y": 627 + "x": 1462, + "y": 611 }, "3": { - "x": 1574, - "y": 686 + "x": 1572, + "y": 670 }, "4": { - "x": 1689, - "y": 745 + "x": 1682, + "y": 729 }, "5": { - "x": 1806, - "y": 804 + "x": 1792, + "y": 788 }, "6": { - "x": 1926, - "y": 863 + "x": 1902, + "y": 847 }, "7": { - "x": 1226, - "y": 627 + "x": 1242, + "y": 611 }, "8": { - "x": 1340, - "y": 683 + "x": 1343, + "y": 670 }, "9": { - "x": 1455, - "y": 739 + "x": 1462, + "y": 729 }, "10": { - "x": 1573, - "y": 798 + "x": 1572, + "y": 788 }, "11": { - "x": 1690, - "y": 857 + "x": 1682, + "y": 847 }, "12": { - "x": 1807, - "y": 916 + "x": 1792, + "y": 906 }, "13": { - "x": 1111, - "y": 683 + "x": 1123, + "y": 670 }, "14": { - "x": 1226, - "y": 739 + "x": 1233, + "y": 729 }, "15": { - "x": 1340, - "y": 795 + "x": 1343, + "y": 788 }, "16": { - "x": 1458, - "y": 855 + "x": 1462, + "y": 847 }, "17": { - "x": 1575, - "y": 912 + "x": 1572, + "y": 906 }, "18": { - "x": 1693, - "y": 972 + "x": 1678, + "y": 965 }, "19": { - "x": 997, - "y": 739 + "x": 1013, + "y": 729 }, "20": { - "x": 1111, - "y": 795 + "x": 1114, + "y": 788 }, "21": { - "x": 1225, - "y": 851 + "x": 1233, + "y": 847 }, "22": { - "x": 1341, - "y": 910 + "x": 1352, + "y": 906 }, "23": { - "x": 1461, - "y": 967 + "x": 1458, + "y": 965 }, "24": { - "x": 1578, - "y": 1025 + "x": 1572, + "y": 1024 }, "25": { - "x": 882, - "y": 795 + "x": 894, + "y": 788 }, "26": { - "x": 997, - "y": 851 + "x": 1004, + "y": 847 }, "27": { - "x": 1111, - "y": 907 + "x": 1123, + "y": 906 }, "28": { - "x": 1226, - "y": 963 + "x": 1233, + "y": 965 }, "29": { - "x": 1343, - "y": 1025 + "x": 1347, + "y": 1024 }, "30": { - "x": 1460, - "y": 1084 + "x": 1462, + "y": 1083 } } } diff --git a/database.py b/database.py index 9592a2f..f08b3e9 100644 --- a/database.py +++ b/database.py @@ -1,10 +1,12 @@ import os +from io import StringIO +from typing import Any, List, Optional import aiosqlite from zhenxun.services.log import logger -from .config import CJsonManager, g_sDBFilePath, g_sDBPath +from .config import g_pJsonManager, g_sDBFilePath, g_sDBPath class CSqlManager: @@ -31,27 +33,100 @@ class CSqlManager: @classmethod async def createDB(cls) -> bool: - """初始化数据库表 + """初始化数据库用户信息表 Returns: bool: 是否创建成功 """ + #用户信息 + userInfo = """ + CREATE TABLE user ( + uid INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + exp INTEGER DEFAULT 0, + point INTEGER DEFAULT 0 + ); + """ + + #用户仓库 + userStorehouse = """ + CREATE TABLE storehouse ( + uid INTEGER PRIMARY KEY AUTOINCREMENT, + item TEXT DEFAULT '', + plant TEXT DEFAULT '' + ); + """ + + #用户土地信息 + with StringIO() as buffer: + buffer.write("CREATE TABLE soil (") + buffer.write("uid INTEGER PRIMARY KEY AUTOINCREMENT,") + + fields = [f"soil{i} TEXT DEFAULT ''" for i in range(1, 31)] + buffer.write(",\n".join(fields)) + + buffer.write(");") + + userSoilInfo = buffer.getvalue() + + if not await cls.executeDB(userInfo): + return False + + if not await cls.executeDB(userStorehouse): + return False + + if not await cls.executeDB(userSoilInfo): + return False + + 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: - await cls.m_pDB.execute(""" - CREATE TABLE user ( - uid INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - exp INTEGER DEFAULT 0, - point INTEGER DEFAULT 0 - ); - """) + await cls.m_pDB.execute(command) await cls.m_pDB.commit() return True except Exception as e: - print(f"An error occurred: {e}") + logger.warning("数据库语句执行出错:" + command) return False + @classmethod + async def executeDBCursor(cls, command: str) -> Optional[List[Any]]: + """执行自定义SQL并返回查询结果 + + Args: + command (str): SQL查询语句 + + Returns: + Optional[List[Any]]: 查询结果列表(成功时),None(失败时) + """ + if len(command) <= 0: + logger.warning("空数据库命令") + return None + + try: + async with cls.m_pDB.execute(command) as cursor: + # 将Row对象转换为字典列表 + results = [dict(row) for row in await cursor.fetchall()] + return results + except Exception as e: + logger.error(f"数据库执行失败: {e}") + return None + @classmethod async def getUserInfoByUid(cls, uid: str) -> list[dict]: """根据用户Uid获取用户信息 @@ -108,6 +183,40 @@ class CSqlManager: logger.warning(f"查询失败: {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: + async with cls.m_pDB.execute( + """UPDATE user + SET point = ? + WHERE uid = ? + RETURNING point""", + (point, uid) + ) as cursor: + async for row in cursor: + return int(row[0]) + + logger.info(f"未找到用户或未修改数据: uid={uid}") + return -1 + except Exception as e: + # 记录详细错误日志(建议记录堆栈) + logger.error(f"更新失败: {e}") + return -1 + @classmethod async def getUserLevelByUid(cls, uid: str) -> int: """根据用户Uid获取用户等级 @@ -135,6 +244,8 @@ class CSqlManager: for key in sorted_keys: if exp >= levelDict[key]: return int(key) + + return -1 except Exception as e: logger.warning(f"查询失败: {e}") return -1 @@ -188,4 +299,55 @@ class CSqlManager: logger.warning(f"添加失败: {e}") return False + # @classmethod + # async def getUserStorehousePlant(cls, info: list[dict]) -> str: + # """获取用户仓库种子信息 + + # Args: + # info (list[dict]): 用户信息 + + # Returns: + # str: 仓库种子信息 + # """ + + # try: + # await cls.m_pDB.execute( + # """ + # INSERT INTO user (uid, name, exp, point) VALUES (?, ?, ?, ?) + # """, + # (info["uid"], info["name"], info["exp"], info["point"]), + # ) + # await cls.m_pDB.commit() + + # return True + # except Exception as e: + # logger.warning(f"添加失败: {e}") + # return False + + # @classmethod + # async def appendUserByUserInfo(cls, info: list[dict]) -> bool: + # """添加用户信息 + + # Args: + # info (list[dict]): 用户信息 + + # Returns: + # bool: 是否添加成功 + # """ + + # try: + # await cls.m_pDB.execute( + # """ + # INSERT INTO user (uid, name, exp, point) VALUES (?, ?, ?, ?) + # """, + # (info["uid"], info["name"], info["exp"], info["point"]), + # ) + # await cls.m_pDB.commit() + + # return True + # except Exception as e: + # logger.warning(f"添加失败: {e}") + # return False + + g_pSqlManager = CSqlManager() diff --git a/drawImage.py b/drawImage.py index 0dd728b..c85d64f 100644 --- a/drawImage.py +++ b/drawImage.py @@ -1,5 +1,3 @@ -from ast import arg - from zhenxun.services.log import logger from zhenxun.utils._build_image import BuildImage @@ -19,24 +17,26 @@ class CDrawImageManager: Returns: bytes: 返回绘制结果 """ - # soilNumber = await self.m_pSql.getUserLevelByUid(uid) - soilNumber = 1 + soilNumber = await g_pSqlManager.getUserLevelByUid(uid) img = BuildImage(background=g_sResourcePath / "background/background.jpg") + soilSize = g_pJsonManager.m_pSoil['size'] # type: ignore + + #TODO 缺少判断用户土地资源状况 soil = BuildImage(background=g_sResourcePath / "soil/普通土地.png") - await soil.resize(0, 229, 112) + await soil.resize(0, soilSize[0], soilSize[1]) grass = BuildImage(background=g_sResourcePath / "soil/草土地.png") - await grass.resize(0, 229, 112) + await grass.resize(0, soilSize[0], soilSize[1]) - soilPos = g_pJsonManager.m_pSoil['soil'] + soilPos = g_pJsonManager.m_pSoil['soil'] # type: ignore for key, value in soilPos.items(): if soilNumber >= int(key): - await img.paste(soil, (value['x'], value['y']), center_type="center") + await img.paste(soil, (value['x'], value['y'])) else: - await img.paste(grass, (value['x'], value['y']), center_type="center") + await img.paste(grass, (value['x'], value['y'])) return img.pic2bytes() diff --git a/farm/farm.py b/farm/farm.py index e69de29..b14f51c 100644 --- a/farm/farm.py +++ b/farm/farm.py @@ -0,0 +1,41 @@ +from zhenxun.services.log import logger +from zhenxun.utils._build_image import BuildImage + +from ..config import g_pJsonManager, g_sResourcePath +from ..database import g_pSqlManager + + +class CFarmManager: + + @classmethod + async def drawFarm(cls, uid: str) -> bytes: + """绘制农场 + + Args: + uid (str): 用户UID + + Returns: + bytes: 返回绘制结果 + """ + soilNumber = await g_pSqlManager.getUserLevelByUid(uid) + + img = BuildImage(background=g_sResourcePath / "background/background.jpg") + + soilSize = g_pJsonManager.m_pSoil['size'] # type: ignore + + #TODO 缺少判断用户土地资源状况 + soil = BuildImage(background=g_sResourcePath / "soil/普通土地.png") + await soil.resize(0, soilSize[0], soilSize[1]) + + grass = BuildImage(background=g_sResourcePath / "soil/草土地.png") + await grass.resize(0, soilSize[0], soilSize[1]) + + soilPos = g_pJsonManager.m_pSoil['soil'] # type: ignore + + for key, value in soilPos.items(): + if soilNumber >= int(key): + await img.paste(soil, (value['x'], value['y'])) + else: + await img.paste(grass, (value['x'], value['y'])) + + return img.pic2bytes() \ No newline at end of file diff --git a/farm/shop.py b/farm/shop.py index a48f3b8..d601247 100644 --- a/farm/shop.py +++ b/farm/shop.py @@ -1,3 +1,8 @@ +from zhenxun.services.log import logger +from zhenxun.utils._build_image import BuildImage + +from ..config import g_pJsonManager, g_sResourcePath +from ..database import g_pSqlManager class CShopManager: @@ -5,3 +10,22 @@ class CShopManager: @classmethod async def getPlantShopImage(cls) -> bytes: return bytes() + + @classmethod + async def buyPlant(cls, uid: str, name: str, num: int = 1) -> str: + if num <= 0: + return "请输入购买数量!" + + plants = g_pJsonManager.m_pPlant['plant'] # type: ignore + + for key, plant in plants.items(): + if plant['name'] == name: + point = g_pSqlManager.getUserPointByUid(uid) + total = int(plant['price']) * num + + if point < total + return "你的农场币不够哦~ 快速速氪金吧!" + else: + await g_pSqlManager.updateUserPointByUid(uid, point - total) + + pass \ No newline at end of file