diff --git a/.gitignore b/.gitignore index ed8ebf5..430cafa 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -__pycache__ \ No newline at end of file +__pycache__ + +./config/sign_in.json diff --git a/README.md b/README.md index 56b2fe7..606244d 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,42 @@ license + + Python + + + Nonebot + + + Python + +

+ +

+ +[![tencent-qq](https://img.shields.io/badge/%E7%BE%A4-%E7%9C%9F%E5%AF%BB%E5%86%9C%E5%9C%BA%E6%B5%8B%E8%AF%95-%23FF99CC +)](https://qm.qq.com/q/7hsOD4rOw2) +

你是说可以种地对吧🤔? +--- +## 目录 +- [真寻农场(zhenxun\_plugin\_farm)](#真寻农场zhenxun_plugin_farm) + - [目录](#目录) + - [如何安装](#如何安装) + - [使用指令](#使用指令) + - [更新日志(详细):](#更新日志详细) + - [用户方面](#用户方面) + - [代码方面](#代码方面) + - [待办事宜 `Todo` 列表](#待办事宜-todo-列表) + - [关于](#关于) + - [致谢](#致谢) + - [许可证](#许可证) + --- ## 如何安装 @@ -26,7 +56,7 @@ | --- | --- | --- | | @小真寻 开通农场 | 首次开通农场 | | | 我的农场币 | 查询农场币 | | -| 种子商店 [页数] | 查看种子商店 | 数量不填默认为1 | +| 种子商店 [筛选关键字] [页数] or [页数] | 查看种子商店 | 当第一个参数为非整数时,会默认进入筛选状态。页数不填默认为1 | | 购买种子 [种子名称] [数量] | 购买种子 | 数量不填默认为1 | | 我的种子 | 查询仓库种子 | | | 播种 [种子名称] [数量] | 播种种子 | 数量不填默认将最大可能播种 | @@ -37,20 +67,23 @@ | @美波理 偷菜 | 偷别人的菜 | 每人每天只能偷5次 | | 购买农场币 | 将真寻金币兑换成农场币 | 兑换比例默认为1:2 手续费默认20% | | 更改农场名 [新的农场名] | 改名 | +| 农场签到 | 签到 | 需要注意,该项会从服务器拉取签到数据 | --- ## 更新日志[(详细)](./log/log.md): 用户方面 --- -- 修复重大BUG,该BUG会导致用户经验等级计算异常 -- 修正种子价格,现在不会以单价的形式购买种子了,而是新增的种子价格 +- 新增种子商店筛选功能(如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能 +- 新增签到功能(测试 +- 新增农场详述功能,能通过该功能更加详细的观看农场数据 +- 修复了迁移旧数据库无法正常迁移的BUG 代码方面 --- -- 彻底重构数据库,但是不会像V1.1一样导致用户数据丢失 -- 迁移部分代码结构,使文件名和代码功能更加匹配 -- 加入事件机制,采用类似Qt信号槽机制 +- 修正了多阶段作物成长素材计算逻辑 +- 修正了作物数据库字段错乱的问题 +- 作物新增offset字段,用于以后偏移坐标(尚未加入代码 TODO --- ## 待办事宜 `Todo` 列表 diff --git a/__init__.py b/__init__.py index 12193d0..76914e2 100644 --- a/__init__.py +++ b/__init__.py @@ -22,7 +22,7 @@ __plugin_meta__ = PluginMetadata( at 开通农场 我的农场 我的农场币 - 种子商店 [页数] + 种子商店 [筛选关键字] [页数] or [页数] 购买种子 [作物/种子名称] [数量] 我的种子 播种 [作物/种子名称] [数量] (数量不填默认将最大可能播种 @@ -34,6 +34,7 @@ __plugin_meta__ = PluginMetadata( 开垦 购买农场币 [数量] 数量为消耗金币的数量 更改农场名 [新农场名] + 农场签到 """.strip(), extra=PluginExtraData( author="Art_Sakura", diff --git a/command.py b/command.py index 53cded2..5ed1044 100644 --- a/command.py +++ b/command.py @@ -1,3 +1,5 @@ +import inspect + from nonebot.adapters import Event, MessageTemplate from nonebot.rule import to_me from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args, @@ -125,7 +127,7 @@ diuse_farm = on_alconna( Option("--all", action=store_true), Subcommand("detail", help_text="农场详述"), Subcommand("my-point", help_text="我的农场币"), - Subcommand("seed-shop", Args["num?", int], help_text="种子商店"), + Subcommand("seed-shop", Args["res?", MultiVar(str)], help_text="种子商店"), Subcommand("buy-seed", Args["name?", str]["num?", int], help_text="购买种子"), Subcommand("my-seed", help_text="我的种子"), Subcommand("sowing", Args["name?", str]["num?", int], help_text="播种"), @@ -147,7 +149,7 @@ diuse_farm = on_alconna( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return image = await g_pFarmManager.drawFarmByUid(uid) @@ -164,7 +166,7 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return info = await g_pFarmManager.drawDetailFarmByUid(uid) @@ -197,13 +199,35 @@ diuse_farm.shortcut( ) @diuse_farm.assign("seed-shop") -async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 1)): +async def _(session: Uninfo, res: Match[tuple[str, ...]]): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return - image = await g_pShopManager.getSeedShopImage(num.result) + if res.result is inspect._empty: + raw = [] + else: + raw = res.result + + filterKey: str | int | None = None + page: int = 1 + + if len(raw) >= 1 and raw[0] is not None: + first = raw[0] + if isinstance(first, str) and first.isdigit(): + page = int(first) + else: + filterKey = first + + if len(raw) >= 2 and raw[1] is not None and isinstance(raw[1], str) and raw[1].isdigit(): + page = int(raw[1]) + + if filterKey is None: + image = await g_pShopManager.getSeedShopImage(page) + else: + image = await g_pShopManager.getSeedShopImage(filterKey, page) + await MessageUtils.build_message(image).send() diuse_farm.shortcut( @@ -214,7 +238,7 @@ diuse_farm.shortcut( ) @diuse_farm.assign("buy-seed") -async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1),): +async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)): if not name.available: await MessageUtils.build_message( "请在指令后跟需要购买的种子名称" @@ -222,7 +246,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pShopManager.buySeed(uid, name.result, num.result) @@ -239,7 +263,7 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.getUserSeedByUid(uid) @@ -253,7 +277,7 @@ diuse_farm.shortcut( ) @diuse_farm.assign("sowing") -async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),): +async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)): if not name.available: await MessageUtils.build_message( "请在指令后跟需要播种的种子名称" @@ -261,7 +285,7 @@ async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("n uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.sowing(uid, name.result, num.result) @@ -279,7 +303,7 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.harvest(uid) @@ -296,7 +320,7 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.eradicate(uid) @@ -314,7 +338,7 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.getUserPlantByUid(uid) @@ -331,7 +355,7 @@ reclamation = on_alconna( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return condition = await g_pFarmManager.reclamationCondition(uid) @@ -360,10 +384,10 @@ diuse_farm.shortcut( ) @diuse_farm.assign("sell-plant") -async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1),): +async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result) @@ -380,7 +404,7 @@ diuse_farm.shortcut( async def _(session: Uninfo, target: Match[At]): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return if not target.available: @@ -412,7 +436,7 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return result = await g_pFarmManager.buyPointByUid(uid, num.result) @@ -430,12 +454,12 @@ diuse_farm.shortcut( async def _(session: Uninfo, name: Match[str]): if not name.available: await MessageUtils.build_message( - "请在指令后跟需要更改的用户名" + "请在指令后跟需要更改的农场名" ).finish(reply_to=True) uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return safeName = sanitize_username(name.result) @@ -443,9 +467,9 @@ async def _(session: Uninfo, name: Match[str]): result = await g_pDBService.user.updateUserNameByUid(uid, safeName) if result == True: - await MessageUtils.build_message("更新用户名成功!").send(reply_to=True) + await MessageUtils.build_message("更新农场名成功!").send(reply_to=True) else: - await MessageUtils.build_message("更新用户名失败!").send(reply_to=True) + await MessageUtils.build_message("更新农场名失败!").send(reply_to=True) diuse_farm.shortcut( "农场签到", @@ -458,11 +482,11 @@ diuse_farm.shortcut( async def _(session: Uninfo): uid = str(session.user.id) - if await isRegisteredByUid(uid) == False: + if not await isRegisteredByUid(uid): return #判断签到是否正常加载 - if g_bSignStatus == False: + if not g_bSignStatus: await MessageUtils.build_message("签到功能异常!").send() return @@ -475,7 +499,6 @@ async def _(session: Uninfo): if status == 1 or status == 2: #获取签到总天数 signDay = await g_pDBService.userSign.getUserSignCountByDate(uid, toDay.strftime("%Y-%m")) - exp, point = await g_pDBService.userSign.getUserSignRewardByDate(uid, toDay.strftime("%Y-%m-%d")) message += f"签到成功!累计签到天数:{signDay}\n获得经验{exp},获得金币{point}" diff --git a/config/sign_in.json b/config/sign_in.json new file mode 100644 index 0000000..331e318 --- /dev/null +++ b/config/sign_in.json @@ -0,0 +1,78 @@ +{ + "date": "202505", + "exp_max": 50, + "exp_min": 5, + "point_max": 2000, + "point_min": 200, + "continuou": + { + "1": + { + "point": 3000, + "exp": 20 + }, + "3": + { + "point": 5000, + "exp": 25, + "plant": + { + "胡萝卜": 3 + } + }, + "5": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + }, + "7": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + }, + "10": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + }, + "15": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + }, + "20": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + }, + "25": + { + "point": 7000, + "exp": 50, + "plant": + { + "胡萝卜": 3 + } + } + } +} diff --git a/database/plant.py b/database/plant.py index 75c0432..216dc35 100644 --- a/database/plant.py +++ b/database/plant.py @@ -1,6 +1,8 @@ +import ast import os import re from contextlib import asynccontextmanager +from unittest import result import aiosqlite @@ -87,6 +89,102 @@ class CPlantManager: logger.warning(f"查询作物失败: {name}", e=e) return None + @classmethod + async def getPlantPhaseByName(cls, name: str) -> list: + """根据作物名称获取作物各个阶段 + + Args: + name (str): 作物名称 + + Returns: + list: 阶段数组 + """ + try: + async with cls.m_pDB.execute( + "SELECT phase FROM plant WHERE name = ?", (name,) + ) as cursor: + row = await cursor.fetchone() + + if not row: + return [] + + phase = row[0].split(',') + + seen = set() + result = [] + for x in phase: + if x not in seen: + seen.add(x) + result.append(x) + + return result + except Exception as e: + logger.warning(f"查询作物阶段失败: {name}", e=e) + return [] + + @classmethod + async def getPlantPhaseNumberByName(cls, name: str) -> int: + """根据作物名称获取作物总阶段数 + + Args: + name (str): 作物名称 + + Returns: + int: 总阶段数 + """ + try: + async with cls.m_pDB.execute( + "SELECT phase FROM plant WHERE name = ?", (name,) + ) as cursor: + row = await cursor.fetchone() + + if not row: + return -1 + + phase = row[0].split(',') + + #去重 + seen = set() + result = [] + for x in phase: + if x not in seen: + seen.add(x) + result.append(x) + + return len(result) + except Exception as e: + logger.warning(f"查询作物阶段失败: {name}", e=e) + return -1 + + @classmethod + async def getPlantAgainByName(cls, name: str) -> int: + """根据作物名称获取作物再次成熟时间 + + Args: + name (str): 作物名称 + + Returns: + int: 再次成熟时间 单位:h + """ + + try: + async with cls.m_pDB.execute( + "SELECT phase FROM plant WHERE name = ?", (name,) + ) as cursor: + row = await cursor.fetchone() + + if not row: + return -1 + + phase = row[0].split(',') + again = phase[-1] - phase[3] / 60 / 60 + + return again + + except Exception as e: + logger.warning(f"查询作物阶段失败: {name}", e=e) + return -1 + @classmethod async def existsPlant(cls, name: str) -> bool: """判断作物是否存在 diff --git a/database/userSign.py b/database/userSign.py index e43b053..dea9c8e 100644 --- a/database/userSign.py +++ b/database/userSign.py @@ -8,8 +8,8 @@ from zhenxun.utils._build_image import BuildImage from ..dbService import g_pDBService from ..json import g_pJsonManager -from .database import CSqlManager from ..tool import g_pToolManager +from .database import CSqlManager class CUserSignDB(CSqlManager): @@ -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'))",#创建时间 "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'))"#更新时间 } await cls.ensureTableSchema("userSignLog", userSignLog) @@ -188,7 +188,7 @@ class CUserSignDB(CSqlManager): ) #计算累签奖励 - reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays + 1}", None) + reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays}", None) if reward: point += reward.get('point', 0) diff --git a/database/userSoil.py b/database/userSoil.py index 5500637..9702930 100644 --- a/database/userSoil.py +++ b/database/userSoil.py @@ -4,8 +4,8 @@ from zhenxun.services.log import logger from ..dbService import g_pDBService from ..json import g_pJsonManager -from .database import CSqlManager from ..tool import g_pToolManager +from .database import CSqlManager class CUserSoilDB(CSqlManager): @@ -241,6 +241,45 @@ class CUserSoilDB(CSqlManager): (value, uid, soilIndex), ) + @classmethod + async def updateUserSoilFields(cls, uid: str, soilIndex: int, updates: dict) -> bool: + """批量更新指定用户土地的多个字段 + + Args: + uid (str): 用户ID + soilIndex (int): 土地索引 + updates (dict): 字段-新值的字典 + + Returns: + bool: 如果无可更新字段则返回 False,否则更新成功返回 True + """ + #允许更新的列白名单 + allowedFields = { + "plantName", "plantTime", "matureTime", "soilLevel", + "wiltStatus", "fertilizerStatus", "bugStatus", + "weedStatus", "waterStatus", "harvestCount" + } + setClauses = [] + values = [] + for field, value in updates.items(): + if field not in allowedFields: + continue + setClauses.append(f'"{field}" = ?') + values.append(value) + if not setClauses: + return False + + values.extend([uid, soilIndex]) + sql = f'UPDATE userSoil SET {", ".join(setClauses)} WHERE uid = ? AND soilIndex = ?' + + try: + async with cls._transaction(): + await cls.m_pDB.execute(sql, tuple(values)) + return True + except Exception as e: + logger.error(f"批量更新土地字段失败: {e}") + return False + @classmethod async def deleteUserSoil(cls, uid: str, soilIndex: int): """删除指定用户的土地记录 diff --git a/farm/farm.py b/farm/farm.py index 6708c55..306c28d 100644 --- a/farm/farm.py +++ b/farm/farm.py @@ -289,18 +289,19 @@ class CFarmManager: currentTime = g_pToolManager.dateTime().now() matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime'])) + phase = await g_pDBService.plant.getPlantPhaseNumberByName(soilInfo['plantName']) + #如果当前时间大于成熟时间 说明作物成熟 if currentTime >= matureTime: - phase = int(plantInfo['phase']) - plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase - 1}.png") + plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{phase}.png") return True, plant, True else: - #如果是多阶段作物 且没有成熟 - if soilInfo['harvestCount'] >= 1: - plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 2}.png") + #如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片 + # if soilInfo['harvestCount'] >= 1: + # plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1s}.png") - return True, plant, False + # return True, plant, False #如果没有成熟 则根据当前阶段进行绘制 plantedTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['plantTime'])) @@ -308,7 +309,7 @@ class CFarmManager: elapsedTime = currentTime - plantedTime elapsedHour = elapsedTime.total_seconds() / 3600 - currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1))) + currentStage = int(elapsedHour / (plantInfo['time'] / phase)) if currentStage <= 0: if plantInfo['general'] == False: @@ -334,7 +335,6 @@ class CFarmManager: "收获数量", "成熟时间(小时)", "收获次数", - "再次成熟时间(小时)", "是否可以上架交易行" ] @@ -358,7 +358,7 @@ class CFarmManager: iconPath = g_sResourcePath / f"plant/{seedName}/icon.png" icon = (iconPath, 33, 33) if iconPath.exists() else "" - sellable = "可以" if plantInfo['again'] else "不可以" + sellable = "可以" if plantInfo['sell'] else "不可以" dataList.append([ icon, @@ -368,7 +368,6 @@ class CFarmManager: plantInfo['harvest'], plantInfo['time'], plantInfo['crop'], - plantInfo['again'], sellable ]) except KeyError: @@ -509,11 +508,18 @@ class CFarmManager: if soilInfo['harvestCount'] + 1 >= plantInfo['crop']: await g_pDBService.userSoil.updateUserSoil(uid, i, "wiltStatus", 1) else: - matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600 + phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName']) - await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1) - await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp())) - await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs) + ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1 + p1, p2, *rest = phase + + await g_pDBService.userSoil.updateUserSoilFields(uid, i, + { + "harvestCount": hc, + "plantTime": ts - p1 - p2, + "matureTime": ts + p2 + sum(rest), + } + ) await g_pEventManager.m_afterHarvest.emit(uid=uid, name=soilInfo['plantName'], num=number, soilIndex=i) @@ -619,7 +625,7 @@ class CFarmManager: if icon_path.exists(): icon = (icon_path, 33, 33) - if plantInfo['again'] == True: + if plantInfo['sell'] == True: sell = "可以" else: sell = "不可以" @@ -722,11 +728,18 @@ class CFarmManager: if soilInfo['harvestCount'] + 1 >= plantInfo['crop']: await g_pDBService.userSoil.updateUserSoil(target, i, "wiltStatus", 1) else: - matureTs = int(currentTime.timestamp()) + int(plantInfo.get("again", 0)) * 3600 + phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName']) - await g_pDBService.userSoil.updateUserSoil(uid, i, "harvestCount", soilInfo['harvestCount'] + 1) - await g_pDBService.userSoil.updateUserSoil(uid, i, "lastResetTime", int(currentTime.timestamp())) - await g_pDBService.userSoil.updateUserSoil(uid, i, "matureTime", matureTs) + ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1 + p1, p2, *rest = phase + + await g_pDBService.userSoil.updateUserSoilFields(uid, i, + { + "harvestCount": hc, + "plantTime": ts - p1 - p2, + "matureTime": ts + p2 + sum(rest), + } + ) await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(g_pToolManager.dateTime().now().timestamp())) diff --git a/farm/shop.py b/farm/shop.py index d5f024a..1843b0d 100644 --- a/farm/shop.py +++ b/farm/shop.py @@ -12,16 +12,28 @@ from ..json import g_pJsonManager class CShopManager: - @classmethod - async def getSeedShopImage(cls, num: int = 1) -> bytes: + async def getSeedShopImage(cls, filterKey: str|int = 1, num: int = 1) -> bytes: """获取商店页面 + Args: + filterKey (str|int): + - 字符串: 根据关键字筛选种子名称 + - 整数: 翻至对应页(无筛选) + num (int, optional): 当 filterKey 为字符串时,用于指定页码。Defaults to 1. + Returns: bytes: 返回商店图片bytes """ + # 解析参数:区分筛选关键字和页码 + filterStr = None + if isinstance(filterKey, int): + page = filterKey + else: + filterStr = filterKey + page = num - dataList = [] + # 表头定义 columnName = [ "-", "种子名称", @@ -32,59 +44,65 @@ class CShopManager: "收获数量", "成熟时间(小时)", "收获次数", - "再次成熟时间(小时)", "是否可以上架交易行" ] - sell = "" + # 查询所有可购买作物,并根据筛选关键字过滤 plants = await g_pDBService.plant.listPlants() - plantSize = await g_pDBService.plant.countPlants(True) - - start = (num - 1) * 15 - items = islice(plants, start, start + 15) - - for plant in items: + filteredPlants = [] + for plant in plants: + # 跳过未解锁购买的种子 if plant['isBuy'] == 0: continue + # 字符串筛选 + if filterStr and filterStr not in plant['name']: + continue + filteredPlants.append(plant) + # 计算分页 + totalCount = len(filteredPlants) + pageCount = math.ceil(totalCount / 15) if totalCount else 1 + startIndex = (page - 1) * 15 + pageItems = filteredPlants[startIndex: startIndex + 15] + + # 构建数据行 + dataList = [] + for plant in pageItems: + # 图标处理 icon = "" iconPath = g_sResourcePath / f"plant/{plant['name']}/icon.png" if iconPath.exists(): icon = (iconPath, 33, 33) - if plant['again'] == True: - sell = "可以" - else: - sell = "不可以" + # 交易行标记 + sell = "可以" if plant['sell'] else "不可以" - dataList.append( - [ - icon, - plant['name'], - plant['buy'], - plant['level'], - plant['price'], - plant['experience'], - plant['harvest'], - plant['time'], - plant['crop'], - plant['again'], - sell - ] - ) + dataList.append([ + icon, + plant['name'], # 种子名称 + plant['buy'], # 种子单价 + plant['level'], # 解锁等级 + plant['price'], # 果实单价 + plant['experience'], # 收获经验 + plant['harvest'], # 收获数量 + plant['time'], # 成熟时间(小时) + plant['crop'], # 收获次数 + sell # 是否可上架交易行 + ]) - count = math.ceil(plantSize / 15) - title = f"种子商店 页数: {num}/{count}" + # 页码标题 + title = f"种子商店 页数: {page}/{pageCount}" + # 渲染表格并返回图片bytes result = await ImageTemplate.table_page( title, "购买示例:@小真寻 购买种子 大白菜 5", columnName, dataList, ) - return result.pic2bytes() + @classmethod async def buySeed(cls, uid: str, name: str, num: int = 1) -> str: """购买种子 @@ -120,7 +138,7 @@ class CShopManager: else: await g_pDBService.user.updateUserPointByUid(uid, point - total) - if await g_pDBService.userSeed.addUserSeedByUid(uid, name, num) == False: + if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num): return "购买失败,执行数据库错误!" return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币" diff --git a/log/log.md b/log/log.md index acc7f9b..b0243c3 100644 --- a/log/log.md +++ b/log/log.md @@ -1,5 +1,19 @@ # 真寻农场更新日志 +## V1.4 +用户方面 +--- +- 新增种子商店筛选功能(如果没有BUG的话后续我的种子、我的作物等也会加入筛选功能 +- 新增签到功能(测试 +- 新增农场详述功能,能通过该功能更加详细的观看农场数据 +- 修复了迁移旧数据库无法正常迁移的BUG + +代码方面 +--- +- 修正了多阶段作物成长素材计算逻辑 +- 修正了作物数据库字段错乱的问题 +- 作物新增offset字段,用于以后偏移坐标(尚未加入代码 TODO + ## V1.3 用户方面 --- diff --git a/resource/db/plant.db b/resource/db/plant.db index 32e8163..46975e9 100644 Binary files a/resource/db/plant.db and b/resource/db/plant.db differ