668 lines
20 KiB
Python
668 lines
20 KiB
Python
"""
|
|
生态系统工具类
|
|
提供各种实用工具函数和辅助功能
|
|
"""
|
|
|
|
import time
|
|
import json
|
|
import math
|
|
import random
|
|
from typing import Dict, Any, List, Optional, Callable
|
|
import hashlib
|
|
|
|
class EcoUtils:
|
|
"""
|
|
生态系统工具类
|
|
提供各种实用工具函数和辅助功能,包括数据处理、性能监控、日志记录等
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化生态系统工具类
|
|
|
|
Args:
|
|
plugin: 植被和生态系统插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 性能监控
|
|
self.performance_monitor = {
|
|
'frame_times': [],
|
|
'update_times': [],
|
|
'render_times': [],
|
|
'memory_usage': 0,
|
|
'object_counts': {}
|
|
}
|
|
|
|
# 数据缓存
|
|
self.data_cache = {}
|
|
self.cache_config = {
|
|
'max_size': 1000,
|
|
'expiration_time': 300 # 5分钟
|
|
}
|
|
|
|
# 日志配置
|
|
self.log_config = {
|
|
'level': 'INFO',
|
|
'file_logging': True,
|
|
'console_logging': True,
|
|
'max_log_size': 10 * 1024 * 1024, # 10MB
|
|
'log_file': 'eco_system.log'
|
|
}
|
|
|
|
# 随机数生成器
|
|
self.random_generator = random.Random()
|
|
self.random_seed = 12345
|
|
|
|
# 数据序列化
|
|
self.serialization_config = {
|
|
'format': 'json',
|
|
'compression': False,
|
|
'pretty_print': True
|
|
}
|
|
|
|
print("✓ 生态系统工具类已创建")
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化生态系统工具类
|
|
|
|
Returns:
|
|
是否初始化成功
|
|
"""
|
|
try:
|
|
# 设置随机种子
|
|
self.random_generator.seed(self.random_seed)
|
|
|
|
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
|
|
print("✓ 生态系统工具类已启用")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 生态系统工具类启用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def disable(self):
|
|
"""禁用生态系统工具类"""
|
|
try:
|
|
self.enabled = False
|
|
print("✓ 生态系统工具类已禁用")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 生态系统工具类禁用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def finalize(self):
|
|
"""清理生态系统工具类资源"""
|
|
try:
|
|
self.disable()
|
|
self.data_cache.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_monitor(dt)
|
|
|
|
# 清理缓存
|
|
self._cleanup_cache()
|
|
|
|
except Exception as e:
|
|
print(f"✗ 生态系统工具类更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _update_performance_monitor(self, dt: float):
|
|
"""更新性能监控数据"""
|
|
try:
|
|
# 记录帧时间
|
|
self.performance_monitor['frame_times'].append(dt)
|
|
|
|
# 保持最近100帧的数据
|
|
if len(self.performance_monitor['frame_times']) > 100:
|
|
self.performance_monitor['frame_times'].pop(0)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 性能监控更新失败: {e}")
|
|
|
|
def _cleanup_cache(self):
|
|
"""清理过期缓存"""
|
|
try:
|
|
current_time = time.time()
|
|
expired_keys = []
|
|
|
|
for key, (timestamp, _) in self.data_cache.items():
|
|
if current_time - timestamp > self.cache_config['expiration_time']:
|
|
expired_keys.append(key)
|
|
|
|
for key in expired_keys:
|
|
del self.data_cache[key]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 缓存清理失败: {e}")
|
|
|
|
def log_message(self, message: str, level: str = 'INFO'):
|
|
"""
|
|
记录日志消息
|
|
|
|
Args:
|
|
message: 日志消息
|
|
level: 日志级别
|
|
"""
|
|
try:
|
|
# 检查日志级别
|
|
levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
|
if levels.index(level) < levels.index(self.log_config['level']):
|
|
return
|
|
|
|
timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
|
|
log_entry = f"[{timestamp}] {level}: {message}"
|
|
|
|
# 控制台输出
|
|
if self.log_config['console_logging']:
|
|
print(log_entry)
|
|
|
|
# 文件输出
|
|
if self.log_config['file_logging']:
|
|
try:
|
|
with open(self.log_config['log_file'], 'a', encoding='utf-8') as f:
|
|
f.write(log_entry + '\n')
|
|
except Exception as e:
|
|
print(f"✗ 日志文件写入失败: {e}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 日志记录失败: {e}")
|
|
|
|
def set_log_level(self, level: str):
|
|
"""
|
|
设置日志级别
|
|
|
|
Args:
|
|
level: 日志级别
|
|
"""
|
|
valid_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
|
if level in valid_levels:
|
|
self.log_config['level'] = level
|
|
self.log_message(f"日志级别设置为: {level}")
|
|
else:
|
|
self.log_message(f"无效的日志级别: {level}", 'WARNING')
|
|
|
|
def get_performance_stats(self) -> Dict[str, Any]:
|
|
"""
|
|
获取性能统计信息
|
|
|
|
Returns:
|
|
性能统计信息字典
|
|
"""
|
|
try:
|
|
if not self.performance_monitor['frame_times']:
|
|
return {'fps': 0, 'avg_frame_time': 0, 'min_frame_time': 0, 'max_frame_time': 0}
|
|
|
|
frame_times = self.performance_monitor['frame_times']
|
|
avg_frame_time = sum(frame_times) / len(frame_times)
|
|
fps = 1.0 / avg_frame_time if avg_frame_time > 0 else 0
|
|
|
|
return {
|
|
'fps': fps,
|
|
'avg_frame_time': avg_frame_time,
|
|
'min_frame_time': min(frame_times),
|
|
'max_frame_time': max(frame_times),
|
|
'frame_count': len(frame_times)
|
|
}
|
|
|
|
except Exception as e:
|
|
self.log_message(f"性能统计获取失败: {e}", 'ERROR')
|
|
return {}
|
|
|
|
def reset_performance_stats(self):
|
|
"""重置性能统计信息"""
|
|
try:
|
|
self.performance_monitor['frame_times'].clear()
|
|
self.performance_monitor['update_times'].clear()
|
|
self.performance_monitor['render_times'].clear()
|
|
self.log_message("性能统计信息已重置")
|
|
except Exception as e:
|
|
self.log_message(f"性能统计重置失败: {e}", 'ERROR')
|
|
|
|
def cache_data(self, key: str, data: Any):
|
|
"""
|
|
缓存数据
|
|
|
|
Args:
|
|
key: 缓存键
|
|
data: 要缓存的数据
|
|
"""
|
|
try:
|
|
# 检查缓存大小
|
|
if len(self.data_cache) >= self.cache_config['max_size']:
|
|
# 移除最旧的条目
|
|
oldest_key = min(self.data_cache.keys(),
|
|
key=lambda k: self.data_cache[k][0])
|
|
del self.data_cache[oldest_key]
|
|
|
|
# 缓存数据
|
|
self.data_cache[key] = (time.time(), data)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"数据缓存失败: {e}", 'ERROR')
|
|
|
|
def get_cached_data(self, key: str) -> Optional[Any]:
|
|
"""
|
|
获取缓存数据
|
|
|
|
Args:
|
|
key: 缓存键
|
|
|
|
Returns:
|
|
缓存的数据或None
|
|
"""
|
|
try:
|
|
if key in self.data_cache:
|
|
timestamp, data = self.data_cache[key]
|
|
if time.time() - timestamp < self.cache_config['expiration_time']:
|
|
return data
|
|
else:
|
|
# 缓存过期,删除条目
|
|
del self.data_cache[key]
|
|
return None
|
|
|
|
except Exception as e:
|
|
self.log_message(f"缓存数据获取失败: {e}", 'ERROR')
|
|
return None
|
|
|
|
def clear_cache(self):
|
|
"""清空缓存"""
|
|
try:
|
|
self.data_cache.clear()
|
|
self.log_message("缓存已清空")
|
|
except Exception as e:
|
|
self.log_message(f"缓存清空失败: {e}", 'ERROR')
|
|
|
|
def serialize_data(self, data: Any, filename: str = None) -> str:
|
|
"""
|
|
序列化数据
|
|
|
|
Args:
|
|
data: 要序列化的数据
|
|
filename: 文件名(可选)
|
|
|
|
Returns:
|
|
序列化后的字符串
|
|
"""
|
|
try:
|
|
if self.serialization_config['format'] == 'json':
|
|
serialized_data = json.dumps(
|
|
data,
|
|
ensure_ascii=False,
|
|
indent=2 if self.serialization_config['pretty_print'] else None
|
|
)
|
|
|
|
if filename:
|
|
with open(filename, 'w', encoding='utf-8') as f:
|
|
f.write(serialized_data)
|
|
|
|
return serialized_data
|
|
|
|
except Exception as e:
|
|
self.log_message(f"数据序列化失败: {e}", 'ERROR')
|
|
return ""
|
|
|
|
def deserialize_data(self, data_str: str) -> Any:
|
|
"""
|
|
反序列化数据
|
|
|
|
Args:
|
|
data_str: 序列化后的字符串
|
|
|
|
Returns:
|
|
反序列化的数据
|
|
"""
|
|
try:
|
|
if self.serialization_config['format'] == 'json':
|
|
return json.loads(data_str)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"数据反序列化失败: {e}", 'ERROR')
|
|
return None
|
|
|
|
def load_data_from_file(self, filename: str) -> Any:
|
|
"""
|
|
从文件加载数据
|
|
|
|
Args:
|
|
filename: 文件名
|
|
|
|
Returns:
|
|
加载的数据
|
|
"""
|
|
try:
|
|
with open(filename, 'r', encoding='utf-8') as f:
|
|
data_str = f.read()
|
|
return self.deserialize_data(data_str)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"文件数据加载失败: {e}", 'ERROR')
|
|
return None
|
|
|
|
def save_data_to_file(self, data: Any, filename: str) -> bool:
|
|
"""
|
|
保存数据到文件
|
|
|
|
Args:
|
|
data: 要保存的数据
|
|
filename: 文件名
|
|
|
|
Returns:
|
|
是否保存成功
|
|
"""
|
|
try:
|
|
self.serialize_data(data, filename)
|
|
self.log_message(f"数据已保存到文件: {filename}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.log_message(f"文件数据保存失败: {e}", 'ERROR')
|
|
return False
|
|
|
|
def generate_hash(self, data: Any) -> str:
|
|
"""
|
|
生成数据哈希值
|
|
|
|
Args:
|
|
data: 要生成哈希的数据
|
|
|
|
Returns:
|
|
哈希值字符串
|
|
"""
|
|
try:
|
|
data_str = str(data).encode('utf-8')
|
|
return hashlib.md5(data_str).hexdigest()
|
|
|
|
except Exception as e:
|
|
self.log_message(f"哈希值生成失败: {e}", 'ERROR')
|
|
return ""
|
|
|
|
def interpolate_values(self, start_value: float, end_value: float, progress: float) -> float:
|
|
"""
|
|
插值计算
|
|
|
|
Args:
|
|
start_value: 起始值
|
|
end_value: 结束值
|
|
progress: 进度 (0.0-1.0)
|
|
|
|
Returns:
|
|
插值结果
|
|
"""
|
|
try:
|
|
return start_value + (end_value - start_value) * max(0.0, min(1.0, progress))
|
|
|
|
except Exception as e:
|
|
self.log_message(f"插值计算失败: {e}", 'ERROR')
|
|
return start_value
|
|
|
|
def clamp_value(self, value: float, min_value: float, max_value: float) -> float:
|
|
"""
|
|
限制值范围
|
|
|
|
Args:
|
|
value: 值
|
|
min_value: 最小值
|
|
max_value: 最大值
|
|
|
|
Returns:
|
|
限制后的值
|
|
"""
|
|
try:
|
|
return max(min_value, min(max_value, value))
|
|
|
|
except Exception as e:
|
|
self.log_message(f"值范围限制失败: {e}", 'ERROR')
|
|
return value
|
|
|
|
def normalize_vector(self, vector: tuple) -> tuple:
|
|
"""
|
|
标准化向量
|
|
|
|
Args:
|
|
vector: 向量 (x, y, z)
|
|
|
|
Returns:
|
|
标准化后的向量
|
|
"""
|
|
try:
|
|
length = math.sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)
|
|
if length > 0:
|
|
return (vector[0] / length, vector[1] / length, vector[2] / length)
|
|
return (0, 0, 0)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"向量标准化失败: {e}", 'ERROR')
|
|
return (0, 0, 0)
|
|
|
|
def distance_3d(self, pos1: tuple, pos2: tuple) -> float:
|
|
"""
|
|
计算3D空间中两点间的距离
|
|
|
|
Args:
|
|
pos1: 位置1 (x, y, z)
|
|
pos2: 位置2 (x, y, z)
|
|
|
|
Returns:
|
|
距离
|
|
"""
|
|
try:
|
|
return math.sqrt((pos1[0] - pos2[0])**2 +
|
|
(pos1[1] - pos2[1])**2 +
|
|
(pos1[2] - pos2[2])**2)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"距离计算失败: {e}", 'ERROR')
|
|
return 0.0
|
|
|
|
def random_float(self, min_value: float, max_value: float) -> float:
|
|
"""
|
|
生成随机浮点数
|
|
|
|
Args:
|
|
min_value: 最小值
|
|
max_value: 最大值
|
|
|
|
Returns:
|
|
随机浮点数
|
|
"""
|
|
try:
|
|
return self.random_generator.uniform(min_value, max_value)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"随机数生成失败: {e}", 'ERROR')
|
|
return 0.0
|
|
|
|
def random_int(self, min_value: int, max_value: int) -> int:
|
|
"""
|
|
生成随机整数
|
|
|
|
Args:
|
|
min_value: 最小值
|
|
max_value: 最大值
|
|
|
|
Returns:
|
|
随机整数
|
|
"""
|
|
try:
|
|
return self.random_generator.randint(min_value, max_value)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"随机整数生成失败: {e}", 'ERROR')
|
|
return 0
|
|
|
|
def set_random_seed(self, seed: int):
|
|
"""
|
|
设置随机种子
|
|
|
|
Args:
|
|
seed: 随机种子
|
|
"""
|
|
try:
|
|
self.random_seed = seed
|
|
self.random_generator.seed(seed)
|
|
self.log_message(f"随机种子设置为: {seed}")
|
|
except Exception as e:
|
|
self.log_message(f"随机种子设置失败: {e}", 'ERROR')
|
|
|
|
def get_system_info(self) -> Dict[str, Any]:
|
|
"""
|
|
获取系统信息
|
|
|
|
Returns:
|
|
系统信息字典
|
|
"""
|
|
try:
|
|
return {
|
|
'plugin_version': getattr(self.plugin, 'version', 'Unknown'),
|
|
'plugin_name': getattr(self.plugin, 'name', 'Unknown'),
|
|
'cache_size': len(self.data_cache),
|
|
'log_level': self.log_config['level'],
|
|
'random_seed': self.random_seed
|
|
}
|
|
|
|
except Exception as e:
|
|
self.log_message(f"系统信息获取失败: {e}", 'ERROR')
|
|
return {}
|
|
|
|
def create_timer(self) -> Callable[[], float]:
|
|
"""
|
|
创建计时器
|
|
|
|
Returns:
|
|
计时器函数,调用时返回经过的时间(秒)
|
|
"""
|
|
try:
|
|
start_time = time.time()
|
|
|
|
def get_elapsed_time():
|
|
return time.time() - start_time
|
|
|
|
return get_elapsed_time
|
|
|
|
except Exception as e:
|
|
self.log_message(f"计时器创建失败: {e}", 'ERROR')
|
|
|
|
def dummy_timer():
|
|
return 0.0
|
|
|
|
return dummy_timer
|
|
|
|
def format_time(self, seconds: float) -> str:
|
|
"""
|
|
格式化时间显示
|
|
|
|
Args:
|
|
seconds: 秒数
|
|
|
|
Returns:
|
|
格式化后的时间字符串
|
|
"""
|
|
try:
|
|
hours = int(seconds // 3600)
|
|
minutes = int((seconds % 3600) // 60)
|
|
secs = int(seconds % 60)
|
|
|
|
if hours > 0:
|
|
return f"{hours:02d}:{minutes:02d}:{secs:02d}"
|
|
else:
|
|
return f"{minutes:02d}:{secs:02d}"
|
|
|
|
except Exception as e:
|
|
self.log_message(f"时间格式化失败: {e}", 'ERROR')
|
|
return "00:00"
|
|
|
|
def get_memory_usage(self) -> int:
|
|
"""
|
|
获取内存使用情况(简化实现)
|
|
|
|
Returns:
|
|
内存使用量(字节)
|
|
"""
|
|
try:
|
|
# 简化实现,实际项目中可能需要使用更精确的方法
|
|
import sys
|
|
return sys.getsizeof(self)
|
|
|
|
except Exception as e:
|
|
self.log_message(f"内存使用量获取失败: {e}", 'ERROR')
|
|
return 0
|
|
|
|
def benchmark_function(self, func: Callable, *args, **kwargs) -> Dict[str, Any]:
|
|
"""
|
|
基准测试函数
|
|
|
|
Args:
|
|
func: 要测试的函数
|
|
*args: 函数参数
|
|
**kwargs: 函数关键字参数
|
|
|
|
Returns:
|
|
测试结果字典
|
|
"""
|
|
try:
|
|
timer = self.create_timer()
|
|
result = func(*args, **kwargs)
|
|
elapsed_time = timer()
|
|
|
|
return {
|
|
'result': result,
|
|
'execution_time': elapsed_time,
|
|
'success': True
|
|
}
|
|
|
|
except Exception as e:
|
|
self.log_message(f"函数基准测试失败: {e}", 'ERROR')
|
|
return {
|
|
'result': None,
|
|
'execution_time': 0,
|
|
'success': False,
|
|
'error': str(e)
|
|
} |