refactor: 14个协议编译器去重精简,删除死代码

- 统一debug_print为共享import,移除14个本地定义
- 移除重复工具函数(find_connected_stirrer, get_vessel_liquid_volume等)
- 精简装饰性日志(emoji分隔线、进度提示),保留关键决策点
- 删除evacuateandrefill_protocol_old.py死代码
- 涉及文件:add, adjustph, clean_vessel, dissolve, dry, evacuateandrefill,
  evaporate, filter, pump, recrystallize, reset_handling, run_column,
  stir, wash_solid

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Junhan Chang
2026-03-25 13:12:10 +08:00
parent 5f36b6c04b
commit 0ab4027de7
15 changed files with 1018 additions and 3461 deletions

View File

@@ -4,199 +4,55 @@ import logging
import re
from .utils.unit_parser import parse_time_input, parse_volume_input
from .utils.resource_helper import get_resource_id, get_resource_display_info, get_resource_liquid_volume, update_vessel_volume
from .utils.logger_util import debug_print
logger = logging.getLogger(__name__)
def debug_print(message):
"""调试输出"""
logger.info(f"[WASH_SOLID] {message}")
def find_solvent_source(G: nx.DiGraph, solvent: str) -> str:
"""查找溶剂源(精简版)"""
debug_print(f"🔍 查找溶剂源: {solvent}")
# 简化搜索列表
"""查找溶剂源"""
search_patterns = [
f"flask_{solvent}", f"bottle_{solvent}", f"reagent_{solvent}",
"liquid_reagent_bottle_1", "flask_1", "solvent_bottle"
]
for pattern in search_patterns:
if pattern in G.nodes():
debug_print(f"🎉 找到溶剂源: {pattern}")
debug_print(f"找到溶剂源: {pattern}")
return pattern
debug_print(f"⚠️ 使用默认溶剂源: flask_{solvent}")
debug_print(f"使用默认溶剂源: flask_{solvent}")
return f"flask_{solvent}"
def find_filtrate_vessel(G: nx.DiGraph, filtrate_vessel: str = "") -> str:
"""查找滤液容器(精简版)"""
debug_print(f"🔍 查找滤液容器: {filtrate_vessel}")
# 如果指定了且存在,直接使用
"""查找滤液容器"""
if filtrate_vessel and filtrate_vessel in G.nodes():
debug_print(f"✅ 使用指定容器: {filtrate_vessel}")
return filtrate_vessel
# 简化搜索列表
default_vessels = ["waste_workup", "filtrate_vessel", "flask_1", "collection_bottle_1"]
for vessel in default_vessels:
if vessel in G.nodes():
debug_print(f"🎉 找到滤液容器: {vessel}")
debug_print(f"找到滤液容器: {vessel}")
return vessel
debug_print(f"⚠️ 使用默认滤液容器: waste_workup")
return "waste_workup"
def extract_vessel_id(vessel: Union[str, dict]) -> str:
"""
从vessel参数中提取vessel_id
Args:
vessel: vessel字典或vessel_id字符串
Returns:
str: vessel_id
"""
if isinstance(vessel, dict):
vessel_id = list(vessel.values())[0].get("id", "")
debug_print(f"🔧 从vessel字典提取ID: {vessel_id}")
return vessel_id
elif isinstance(vessel, str):
debug_print(f"🔧 vessel参数为字符串: {vessel}")
return vessel
else:
debug_print(f"⚠️ 无效的vessel参数类型: {type(vessel)}")
return ""
def extract_vessel_id(vessel) -> str:
"""从vessel参数中提取vessel_id兼容 str / dict / ResourceDictInstance"""
return get_resource_id(vessel)
def get_vessel_display_info(vessel: Union[str, dict]) -> str:
"""
获取容器的显示信息(用于日志)
Args:
vessel: vessel字典或vessel_id字符串
Returns:
str: 显示信息
"""
if isinstance(vessel, dict):
vessel_id = vessel.get("id", "unknown")
vessel_name = vessel.get("name", "")
if vessel_name:
return f"{vessel_id} ({vessel_name})"
else:
return vessel_id
else:
return str(vessel)
def get_vessel_liquid_volume(vessel: dict) -> float:
"""
获取容器中的液体体积 - 支持vessel字典
Args:
vessel: 容器字典
Returns:
float: 液体体积mL
"""
if not vessel or "data" not in vessel:
debug_print(f"⚠️ 容器数据为空,返回 0.0mL")
return 0.0
vessel_data = vessel["data"]
vessel_id = vessel.get("id", "unknown")
debug_print(f"🔍 读取容器 '{vessel_id}' 体积数据: {vessel_data}")
# 检查liquid_volume字段
if "liquid_volume" in vessel_data:
liquid_volume = vessel_data["liquid_volume"]
# 处理列表格式
if isinstance(liquid_volume, list):
if len(liquid_volume) > 0:
volume = liquid_volume[0]
if isinstance(volume, (int, float)):
debug_print(f"✅ 容器 '{vessel_id}' 体积: {volume}mL (列表格式)")
return float(volume)
# 处理直接数值格式
elif isinstance(liquid_volume, (int, float)):
debug_print(f"✅ 容器 '{vessel_id}' 体积: {liquid_volume}mL (数值格式)")
return float(liquid_volume)
# 检查其他可能的体积字段
volume_keys = ['current_volume', 'total_volume', 'volume']
for key in volume_keys:
if key in vessel_data:
try:
volume = float(vessel_data[key])
if volume > 0:
debug_print(f"✅ 容器 '{vessel_id}' 体积: {volume}mL (字段: {key})")
return volume
except (ValueError, TypeError):
continue
debug_print(f"⚠️ 无法获取容器 '{vessel_id}' 的体积,返回默认值 0.0mL")
return 0.0
def update_vessel_volume(vessel: dict, G: nx.DiGraph, new_volume: float, description: str = "") -> None:
"""
更新容器体积同时更新vessel字典和图节点
Args:
vessel: 容器字典
G: 网络图
new_volume: 新体积
description: 更新描述
"""
vessel_id = vessel.get("id", "unknown")
if description:
debug_print(f"🔧 更新容器体积 - {description}")
# 更新vessel字典中的体积
if "data" in vessel:
if "liquid_volume" in vessel["data"]:
current_volume = vessel["data"]["liquid_volume"]
if isinstance(current_volume, list):
if len(current_volume) > 0:
vessel["data"]["liquid_volume"][0] = new_volume
else:
vessel["data"]["liquid_volume"] = [new_volume]
else:
vessel["data"]["liquid_volume"] = new_volume
else:
vessel["data"]["liquid_volume"] = new_volume
else:
vessel["data"] = {"liquid_volume": new_volume}
# 同时更新图中的容器数据
if vessel_id in G.nodes():
if 'data' not in G.nodes[vessel_id]:
G.nodes[vessel_id]['data'] = {}
vessel_node_data = G.nodes[vessel_id]['data']
current_node_volume = vessel_node_data.get('liquid_volume', 0.0)
if isinstance(current_node_volume, list):
if len(current_node_volume) > 0:
G.nodes[vessel_id]['data']['liquid_volume'][0] = new_volume
else:
G.nodes[vessel_id]['data']['liquid_volume'] = [new_volume]
else:
G.nodes[vessel_id]['data']['liquid_volume'] = new_volume
debug_print(f"📊 容器 '{vessel_id}' 体积已更新为: {new_volume:.2f}mL")
def get_vessel_display_info(vessel) -> str:
"""获取容器的显示信息(用于日志),兼容 str / dict / ResourceDictInstance"""
return get_resource_display_info(vessel)
def generate_wash_solid_protocol(
G: nx.DiGraph,
vessel: Union[str, dict], # 🔧 修改支持vessel字典
vessel: Union[str, dict],
solvent: str,
volume: Union[float, str] = "50",
filtrate_vessel: Union[str, dict] = "", # 🔧 修改支持vessel字典
filtrate_vessel: Union[str, dict] = "",
temp: float = 25.0,
stir: bool = False,
stir_speed: float = 0.0,
@@ -210,7 +66,7 @@ def generate_wash_solid_protocol(
) -> List[Dict[str, Any]]:
"""
生成固体清洗协议 - 支持vessel字典和体积运算
Args:
G: 有向图,节点为设备和容器,边为流体管道
vessel: 清洗容器字典从XDL传入或容器ID字符串
@@ -227,106 +83,78 @@ def generate_wash_solid_protocol(
mass: 固体质量(用于计算溶剂用量)
event: 事件描述
**kwargs: 其他可选参数
Returns:
List[Dict[str, Any]]: 固体清洗操作的动作序列
"""
# 🔧 核心修改从vessel参数中提取vessel_id
vessel_id = extract_vessel_id(vessel)
vessel_display = get_vessel_display_info(vessel)
# 🔧 处理filtrate_vessel参数
filtrate_vessel_id = extract_vessel_id(filtrate_vessel) if filtrate_vessel else ""
debug_print("🧼" * 20)
debug_print("🚀 开始生成固体清洗协议支持vessel字典和体积运算")
debug_print(f"📝 输入参数:")
debug_print(f" 🥽 vessel: {vessel_display} (ID: {vessel_id})")
debug_print(f" 🧪 solvent: {solvent}")
debug_print(f" 💧 volume: {volume}")
debug_print(f" 🗑️ filtrate_vessel: {filtrate_vessel_id}")
debug_print(f" ⏰ time: {time}")
debug_print(f" 🔄 repeats: {repeats}")
debug_print("🧼" * 20)
# 🔧 新增:记录清洗前的容器状态
debug_print("🔍 记录清洗前容器状态...")
debug_print(f"开始生成固体清洗协议: vessel={vessel_id}, solvent={solvent}, volume={volume}, repeats={repeats}")
# 记录清洗前的容器状态
if isinstance(vessel, dict):
original_volume = get_vessel_liquid_volume(vessel)
debug_print(f"📊 清洗前液体体积: {original_volume:.2f}mL")
original_volume = get_resource_liquid_volume(vessel)
else:
original_volume = 0.0
debug_print(f"📊 vessel为字符串格式无法获取体积信息")
# 📋 快速验证
if not vessel_id or vessel_id not in G.nodes(): # 🔧 使用 vessel_id
debug_print("❌ 容器验证失败! 😱")
# 快速验证
if not vessel_id or vessel_id not in G.nodes():
raise ValueError("vessel 参数无效")
if not solvent:
debug_print("❌ 溶剂不能为空! 😱")
raise ValueError("solvent 参数不能为空")
debug_print("✅ 基础验证通过 🎯")
# 🔄 参数解析
debug_print("📍 步骤1: 参数解析... ⚡")
# 参数解析
final_volume = parse_volume_input(volume, volume_spec, mass)
final_time = parse_time_input(time)
# 重复次数处理(简化)
# 重复次数处理
if repeats_spec:
spec_map = {'few': 2, 'several': 3, 'many': 4, 'thorough': 5}
final_repeats = next((v for k, v in spec_map.items() if k in repeats_spec.lower()), repeats)
else:
final_repeats = max(1, min(repeats, 5)) # 限制1-5次
# 🕐 模拟时间优化
debug_print(" ⏱️ 模拟时间优化...")
final_repeats = max(1, min(repeats, 5))
# 模拟时间优化
original_time = final_time
if final_time > 60.0:
final_time = 60.0 # 限制最长60秒
debug_print(f" 🎮 时间优化: {original_time}s {final_time}s")
final_time = 60.0
debug_print(f"时间优化: {original_time}s -> {final_time}s")
# 参数修正
temp = max(25.0, min(temp, 80.0)) # 温度范围25-80°C
stir_speed = max(0.0, min(stir_speed, 300.0)) if stir else 0.0 # 速度范围0-300
debug_print(f"🎯 最终参数: 体积={final_volume}mL, 时间={final_time}s, 重复={final_repeats}")
# 🔍 查找设备
debug_print("📍 步骤2: 查找设备... 🔍")
temp = max(25.0, min(temp, 80.0))
stir_speed = max(0.0, min(stir_speed, 300.0)) if stir else 0.0
debug_print(f"最终参数: 体积={final_volume}mL, 时间={final_time}s, 重复={final_repeats}")
# 查找设备
try:
solvent_source = find_solvent_source(G, solvent)
actual_filtrate_vessel = find_filtrate_vessel(G, filtrate_vessel_id)
debug_print(f"🎉 设备配置完成 ✨")
debug_print(f" 🧪 溶剂源: {solvent_source}")
debug_print(f" 🗑️ 滤液容器: {actual_filtrate_vessel}")
except Exception as e:
debug_print(f"❌ 设备查找失败: {str(e)} 😭")
raise ValueError(f"设备查找失败: {str(e)}")
# 🚀 生成动作序列
debug_print("📍 步骤3: 生成清洗动作... 🧼")
# 生成动作序列
action_sequence = []
# 🔧 新增:体积变化跟踪变量
current_volume = original_volume
total_solvent_used = 0.0
for cycle in range(final_repeats):
debug_print(f" 🔄 {cycle+1}/{final_repeats}次清洗...")
debug_print(f"{cycle+1}/{final_repeats}次清洗")
# 1. 转移溶剂
try:
from .pump_protocol import generate_pump_protocol_with_rinsing
debug_print(f" 💧 添加溶剂: {final_volume}mL {solvent}")
transfer_actions = generate_pump_protocol_with_rinsing(
G=G,
from_vessel=solvent_source,
to_vessel=vessel_id, # 🔧 使用 vessel_id
to_vessel=vessel_id,
volume=final_volume,
amount="",
time=0.0,
@@ -338,211 +166,160 @@ def generate_wash_solid_protocol(
flowrate=2.5,
transfer_flowrate=0.5
)
if transfer_actions:
action_sequence.extend(transfer_actions)
debug_print(f" ✅ 转移动作: {len(transfer_actions)}个 🚚")
# 🔧 新增:更新体积 - 添加溶剂后
current_volume += final_volume
total_solvent_used += final_volume
if isinstance(vessel, dict):
update_vessel_volume(vessel, G, current_volume,
update_vessel_volume(vessel, G, current_volume,
f"{cycle+1}次清洗添加{final_volume}mL溶剂后")
except Exception as e:
debug_print(f"转移失败: {str(e)} 😞")
debug_print(f"转移失败: {str(e)}")
# 2. 搅拌(如果需要)
if stir and final_time > 0:
debug_print(f" 🌪️ 搅拌: {final_time}s @ {stir_speed}RPM")
stir_action = {
"device_id": "stirrer_1",
"action_name": "stir",
"action_kwargs": {
"vessel": {"id": vessel_id}, # 🔧 使用 vessel_id
"vessel": {"id": vessel_id},
"time": str(time),
"stir_time": final_time,
"stir_speed": stir_speed,
"settling_time": 10.0 # 🕐 缩短沉降时间
"settling_time": 10.0
}
}
action_sequence.append(stir_action)
debug_print(f" ✅ 搅拌动作: {final_time}s, {stir_speed}RPM 🌪️")
# 3. 过滤
debug_print(f" 🌊 过滤到: {actual_filtrate_vessel}")
filter_action = {
"device_id": "filter_1",
"action_name": "filter",
"action_kwargs": {
"vessel": {"id": vessel_id}, # 🔧 使用 vessel_id
"vessel": {"id": vessel_id},
"filtrate_vessel": actual_filtrate_vessel,
"temp": temp,
"volume": final_volume
}
}
action_sequence.append(filter_action)
debug_print(f" ✅ 过滤动作: → {actual_filtrate_vessel} 🌊")
# 🔧 新增:更新体积 - 过滤后(液体被滤除)
# 假设滤液完全被移除,固体残留在容器中
filtered_volume = current_volume * 0.9 # 假设90%的液体被过滤掉
# 更新体积 - 过滤后
filtered_volume = current_volume * 0.9
current_volume = current_volume - filtered_volume
if isinstance(vessel, dict):
update_vessel_volume(vessel, G, current_volume,
update_vessel_volume(vessel, G, current_volume,
f"{cycle+1}次清洗过滤后")
# 4. 等待(缩短时间)
wait_time = 5.0 # 🕐 缩短等待时间10s → 5s
# 4. 等待
wait_time = 5.0
action_sequence.append({
"action_name": "wait",
"action_kwargs": {"time": wait_time}
})
debug_print(f" ✅ 等待: {wait_time}s ⏰")
# 🔧 新增:清洗完成后的最终状态报告
# 最终状态
if isinstance(vessel, dict):
final_volume_vessel = get_vessel_liquid_volume(vessel)
final_volume_vessel = get_resource_liquid_volume(vessel)
else:
final_volume_vessel = current_volume
# 🎊 总结
debug_print("🧼" * 20)
debug_print(f"🎉 固体清洗协议生成完成! ✨")
debug_print(f"📊 协议统计:")
debug_print(f" 📋 总动作数: {len(action_sequence)}")
debug_print(f" 🥽 清洗容器: {vessel_display}")
debug_print(f" 🧪 使用溶剂: {solvent}")
debug_print(f" 💧 单次体积: {final_volume}mL")
debug_print(f" 🔄 清洗次数: {final_repeats}")
debug_print(f" 💧 总溶剂用量: {total_solvent_used:.2f}mL")
debug_print(f"📊 体积变化统计:")
debug_print(f" - 清洗前体积: {original_volume:.2f}mL")
debug_print(f" - 清洗后体积: {final_volume_vessel:.2f}mL")
debug_print(f" - 溶剂总用量: {total_solvent_used:.2f}mL")
debug_print(f"⏱️ 预计总时间: {(final_time + 5) * final_repeats / 60:.1f} 分钟")
debug_print("🧼" * 20)
debug_print(f"固体清洗协议生成完成: {len(action_sequence)} 个动作, {final_repeats}次清洗, 溶剂总用量={total_solvent_used:.2f}mL")
return action_sequence
# 🔧 新增:便捷函数
def wash_with_water(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "50",
# 便捷函数
def wash_with_water(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "50",
repeats: int = 2) -> List[Dict[str, Any]]:
"""用水清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"💧 水洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, "water", volume=volume, repeats=repeats)
def wash_with_ethanol(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "30",
def wash_with_ethanol(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "30",
repeats: int = 1) -> List[Dict[str, Any]]:
"""用乙醇清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"🍺 乙醇洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, "ethanol", volume=volume, repeats=repeats)
def wash_with_acetone(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "25",
def wash_with_acetone(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "25",
repeats: int = 1) -> List[Dict[str, Any]]:
"""用丙酮清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"💨 丙酮洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, "acetone", volume=volume, repeats=repeats)
def wash_with_ether(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "40",
def wash_with_ether(G: nx.DiGraph, vessel: Union[str, dict],
volume: Union[float, str] = "40",
repeats: int = 2) -> List[Dict[str, Any]]:
"""用乙醚清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"🌬️ 乙醚洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, "diethyl_ether", volume=volume, repeats=repeats)
def wash_with_cold_solvent(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "30",
def wash_with_cold_solvent(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "30",
repeats: int = 1) -> List[Dict[str, Any]]:
"""用冷溶剂清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"❄️ 冷{solvent}洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
temp=5.0, repeats=repeats)
def wash_with_hot_solvent(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "50",
def wash_with_hot_solvent(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "50",
repeats: int = 1) -> List[Dict[str, Any]]:
"""用热溶剂清洗固体"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"🔥 热{solvent}洗固体: {vessel_display} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
temp=60.0, repeats=repeats)
def wash_with_stirring(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "50",
stir_time: Union[str, float] = "5 min",
def wash_with_stirring(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "50",
stir_time: Union[str, float] = "5 min",
repeats: int = 1) -> List[Dict[str, Any]]:
"""带搅拌的溶剂清洗"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"🌪️ 搅拌清洗: {vessel_display} with {solvent} ({repeats} 次)")
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
stir=True, stir_speed=200.0,
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
stir=True, stir_speed=200.0,
time=stir_time, repeats=repeats)
def thorough_wash(G: nx.DiGraph, vessel: Union[str, dict],
def thorough_wash(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "50") -> List[Dict[str, Any]]:
"""彻底清洗(多次重复)"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"🔄 彻底清洗: {vessel_display} with {solvent} (5 次)")
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume, repeats=5)
def quick_rinse(G: nx.DiGraph, vessel: Union[str, dict],
def quick_rinse(G: nx.DiGraph, vessel: Union[str, dict],
solvent: str, volume: Union[float, str] = "20") -> List[Dict[str, Any]]:
"""快速冲洗(单次,小体积)"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"⚡ 快速冲洗: {vessel_display} with {solvent}")
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume, repeats=1)
def sequential_wash(G: nx.DiGraph, vessel: Union[str, dict],
def sequential_wash(G: nx.DiGraph, vessel: Union[str, dict],
solvents: list, volume: Union[float, str] = "40") -> List[Dict[str, Any]]:
"""连续多溶剂清洗"""
vessel_display = get_vessel_display_info(vessel)
debug_print(f"📝 连续清洗: {vessel_display} with {''.join(solvents)}")
action_sequence = []
for solvent in solvents:
wash_actions = generate_wash_solid_protocol(G, vessel, solvent,
wash_actions = generate_wash_solid_protocol(G, vessel, solvent,
volume=volume, repeats=1)
action_sequence.extend(wash_actions)
return action_sequence
# 测试函数
def test_wash_solid_protocol():
"""测试固体清洗协议"""
debug_print("🧪 === WASH SOLID PROTOCOL 测试 ===")
# 测试vessel参数处理
debug_print("🔧 测试vessel参数处理...")
# 测试字典格式
vessel_dict = {"id": "filter_flask_1", "name": "过滤瓶1",
debug_print("=== WASH SOLID PROTOCOL 测试 ===")
vessel_dict = {"id": "filter_flask_1", "name": "过滤瓶1",
"data": {"liquid_volume": 25.0}}
vessel_id = extract_vessel_id(vessel_dict)
vessel_display = get_vessel_display_info(vessel_dict)
volume = get_vessel_liquid_volume(vessel_dict)
debug_print(f" 字典格式: {vessel_dict}")
debug_print(f" → ID: {vessel_id}, 显示: {vessel_display}, 体积: {volume}mL")
# 测试字符串格式
volume = get_resource_liquid_volume(vessel_dict)
debug_print(f"字典格式: ID={vessel_id}, 显示={vessel_display}, 体积={volume}mL")
vessel_str = "filter_flask_2"
vessel_id = extract_vessel_id(vessel_str)
vessel_display = get_vessel_display_info(vessel_str)
debug_print(f" 字符串格式: {vessel_str}")
debug_print(f" → ID: {vessel_id}, 显示: {vessel_display}")
debug_print("✅ 测试完成 🎉")
debug_print(f"字符串格式: ID={vessel_id}, 显示={vessel_display}")
debug_print("测试完成")
if __name__ == "__main__":
test_wash_solid_protocol()
test_wash_solid_protocol()