882 lines
28 KiB
Python
882 lines
28 KiB
Python
"""
|
|
工具类模块
|
|
提供语音控制插件所需的实用工具函数
|
|
"""
|
|
|
|
import time
|
|
import math
|
|
import os
|
|
import json
|
|
import threading
|
|
from typing import Dict, Any, List, Optional, Union
|
|
import hashlib
|
|
|
|
class VoiceUtils:
|
|
"""
|
|
语音工具类
|
|
提供语音控制插件所需的实用工具函数
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化语音工具类
|
|
|
|
Args:
|
|
plugin: 语音控制插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 性能监控
|
|
self.performance_metrics = {
|
|
"update_times": [],
|
|
"processing_times": [],
|
|
"memory_usage": 0,
|
|
"cpu_usage": 0
|
|
}
|
|
|
|
# 日志配置
|
|
self.log_config = {
|
|
"enable_logging": True,
|
|
"log_level": "INFO",
|
|
"log_file": "/home/hello/EG/plugins/user/voice_control/logs/voice.log",
|
|
"max_log_size": 10 * 1024 * 1024, # 10MB
|
|
"log_format": "[{timestamp}] {level}: {message}"
|
|
}
|
|
|
|
# 数据转换配置
|
|
self.conversion_config = {
|
|
"audio_level_curve": "linear", # linear, exponential, logarithmic
|
|
"confidence_mapping": "linear",
|
|
"duration_scaling": "linear"
|
|
}
|
|
|
|
# 数学工具
|
|
self.math_utils = MathUtils()
|
|
|
|
# 缓存管理
|
|
self.cache_manager = CacheManager()
|
|
|
|
# 调试工具
|
|
self.debug_tools = DebugTools()
|
|
|
|
# 文件管理
|
|
self.file_manager = FileManager()
|
|
|
|
# 统计信息
|
|
self.stats = {
|
|
"functions_called": 0,
|
|
"data_processed": 0,
|
|
"cache_hits": 0,
|
|
"cache_misses": 0,
|
|
"files_processed": 0
|
|
}
|
|
|
|
# 线程锁
|
|
self.utils_lock = threading.RLock()
|
|
|
|
print("✓ 语音工具类已创建")
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化语音工具类
|
|
|
|
Returns:
|
|
是否初始化成功
|
|
"""
|
|
try:
|
|
# 创建日志目录
|
|
log_dir = "/home/hello/EG/plugins/user/voice_control/logs"
|
|
if not os.path.exists(log_dir):
|
|
os.makedirs(log_dir)
|
|
|
|
# 初始化子工具
|
|
self.math_utils.initialize()
|
|
self.cache_manager.initialize()
|
|
self.debug_tools.initialize()
|
|
self.file_manager.initialize()
|
|
|
|
self.initialized = True
|
|
print("✓ 语音工具类初始化完成")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音工具类初始化失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def enable(self) -> bool:
|
|
"""
|
|
启用语音工具类
|
|
|
|
Returns:
|
|
是否启用成功
|
|
"""
|
|
try:
|
|
if not self.initialized:
|
|
print("✗ 语音工具类未初始化")
|
|
return False
|
|
|
|
self.enabled = True
|
|
|
|
# 启用子工具
|
|
self.math_utils.enable()
|
|
self.cache_manager.enable()
|
|
self.debug_tools.enable()
|
|
self.file_manager.enable()
|
|
|
|
print("✓ 语音工具类已启用")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音工具类启用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def disable(self):
|
|
"""禁用语音工具类"""
|
|
try:
|
|
self.enabled = False
|
|
|
|
# 禁用子工具
|
|
self.math_utils.disable()
|
|
self.cache_manager.disable()
|
|
self.debug_tools.disable()
|
|
self.file_manager.disable()
|
|
|
|
print("✓ 语音工具类已禁用")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音工具类禁用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def finalize(self):
|
|
"""清理语音工具类资源"""
|
|
try:
|
|
self.disable()
|
|
self.performance_metrics.clear()
|
|
self.cache_manager.clear()
|
|
self.debug_tools.clear()
|
|
self.file_manager.clear()
|
|
self.initialized = False
|
|
print("✓ 语音工具类资源已清理")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音工具类资源清理失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def update(self, dt: float):
|
|
"""
|
|
更新语音工具类状态
|
|
|
|
Args:
|
|
dt: 时间增量
|
|
"""
|
|
try:
|
|
if not self.enabled:
|
|
return
|
|
|
|
# 更新性能指标
|
|
self._update_performance_metrics(dt)
|
|
|
|
# 更新子工具
|
|
self.cache_manager.update(dt)
|
|
self.debug_tools.update(dt)
|
|
self.file_manager.update(dt)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音工具类更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _update_performance_metrics(self, dt: float):
|
|
"""更新性能指标"""
|
|
try:
|
|
# 记录更新时间
|
|
self.performance_metrics["update_times"].append(dt)
|
|
|
|
# 保持历史记录大小
|
|
if len(self.performance_metrics["update_times"]) > 1000:
|
|
self.performance_metrics["update_times"] = self.performance_metrics["update_times"][-1000:]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 性能指标更新失败: {e}")
|
|
|
|
def log_message(self, message: str, level: str = "INFO"):
|
|
"""
|
|
记录日志消息
|
|
|
|
Args:
|
|
message: 日志消息
|
|
level: 日志级别 (DEBUG, INFO, WARNING, ERROR)
|
|
"""
|
|
try:
|
|
if not self.log_config["enable_logging"]:
|
|
return
|
|
|
|
# 检查日志级别
|
|
level_priority = {"DEBUG": 0, "INFO": 1, "WARNING": 2, "ERROR": 3}
|
|
config_level = self.log_config["log_level"]
|
|
|
|
if level_priority.get(level, 1) < level_priority.get(config_level, 1):
|
|
return
|
|
|
|
# 格式化日志消息
|
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
formatted_message = self.log_config["log_format"].format(
|
|
timestamp=timestamp,
|
|
level=level,
|
|
message=message
|
|
)
|
|
|
|
# 输出到控制台
|
|
print(formatted_message)
|
|
|
|
# 写入日志文件
|
|
try:
|
|
with self.utils_lock:
|
|
# 检查文件大小
|
|
if os.path.exists(self.log_config["log_file"]):
|
|
if os.path.getsize(self.log_config["log_file"]) > self.log_config["max_log_size"]:
|
|
# 重命名旧日志文件
|
|
backup_file = self.log_config["log_file"] + ".old"
|
|
if os.path.exists(backup_file):
|
|
os.remove(backup_file)
|
|
os.rename(self.log_config["log_file"], backup_file)
|
|
|
|
with open(self.log_config["log_file"], "a", encoding="utf-8") as f:
|
|
f.write(formatted_message + "\n")
|
|
except Exception as e:
|
|
pass # 忽略文件写入错误
|
|
|
|
except Exception as e:
|
|
pass # 忽略日志记录错误
|
|
|
|
def measure_performance(self, func: callable, *args, **kwargs) -> tuple:
|
|
"""
|
|
测量函数性能
|
|
|
|
Args:
|
|
func: 要测量的函数
|
|
*args: 函数参数
|
|
**kwargs: 函数关键字参数
|
|
|
|
Returns:
|
|
(结果, 执行时间)
|
|
"""
|
|
try:
|
|
start_time = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
end_time = time.perf_counter()
|
|
|
|
execution_time = end_time - start_time
|
|
|
|
# 记录到性能指标
|
|
metric_name = f"{func.__name__}_times"
|
|
if metric_name not in self.performance_metrics:
|
|
self.performance_metrics[metric_name] = []
|
|
|
|
self.performance_metrics[metric_name].append(execution_time)
|
|
|
|
# 保持历史记录大小
|
|
if len(self.performance_metrics[metric_name]) > 1000:
|
|
self.performance_metrics[metric_name] = self.performance_metrics[metric_name][-1000:]
|
|
|
|
self.stats["functions_called"] += 1
|
|
return (result, execution_time)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"性能测量失败: {e}", "ERROR")
|
|
raise
|
|
|
|
def convert_audio_level(self, level: float, curve: str = None) -> float:
|
|
"""
|
|
转换音频级别值
|
|
|
|
Args:
|
|
level: 原始级别值 (0.0-1.0)
|
|
curve: 转换曲线类型
|
|
|
|
Returns:
|
|
转换后的级别值
|
|
"""
|
|
try:
|
|
curve_type = curve or self.conversion_config["audio_level_curve"]
|
|
level = max(0.0, min(1.0, level))
|
|
|
|
if curve_type == "exponential":
|
|
# 指数曲线
|
|
return math.pow(level, 2)
|
|
elif curve_type == "logarithmic":
|
|
# 对数曲线
|
|
return math.log(level + 1) / math.log(2)
|
|
else:
|
|
# 线性曲线
|
|
return level
|
|
|
|
except Exception as e:
|
|
self.log_message(f"音频级别转换失败: {e}", "ERROR")
|
|
return level
|
|
|
|
def convert_confidence(self, confidence: float, mapping: str = None) -> float:
|
|
"""
|
|
转换置信度值
|
|
|
|
Args:
|
|
confidence: 原始置信度值 (0.0-1.0)
|
|
mapping: 映射类型
|
|
|
|
Returns:
|
|
转换后的置信度值
|
|
"""
|
|
try:
|
|
mapping_type = mapping or self.conversion_config["confidence_mapping"]
|
|
confidence = max(0.0, min(1.0, confidence))
|
|
|
|
if mapping_type == "exponential":
|
|
# 指数映射
|
|
return math.pow(confidence, 2)
|
|
elif mapping_type == "logarithmic":
|
|
# 对数映射
|
|
return math.log(confidence * 9 + 1) / math.log(10)
|
|
else:
|
|
# 线性映射
|
|
return confidence
|
|
|
|
except Exception as e:
|
|
self.log_message(f"置信度转换失败: {e}", "ERROR")
|
|
return confidence
|
|
|
|
def scale_duration(self, duration: float, scale_factor: float = 1.0,
|
|
scaling_type: str = None) -> float:
|
|
"""
|
|
缩放持续时间
|
|
|
|
Args:
|
|
duration: 原始持续时间
|
|
scale_factor: 缩放因子
|
|
scaling_type: 缩放类型
|
|
|
|
Returns:
|
|
缩放后的持续时间
|
|
"""
|
|
try:
|
|
scaling = scaling_type or self.conversion_config["duration_scaling"]
|
|
duration = max(0.0, duration)
|
|
scale_factor = max(0.0, scale_factor)
|
|
|
|
if scaling == "exponential":
|
|
return duration * math.pow(scale_factor, 2)
|
|
elif scaling == "logarithmic":
|
|
return duration * math.log(scale_factor + 1)
|
|
else:
|
|
return duration * scale_factor
|
|
|
|
except Exception as e:
|
|
self.log_message(f"持续时间缩放失败: {e}", "ERROR")
|
|
return duration
|
|
|
|
def interpolate_values(self, start_value: float, end_value: float,
|
|
progress: float, interpolation_type: str = "linear") -> float:
|
|
"""
|
|
插值计算
|
|
|
|
Args:
|
|
start_value: 起始值
|
|
end_value: 结束值
|
|
progress: 进度 (0.0-1.0)
|
|
interpolation_type: 插值类型
|
|
|
|
Returns:
|
|
插值结果
|
|
"""
|
|
try:
|
|
progress = max(0.0, min(1.0, progress))
|
|
|
|
if interpolation_type == "ease_in":
|
|
progress = math.pow(progress, 2)
|
|
elif interpolation_type == "ease_out":
|
|
progress = 1.0 - math.pow(1.0 - progress, 2)
|
|
elif interpolation_type == "ease_in_out":
|
|
progress = 0.5 * (1 - math.cos(progress * math.pi))
|
|
# linear 为默认情况,无需特殊处理
|
|
|
|
return start_value + (end_value - start_value) * progress
|
|
|
|
except Exception as e:
|
|
self.log_message(f"插值计算失败: {e}", "ERROR")
|
|
return start_value
|
|
|
|
def calculate_similarity(self, text1: str, text2: str) -> float:
|
|
"""
|
|
计算文本相似度
|
|
|
|
Args:
|
|
text1: 文本1
|
|
text2: 文本2
|
|
|
|
Returns:
|
|
相似度值 (0.0-1.0)
|
|
"""
|
|
try:
|
|
# 使用简单的字符级相似度计算
|
|
set1 = set(text1)
|
|
set2 = set(text2)
|
|
|
|
intersection = len(set1.intersection(set2))
|
|
union = len(set1.union(set2))
|
|
|
|
if union == 0:
|
|
return 1.0 if text1 == text2 else 0.0
|
|
|
|
return intersection / union
|
|
|
|
except Exception as e:
|
|
self.log_message(f"相似度计算失败: {e}", "ERROR")
|
|
return 0.0
|
|
|
|
def normalize_text(self, text: str, language: str = "zh-CN") -> str:
|
|
"""
|
|
标准化文本
|
|
|
|
Args:
|
|
text: 原始文本
|
|
language: 语言代码
|
|
|
|
Returns:
|
|
标准化后的文本
|
|
"""
|
|
try:
|
|
# 移除多余空格
|
|
text = " ".join(text.split())
|
|
|
|
# 转换为小写(仅适用于英文)
|
|
if language == "en-US":
|
|
text = text.lower()
|
|
|
|
# 移除特殊字符(保留字母、数字和基本标点)
|
|
import re
|
|
if language == "zh-CN":
|
|
text = re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\s\.,!?;:]", "", text)
|
|
else:
|
|
text = re.sub(r"[^a-zA-Z0-9\s\.,!?;:]", "", text)
|
|
|
|
return text.strip()
|
|
|
|
except Exception as e:
|
|
self.log_message(f"文本标准化失败: {e}", "ERROR")
|
|
return text
|
|
|
|
def generate_hash(self, data: Union[str, bytes]) -> str:
|
|
"""
|
|
生成数据哈希值
|
|
|
|
Args:
|
|
data: 要哈希的数据
|
|
|
|
Returns:
|
|
哈希值字符串
|
|
"""
|
|
try:
|
|
if isinstance(data, str):
|
|
data = data.encode("utf-8")
|
|
|
|
return hashlib.md5(data).hexdigest()
|
|
|
|
except Exception as e:
|
|
self.log_message(f"哈希生成失败: {e}", "ERROR")
|
|
return ""
|
|
|
|
def format_time(self, seconds: float) -> str:
|
|
"""
|
|
格式化时间显示
|
|
|
|
Args:
|
|
seconds: 秒数
|
|
|
|
Returns:
|
|
格式化的时间字符串
|
|
"""
|
|
try:
|
|
if seconds < 60:
|
|
return f"{seconds:.1f}秒"
|
|
elif seconds < 3600:
|
|
minutes = int(seconds // 60)
|
|
secs = seconds % 60
|
|
return f"{minutes}分{secs:.1f}秒"
|
|
else:
|
|
hours = int(seconds // 3600)
|
|
minutes = int((seconds % 3600) // 60)
|
|
secs = seconds % 60
|
|
return f"{hours}时{minutes}分{secs:.1f}秒"
|
|
|
|
except Exception as e:
|
|
self.log_message(f"时间格式化失败: {e}", "ERROR")
|
|
return f"{seconds:.1f}秒"
|
|
|
|
def get_performance_stats(self) -> Dict[str, Any]:
|
|
"""
|
|
获取性能统计信息
|
|
|
|
Returns:
|
|
性能统计字典
|
|
"""
|
|
try:
|
|
stats = {}
|
|
for key, times in self.performance_metrics.items():
|
|
if times:
|
|
stats[key] = {
|
|
"count": len(times),
|
|
"average": sum(times) / len(times),
|
|
"min": min(times),
|
|
"max": max(times),
|
|
"total": sum(times)
|
|
}
|
|
return stats
|
|
except Exception as e:
|
|
self.log_message(f"性能统计获取失败: {e}", "ERROR")
|
|
return {}
|
|
|
|
def get_system_info(self) -> Dict[str, Any]:
|
|
"""
|
|
获取系统信息
|
|
|
|
Returns:
|
|
系统信息字典
|
|
"""
|
|
try:
|
|
import platform
|
|
import psutil
|
|
|
|
return {
|
|
"platform": platform.system(),
|
|
"platform_version": platform.version(),
|
|
"processor": platform.processor(),
|
|
"cpu_count": psutil.cpu_count(),
|
|
"memory_total": psutil.virtual_memory().total,
|
|
"memory_available": psutil.virtual_memory().available,
|
|
"plugin_version": getattr(self.plugin, "version", "unknown")
|
|
}
|
|
except Exception as e:
|
|
self.log_message(f"系统信息获取失败: {e}", "ERROR")
|
|
return {}
|
|
|
|
def get_stats(self) -> Dict[str, int]:
|
|
"""
|
|
获取统计信息
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
return self.stats.copy()
|
|
|
|
def reset_stats(self):
|
|
"""重置统计信息"""
|
|
try:
|
|
self.stats = {
|
|
"functions_called": 0,
|
|
"data_processed": 0,
|
|
"cache_hits": 0,
|
|
"cache_misses": 0,
|
|
"files_processed": 0
|
|
}
|
|
print("✓ 工具类统计信息已重置")
|
|
except Exception as e:
|
|
self.log_message(f"统计信息重置失败: {e}", "ERROR")
|
|
|
|
def set_log_config(self, config: Dict[str, Any]) -> bool:
|
|
"""
|
|
设置日志配置
|
|
|
|
Args:
|
|
config: 日志配置字典
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.log_config.update(config)
|
|
self.log_message(f"日志配置已更新: {self.log_config}", "INFO")
|
|
return True
|
|
except Exception as e:
|
|
self.log_message(f"日志配置设置失败: {e}", "ERROR")
|
|
return False
|
|
|
|
def set_conversion_config(self, config: Dict[str, Any]) -> bool:
|
|
"""
|
|
设置转换配置
|
|
|
|
Args:
|
|
config: 转换配置字典
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.conversion_config.update(config)
|
|
self.log_message(f"转换配置已更新: {self.conversion_config}", "INFO")
|
|
return True
|
|
except Exception as e:
|
|
self.log_message(f"转换配置设置失败: {e}", "ERROR")
|
|
return False
|
|
|
|
def get_cache_manager(self):
|
|
"""
|
|
获取缓存管理器
|
|
|
|
Returns:
|
|
缓存管理器实例
|
|
"""
|
|
return self.cache_manager
|
|
|
|
def get_debug_tools(self):
|
|
"""
|
|
获取调试工具
|
|
|
|
Returns:
|
|
调试工具实例
|
|
"""
|
|
return self.debug_tools
|
|
|
|
def get_file_manager(self):
|
|
"""
|
|
获取文件管理器
|
|
|
|
Returns:
|
|
文件管理器实例
|
|
"""
|
|
return self.file_manager
|
|
|
|
class MathUtils:
|
|
"""数学工具类"""
|
|
|
|
def __init__(self):
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
def initialize(self):
|
|
"""初始化数学工具"""
|
|
self.initialized = True
|
|
|
|
def enable(self):
|
|
"""启用数学工具"""
|
|
self.enabled = True
|
|
|
|
def disable(self):
|
|
"""禁用数学工具"""
|
|
self.enabled = False
|
|
|
|
@staticmethod
|
|
def clamp(value: float, min_value: float, max_value: float) -> float:
|
|
"""限制值在指定范围内"""
|
|
return max(min_value, min(max_value, value))
|
|
|
|
@staticmethod
|
|
def lerp(start: float, end: float, t: float) -> float:
|
|
"""线性插值"""
|
|
return start + (end - start) * t
|
|
|
|
@staticmethod
|
|
def smoothstep(edge0: float, edge1: float, x: float) -> float:
|
|
"""平滑插值"""
|
|
t = MathUtils.clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0)
|
|
return t * t * (3.0 - 2.0 * t)
|
|
|
|
@staticmethod
|
|
def distance(pos1: tuple, pos2: tuple) -> float:
|
|
"""计算两点间距离"""
|
|
try:
|
|
dx = pos2[0] - pos1[0]
|
|
dy = pos2[1] - pos1[1]
|
|
dz = pos2[2] - pos1[2] if len(pos1) > 2 and len(pos2) > 2 else 0
|
|
return math.sqrt(dx*dx + dy*dy + dz*dz)
|
|
except Exception:
|
|
return 0.0
|
|
|
|
class CacheManager:
|
|
"""缓存管理器"""
|
|
|
|
def __init__(self):
|
|
self.enabled = False
|
|
self.initialized = False
|
|
self.cache = {}
|
|
self.access_times = {}
|
|
self.max_size = 1000
|
|
|
|
def initialize(self):
|
|
"""初始化缓存管理器"""
|
|
self.initialized = True
|
|
|
|
def enable(self):
|
|
"""启用缓存管理器"""
|
|
self.enabled = True
|
|
|
|
def disable(self):
|
|
"""禁用缓存管理器"""
|
|
self.enabled = False
|
|
|
|
def update(self, dt: float):
|
|
"""更新缓存管理器"""
|
|
if self.enabled:
|
|
self._cleanup()
|
|
|
|
def get(self, key: str) -> Optional[Any]:
|
|
"""获取缓存值"""
|
|
if key in self.cache:
|
|
self.access_times[key] = time.time()
|
|
return self.cache[key]
|
|
return None
|
|
|
|
def set(self, key: str, value: Any, ttl: float = 300.0):
|
|
"""设置缓存值"""
|
|
self.cache[key] = value
|
|
self.access_times[key] = time.time()
|
|
|
|
# 检查缓存大小
|
|
if len(self.cache) > self.max_size:
|
|
self._cleanup()
|
|
|
|
def _cleanup(self):
|
|
"""清理过期缓存"""
|
|
current_time = time.time()
|
|
expired_keys = [
|
|
key for key, access_time in self.access_times.items()
|
|
if current_time - access_time > 300.0
|
|
]
|
|
|
|
for key in expired_keys:
|
|
del self.cache[key]
|
|
del self.access_times[key]
|
|
|
|
def clear(self):
|
|
"""清空缓存"""
|
|
self.cache.clear()
|
|
self.access_times.clear()
|
|
|
|
class DebugTools:
|
|
"""调试工具类"""
|
|
|
|
def __init__(self):
|
|
self.enabled = False
|
|
self.initialized = False
|
|
self.debug_enabled = False
|
|
self.debug_data = {}
|
|
|
|
def initialize(self):
|
|
"""初始化调试工具"""
|
|
self.initialized = True
|
|
|
|
def enable(self):
|
|
"""启用调试工具"""
|
|
self.enabled = True
|
|
|
|
def disable(self):
|
|
"""禁用调试工具"""
|
|
self.enabled = False
|
|
|
|
def update(self, dt: float):
|
|
"""更新调试工具"""
|
|
pass
|
|
|
|
def enable_debug(self):
|
|
"""启用调试模式"""
|
|
self.debug_enabled = True
|
|
|
|
def disable_debug(self):
|
|
"""禁用调试模式"""
|
|
self.debug_enabled = False
|
|
|
|
def log_debug_data(self, key: str, data: Any):
|
|
"""记录调试数据"""
|
|
if self.debug_enabled:
|
|
self.debug_data[key] = data
|
|
|
|
def get_debug_data(self, key: str = None) -> Union[Dict[str, Any], Any]:
|
|
"""获取调试数据"""
|
|
if key:
|
|
return self.debug_data.get(key)
|
|
return self.debug_data.copy()
|
|
|
|
def clear_debug_data(self):
|
|
"""清空调试数据"""
|
|
self.debug_data.clear()
|
|
|
|
def clear(self):
|
|
"""清理调试工具"""
|
|
self.debug_data.clear()
|
|
|
|
class FileManager:
|
|
"""文件管理器"""
|
|
|
|
def __init__(self):
|
|
self.enabled = False
|
|
self.initialized = False
|
|
self.watched_files = {}
|
|
|
|
def initialize(self):
|
|
"""初始化文件管理器"""
|
|
self.initialized = True
|
|
|
|
def enable(self):
|
|
"""启用文件管理器"""
|
|
self.enabled = True
|
|
|
|
def disable(self):
|
|
"""禁用文件管理器"""
|
|
self.enabled = False
|
|
|
|
def update(self, dt: float):
|
|
"""更新文件管理器"""
|
|
if self.enabled:
|
|
self._check_file_changes()
|
|
|
|
def _check_file_changes(self):
|
|
"""检查文件变化"""
|
|
try:
|
|
for file_path, last_modified in list(self.watched_files.items()):
|
|
if os.path.exists(file_path):
|
|
current_modified = os.path.getmtime(file_path)
|
|
if current_modified > last_modified:
|
|
self.watched_files[file_path] = current_modified
|
|
# 触发文件变化事件
|
|
except Exception as e:
|
|
pass
|
|
|
|
def watch_file(self, file_path: str):
|
|
"""监视文件变化"""
|
|
try:
|
|
if os.path.exists(file_path):
|
|
self.watched_files[file_path] = os.path.getmtime(file_path)
|
|
except Exception as e:
|
|
pass
|
|
|
|
def unwatch_file(self, file_path: str):
|
|
"""取消监视文件"""
|
|
if file_path in self.watched_files:
|
|
del self.watched_files[file_path]
|
|
|
|
def read_json_file(self, file_path: str) -> Optional[Dict[str, Any]]:
|
|
"""读取JSON文件"""
|
|
try:
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
except Exception as e:
|
|
return None
|
|
|
|
def write_json_file(self, file_path: str, data: Dict[str, Any]) -> bool:
|
|
"""写入JSON文件"""
|
|
try:
|
|
with open(file_path, "w", encoding="utf-8") as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
return True
|
|
except Exception as e:
|
|
return False
|
|
|
|
def clear(self):
|
|
"""清理文件管理器"""
|
|
self.watched_files.clear() |