From 1716985d1ad8ce066beaa0eaff03266b7a437ae3 Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Sat, 15 Nov 2025 00:56:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E6=94=B6=E8=8E=B7=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E5=9C=B0=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tasks/2025-11-15_1_harvest-multiple-plots.md | 99 +++++++++++ PWF | 2 +- .../WPSGardenSystem/garden_plugin_harvest.py | 160 +++++++++++++----- 3 files changed, 213 insertions(+), 48 deletions(-) create mode 100644 .tasks/2025-11-15_1_harvest-multiple-plots.md diff --git a/.tasks/2025-11-15_1_harvest-multiple-plots.md b/.tasks/2025-11-15_1_harvest-multiple-plots.md new file mode 100644 index 0000000..d0ce8a8 --- /dev/null +++ b/.tasks/2025-11-15_1_harvest-multiple-plots.md @@ -0,0 +1,99 @@ +# 背景 +文件名:2025-11-15_1_harvest-multiple-plots.md +创建于:2025-11-15_00:37:12 +创建者:ASUS@LIUBAI095 +主分支:main +任务分支:main +Yolo模式:Off + +# 任务描述 +修改收获指令,从只能收获单个地块改为可以一次收获多个地块。 + +当前格式:`收获 <地块序号>` +新格式:`收获 <地块序号> [地块序号...]` + +# 项目概览 +这是一个基于WPS Bot的菜园系统插件。当前收获功能只支持一次收获一个地块,用户希望能够一次收获多个地块,提高操作效率。 + +# 分析 +## 当前实现分析 +1. **garden_plugin_harvest.py**: + - `callback` 方法(第59-112行)只解析单个地块序号 + - 第64-66行:只提取第一个token作为地块序号 + - 第71-75行:调用 `service().harvest()` 处理单个地块 + - 第79-112行:处理单个地块的收获结果并返回消息 + +2. **garden_service.py**: + - `harvest` 方法(第181-235行)每次只处理一个地块 + - 该方法会删除地块记录,返回收获结果 + +3. **指令格式说明**: + - 第25行:`identifier="收获 <地块序号>"` + - 第33行:步骤说明中只提到"输入正整数地块序号" + - 第46行:帮助文档中也是单个地块格式 + +## 需要修改的部分 +1. **解析多个地块序号**:修改 `callback` 方法,支持解析空格分隔的多个地块序号 +2. **循环处理多个地块**:对每个地块序号调用 `harvest` 方法 +3. **汇总结果**:收集所有成功和失败的结果,统一返回给用户 +4. **更新文档**:更新指令格式说明和帮助文档 + +## 关键逻辑考虑 +- 每个地块的收获是独立的,可能触发不同的额外奖励 +- 需要处理部分成功的情况(某些地块成功,某些失败) +- 需要汇总所有收获的果实和额外奖励 +- 错误处理:如果某个地块失败,应该继续处理其他地块,最后汇总所有结果 + +# 提议的解决方案 +## 方案概述 +修改 `garden_plugin_harvest.py` 的 `callback` 方法,支持解析和处理多个地块序号。 + +## 具体实现思路 +1. **解析多个地块序号**: + - 将 `payload.split()` 后的所有token都解析为地块序号 + - 过滤掉非数字的token + - 去重处理,避免重复收获同一地块 + +2. **循环处理**: + - 对每个地块序号调用 `service().harvest()` + - 使用try-except捕获每个地块的错误 + - 记录成功和失败的结果 + +3. **结果汇总**: + - 统计成功收获的地块数量 + - 汇总所有基础果实(按作物类型分组) + - 汇总所有额外奖励(积分和物品) + - 列出失败的地块及原因 + +4. **消息格式**: + - 如果全部成功:显示汇总信息 + - 如果部分成功:分别显示成功和失败信息 + - 如果全部失败:显示所有失败原因 + +5. **文档更新**: + - 更新 `collect_command_entries` 中的指令格式 + - 更新 `collect_guide_entries` 中的帮助说明 + +# 当前执行步骤:"已完成所有实施步骤" + +# 任务进度 +[2025-11-15_00:51:11] +- 已修改:Plugins/WPSGardenSystem/garden_plugin_harvest.py +- 更改: + 1. 更新 collect_command_entries 方法:修改 identifier 为 "收获 <地块序号> [地块序号...]",更新 description 和 details 说明支持多个地块 + 2. 更新 collect_guide_entries 方法:修改指令格式描述,说明支持多个地块序号 + 3. 重构 callback 方法: + - 修改解析逻辑:支持解析多个地块序号,添加去重处理 + - 重构处理逻辑:循环处理每个地块,收集成功和失败结果 + - 添加数据结构:successful_harvests, failed_harvests, fruit_counts, extra_items, total_points_gained + - 实现果实统计和额外奖励汇总 + - 统一积分结算:在所有地块处理完成后统一调用 adjust_user_points + - 重构消息生成:根据成功和失败结果生成汇总消息,包括地块列表、果实汇总、额外奖励等 + - 处理边界情况:支持部分成功、全部失败等场景 +- 原因:实现一次收获多个地块的功能,提高用户操作效率 +- 阻碍因素:无 +- 状态:未确认 + +# 最终审查 +[待完成] + diff --git a/PWF b/PWF index 9cb259f..89de330 160000 --- a/PWF +++ b/PWF @@ -1 +1 @@ -Subproject commit 9cb259f2c71f5814062c8aeae3cc83a90f0f9ec3 +Subproject commit 89de330e2d102d59c6732b017fee7ec8d04bc186 diff --git a/Plugins/WPSGardenSystem/garden_plugin_harvest.py b/Plugins/WPSGardenSystem/garden_plugin_harvest.py index 3286d7c..9a22744 100644 --- a/Plugins/WPSGardenSystem/garden_plugin_harvest.py +++ b/Plugins/WPSGardenSystem/garden_plugin_harvest.py @@ -22,15 +22,15 @@ class WPSGardenHarvest(WPSGardenBase): return ( GuideEntry( title="收获", - identifier="收获 <地块序号>", - description="从成熟地块采摘果实并发放额外奖励。", + identifier="收获 <地块序号> [地块序号...]", + description="从成熟地块采摘果实并发放额外奖励。支持一次收获多个地块。", metadata={"别名": "harvest"}, icon="🧺", details=[ { "type": "steps", "items": [ - "输入正整数地块序号。", + "输入一个或多个正整数地块序号,用空格分隔。", "系统校验成熟状态,计算基础果实数量。", "发放额外奖励:积分或额外物品会自动结算。", ], @@ -43,7 +43,7 @@ class WPSGardenHarvest(WPSGardenBase): return ( { "title": "指令格式", - "description": "`收获 <地块序号>`,序号需为正整数。", + "description": "`收获 <地块序号> [地块序号...]`,支持一次收获多个地块,序号用空格分隔,序号需为正整数。", }, { "title": "收益构成", @@ -59,56 +59,122 @@ class WPSGardenHarvest(WPSGardenBase): async def callback(self, message: str, chat_id: int, user_id: int) -> Optional[str]: payload = self.parse_message_after_at(message).strip() if not payload: - return await self.send_markdown_message("❌ 指令格式:`收获 <地块序号>`", chat_id, user_id) + return await self.send_markdown_message("❌ 指令格式:`收获 <地块序号> [地块序号...]`", chat_id, user_id) tokens = [token.strip() for token in payload.split() if token.strip()] - if not tokens or not tokens[0].isdigit(): - return await self.send_markdown_message("❌ 指令格式:`收获 <地块序号>`", chat_id, user_id) - plot_index = int(tokens[0]) + + # 解析多个地块序号 + plot_indices = [] + for token in tokens: + if token.isdigit(): + plot_index = int(token) + if plot_index > 0: # 确保是正整数 + plot_indices.append(plot_index) + + # 去重 + plot_indices = list(set(plot_indices)) + + if not plot_indices: + return await self.send_markdown_message("❌ 指令格式:`收获 <地块序号> [地块序号...]`", chat_id, user_id) fortune: WPSFortuneSystem = Architecture.Get(WPSFortuneSystem) fortune_value = fortune.get_fortune_value(user_id) - try: - result = self.service().harvest( - user_id=user_id, - plot_index=plot_index, - fortune_value=fortune_value, - ) - except ValueError as exc: - return await self.send_markdown_message(f"❌ {exc}", chat_id, user_id) - - crop = result["crop"] - base_qty = result["base_yield"] backpack: WPSBackpackSystem = Architecture.Get(WPSBackpackSystem) - backpack.add_item(user_id, crop.fruit_id, base_qty) - config_api: WPSConfigAPI = Architecture.Get(WPSConfigAPI) - extra_lines = [] - if result["extra"]: - extra = result["extra"] - if extra["type"] == "points": - gained = int(extra["amount"]) - if gained > 0: - new_points = await config_api.adjust_user_points( - chat_id, - user_id, - gained, - reason=f"收获 {crop.display_name} 的额外积分", + + # 收集结果 + successful_harvests = [] + failed_harvests = [] + total_points_gained = 0 + extra_items = {} # {item_id: quantity} + fruit_counts = {} # {fruit_id: quantity} + + # 循环处理每个地块 + for plot_index in plot_indices: + try: + result = self.service().harvest( + user_id=user_id, + plot_index=plot_index, + fortune_value=fortune_value, + ) + crop = result["crop"] + base_qty = result["base_yield"] + + # 添加到背包 + backpack.add_item(user_id, crop.fruit_id, base_qty) + + # 统计果实 + fruit_counts[crop.fruit_id] = fruit_counts.get(crop.fruit_id, 0) + base_qty + + # 处理额外奖励 + if result["extra"]: + extra = result["extra"] + if extra["type"] == "points": + gained = int(extra["amount"]) + if gained > 0: + total_points_gained += gained + elif extra["type"] == "item": + item_id = extra["item_id"] + qty = int(extra["quantity"]) + if qty > 0: + extra_items[item_id] = extra_items.get(item_id, 0) + qty + backpack.add_item(user_id, item_id, qty) + + successful_harvests.append((plot_index, crop, result)) + except ValueError as exc: + failed_harvests.append((plot_index, str(exc))) + + # 统一处理积分奖励 + new_points = None + if total_points_gained > 0: + new_points = await config_api.adjust_user_points( + chat_id, + user_id, + total_points_gained, + reason=f"收获 {len(successful_harvests)} 个地块的额外积分", + ) + + # 生成汇总消息 + message_lines = [] + + if successful_harvests: + message_lines.append("# ✅ 收获成功") + message_lines.append(f"- 成功收获:{len(successful_harvests)} 个地块") + + # 列出成功的地块 + for plot_index, crop, result in successful_harvests: + message_lines.append(f" - 地块 {plot_index}:{crop.display_name} × {result['base_yield']}") + + # 汇总果实 + if fruit_counts: + message_lines.append("\n- 获得果实:") + for fruit_id, qty in fruit_counts.items(): + # 从成功收获中查找对应的作物显示名称 + crop_for_fruit = next( + (c for _, c, _ in successful_harvests if c.fruit_id == fruit_id), + None ) - extra_lines.append(f"- 额外积分:+{gained}(当前积分 {new_points})") - elif extra["type"] == "item": - item_id = extra["item_id"] - qty = int(extra["quantity"]) - if qty > 0: - backpack.add_item(user_id, item_id, qty) - extra_lines.append(f"- 额外物品:{item_id} × {qty}") - - message_lines = [ - "# ✅ 收获成功", - f"- 地块:{plot_index}", - f"- 作物:{crop.display_name}", - f"- 基础果实:{crop.display_name}的果实 × {base_qty}", - ] - message_lines.extend(extra_lines) + fruit_name = crop_for_fruit.display_name if crop_for_fruit else fruit_id + message_lines.append(f" - {fruit_name}的果实 × {qty}") + + # 额外奖励 + if total_points_gained > 0: + message_lines.append(f"\n- 额外积分:+{total_points_gained}(当前积分 {new_points})") + + if extra_items: + message_lines.append("\n- 额外物品:") + for item_id, qty in extra_items.items(): + message_lines.append(f" - {item_id} × {qty}") + + if failed_harvests: + if message_lines: + message_lines.append("\n---\n") + message_lines.append("# ❌ 收获失败") + for plot_index, error_msg in failed_harvests: + message_lines.append(f"- 地块 {plot_index}:{error_msg}") + + if not message_lines: + return await self.send_markdown_message("❌ 没有可收获的地块", chat_id, user_id) + return await self.send_markdown_message("\n".join(message_lines), chat_id, user_id)