""" 算法管理器模块 实现不同的匹配算法(技能匹配、快速匹配等) """ import time import random from typing import Dict, Any, List, Optional from collections import defaultdict class AlgorithmManager: """ 算法管理器 实现不同的匹配算法(技能匹配、快速匹配等) """ def __init__(self, plugin): """ 初始化算法管理器 Args: plugin: 匹配系统插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 算法配置 self.algorithm_config = { "default_algorithm": "skill_based", "available_algorithms": ["skill_based", "quick", "team_balanced", "custom"], "skill_based_config": { "skill_range": 100, # 技能匹配范围 "max_wait_time": 120.0, # 最大等待时间(秒) "expand_range_over_time": True, # 随时间扩展匹配范围 "range_expansion_rate": 10 # 每秒扩展范围 }, "team_balanced_config": { "balance_threshold": 0.1, # 平衡阈值 "max_balance_attempts": 5 # 最大平衡尝试次数 }, "quick_match_config": { "max_queue_time": 30.0, # 最大排队时间 "min_players": 2, # 最少玩家数 "max_players": 8 # 最多玩家数 } } # 算法状态 self.algorithm_state = { "active_algorithm": "skill_based", "total_matches": 0, "successful_matches": 0, "failed_matches": 0, "average_match_quality": 0.0 } # 玩家数据存储 self.player_data = {} # 玩家技能、统计数据等 # 算法统计 self.algorithm_stats = { "algorithms_run": 0, "matches_created": 0, "players_matched": 0, "algorithm_errors": 0 } # 回调函数 self.algorithm_callbacks = { "algorithm_selected": [], "match_quality_calculated": [], "algorithm_error": [] } # 时间戳记录 self.last_algorithm_run = 0.0 self.last_stats_reset = 0.0 print("✓ 算法管理器已创建") def initialize(self) -> bool: """ 初始化算法管理器 Returns: 是否初始化成功 """ try: print("正在初始化算法管理器...") # 注册默认算法 self._register_default_algorithms() self.initialized = True print("✓ 算法管理器初始化完成") return True except Exception as e: print(f"✗ 算法管理器初始化失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 import traceback traceback.print_exc() return False def _register_default_algorithms(self): """注册默认算法""" try: print("✓ 默认算法已注册") except Exception as e: print(f"✗ 默认算法注册失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 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}") self.algorithm_stats["algorithm_errors"] += 1 import traceback traceback.print_exc() return False def disable(self): """禁用算法管理器""" try: self.enabled = False print("✓ 算法管理器已禁用") except Exception as e: print(f"✗ 算法管理器禁用失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 import traceback traceback.print_exc() def finalize(self): """清理算法管理器资源""" try: # 禁用算法管理器 if self.enabled: self.disable() # 清理回调 self.algorithm_callbacks.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.last_algorithm_run = time.time() except Exception as e: print(f"✗ 算法管理器更新失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 import traceback traceback.print_exc() def set_active_algorithm(self, algorithm_name: str) -> bool: """ 设置活动算法 Args: algorithm_name: 算法名称 Returns: 是否设置成功 """ try: if algorithm_name not in self.algorithm_config["available_algorithms"]: print(f"✗ 不支持的算法: {algorithm_name}") return False self.algorithm_state["active_algorithm"] = algorithm_name print(f"✓ 活动算法已设置为: {algorithm_name}") # 触发算法选择回调 self._trigger_algorithm_callback("algorithm_selected", { "algorithm": algorithm_name, "timestamp": time.time() }) return True except Exception as e: print(f"✗ 活动算法设置失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return False def run_matching_algorithm(self, players: List[Dict[str, Any]], algorithm: str = None) -> Optional[List[List[Dict[str, Any]]]]: """ 运行匹配算法 Args: players: 玩家列表 algorithm: 算法名称(可选,默认使用活动算法) Returns: 匹配结果(玩家分组列表)或None """ try: if not self.enabled: return None # 使用指定算法或活动算法 if algorithm is None: algorithm = self.algorithm_state["active_algorithm"] # 验证算法支持 if algorithm not in self.algorithm_config["available_algorithms"]: print(f"✗ 不支持的算法: {algorithm}") self.algorithm_stats["algorithm_errors"] += 1 return None self.algorithm_stats["algorithms_run"] += 1 # 根据算法类型运行相应算法 if algorithm == "skill_based": result = self._run_skill_based_matching(players) elif algorithm == "quick": result = self._run_quick_matching(players) elif algorithm == "team_balanced": result = self._run_team_balanced_matching(players) else: # 默认使用技能匹配 result = self._run_skill_based_matching(players) if result: self.algorithm_state["successful_matches"] += 1 self.algorithm_state["total_matches"] += 1 self.algorithm_stats["matches_created"] += 1 # 计算匹配质量 match_quality = self._calculate_match_quality(result) self.algorithm_state["average_match_quality"] = ( self.algorithm_state["average_match_quality"] * (self.algorithm_state["successful_matches"] - 1) + match_quality ) / self.algorithm_state["successful_matches"] # 触发匹配质量计算回调 self._trigger_algorithm_callback("match_quality_calculated", { "quality": match_quality, "algorithm": algorithm, "timestamp": time.time() }) else: self.algorithm_state["failed_matches"] += 1 return result except Exception as e: print(f"✗ 匹配算法运行失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return None def _run_skill_based_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]: """ 运行基于技能的匹配算法 Args: players: 玩家列表 Returns: 匹配结果或None """ try: if not players: return None config = self.algorithm_config["skill_based_config"] skill_range = config["skill_range"] # 按技能水平排序玩家 sorted_players = sorted(players, key=lambda p: p.get("skill_level", 0)) # 简化实现:将技能相近的玩家分组 groups = [] current_group = [sorted_players[0]] for i in range(1, len(sorted_players)): current_player = sorted_players[i] last_player = current_group[-1] # 检查技能差异是否在范围内 skill_diff = abs(current_player.get("skill_level", 0) - last_player.get("skill_level", 0)) if skill_diff <= skill_range and len(current_group) < 8: # 最多8人一组 current_group.append(current_player) else: # 创建新组 groups.append(current_group) current_group = [current_player] # 添加最后一组 if current_group: groups.append(current_group) print(f"✓ 技能匹配完成: 创建了 {len(groups)} 个组") return groups except Exception as e: print(f"✗ 技能匹配算法失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return None def _run_quick_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]: """ 运行快速匹配算法 Args: players: 玩家列表 Returns: 匹配结果或None """ try: if not players: return None config = self.algorithm_config["quick_match_config"] min_players = config["min_players"] max_players = config["max_players"] # 简化实现:随机分组 groups = [] player_pool = players.copy() random.shuffle(player_pool) while player_pool: group_size = min(random.randint(min_players, max_players), len(player_pool)) group = player_pool[:group_size] groups.append(group) player_pool = player_pool[group_size:] print(f"✓ 快速匹配完成: 创建了 {len(groups)} 个组") return groups except Exception as e: print(f"✗ 快速匹配算法失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return None def _run_team_balanced_matching(self, players: List[Dict[str, Any]]) -> Optional[List[List[Dict[str, Any]]]]: """ 运行团队平衡匹配算法 Args: players: 玩家列表 Returns: 匹配结果或None """ try: if not players or len(players) < 2: return None # 简化实现:创建两个平衡的团队 # 按技能排序 sorted_players = sorted(players, key=lambda p: p.get("skill_level", 0), reverse=True) team1 = [] team2 = [] team1_skill = 0 team2_skill = 0 # 贪心算法分配玩家到技能平衡的团队 for player in sorted_players: player_skill = player.get("skill_level", 0) if team1_skill <= team2_skill: team1.append(player) team1_skill += player_skill else: team2.append(player) team2_skill += player_skill groups = [team1, team2] if team1 and team2 else [sorted_players] print(f"✓ 团队平衡匹配完成: 创建了 {len(groups)} 个组") return groups except Exception as e: print(f"✗ 团队平衡匹配算法失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return None def _calculate_match_quality(self, groups: List[List[Dict[str, Any]]]) -> float: """ 计算匹配质量 Args: groups: 玩家分组 Returns: 匹配质量分数(0-1) """ try: if not groups: return 0.0 total_quality = 0.0 group_count = 0 for group in groups: if len(group) < 2: continue # 计算组内技能差异 skills = [p.get("skill_level", 0) for p in group] avg_skill = sum(skills) / len(skills) variance = sum((s - avg_skill) ** 2 for s in skills) / len(skills) std_dev = variance ** 0.5 # 转换为质量分数(标准差越小质量越高) max_expected_std = 100.0 # 假设最大预期标准差 quality = max(0.0, 1.0 - (std_dev / max_expected_std)) total_quality += quality group_count += 1 return total_quality / group_count if group_count > 0 else 0.0 except Exception as e: print(f"✗ 匹配质量计算失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return 0.0 def update_player_skill(self, player_id: str, skill_level: float, stats: Dict[str, Any] = None): """ 更新玩家技能 Args: player_id: 玩家ID skill_level: 技能等级 stats: 玩家统计数据 """ try: if player_id not in self.player_data: self.player_data[player_id] = { "skill_history": [], "match_stats": {} } player_info = self.player_data[player_id] player_info["current_skill"] = skill_level player_info["skill_history"].append({ "skill": skill_level, "timestamp": time.time() }) if stats: player_info["match_stats"].update(stats) except Exception as e: print(f"✗ 玩家技能更新失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 def get_player_skill(self, player_id: str) -> Optional[float]: """ 获取玩家技能 Args: player_id: 玩家ID Returns: 玩家技能等级或None """ try: if player_id in self.player_data: return self.player_data[player_id].get("current_skill") return None except Exception as e: print(f"✗ 玩家技能获取失败: {e}") self.algorithm_stats["algorithm_errors"] += 1 return None def get_algorithm_stats(self) -> Dict[str, Any]: """ 获取算法统计信息 Returns: 算法统计字典 """ return { "state": self.algorithm_state.copy(), "stats": self.algorithm_stats.copy(), "config": self.algorithm_config.copy(), "tracked_players": len(self.player_data) } def reset_stats(self): """重置算法统计信息""" try: self.algorithm_stats = { "algorithms_run": 0, "matches_created": 0, "players_matched": 0, "algorithm_errors": 0 } self.algorithm_state["total_matches"] = 0 self.algorithm_state["successful_matches"] = 0 self.algorithm_state["failed_matches"] = 0 self.algorithm_state["average_match_quality"] = 0.0 print("✓ 算法统计信息已重置") except Exception as e: print(f"✗ 算法统计信息重置失败: {e}") def set_algorithm_config(self, config: Dict[str, Any]) -> bool: """ 设置算法配置 Args: config: 算法配置字典 Returns: 是否设置成功 """ try: self.algorithm_config.update(config) print(f"✓ 算法配置已更新: {self.algorithm_config}") return True except Exception as e: print(f"✗ 算法配置设置失败: {e}") return False def get_algorithm_config(self) -> Dict[str, Any]: """ 获取算法配置 Returns: 算法配置字典 """ return self.algorithm_config.copy() def _trigger_algorithm_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发算法回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.algorithm_callbacks: for callback in self.algorithm_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 算法回调执行失败: {callback_type} - {e}") except Exception as e: print(f"✗ 算法回调触发失败: {e}") def register_algorithm_callback(self, callback_type: str, callback: callable): """ 注册算法回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.algorithm_callbacks: self.algorithm_callbacks[callback_type].append(callback) print(f"✓ 算法回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 算法回调注册失败: {e}") def unregister_algorithm_callback(self, callback_type: str, callback: callable): """ 注销算法回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.algorithm_callbacks: if callback in self.algorithm_callbacks[callback_type]: self.algorithm_callbacks[callback_type].remove(callback) print(f"✓ 算法回调已注销: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 算法回调注销失败: {e}")