-- ================================================================
-- 游戏匹配系统 - Lua版本 (支持队伍聚合功能)
-- 包含团队对战模式和大乱斗模式
-- ================================================================

-- 工具函数
local function printf(fmt, ...)
    print(string.format(fmt, ...))
end

local function table_size(t)
    local count = 0
    for _ in pairs(t) do count = count + 1 end
    return count
end

local function table_copy(t)
    local copy = {}
    for k, v in pairs(t) do
        if type(v) == "table" then
            copy[k] = table_copy(v)
        else
            copy[k] = v
        end
    end
    return copy
end

local function table_contains(t, item)
    for _, v in ipairs(t) do
        if v == item then return true end
    end
    return false
end

local function table_remove_item(t, item)
    for i, v in ipairs(t) do
        if v == item then
            table.remove(t, i)
            return true
        end
    end
    return false
end

-- 时间工具
local function get_current_time()
    return os.clock()
end

local function sleep(seconds)
    local start = os.clock()
    while os.clock() - start < seconds do
        -- 忙等待（在实际游戏中可能需要更好的实现）
    end
end

-- ================================================================
-- 玩家类
-- ================================================================
local Player = {}
Player.__index = Player

function Player:new(player_id, rank)
    local self = setmetatable({}, Player)
    self.player_id = player_id
    self.create_time = get_current_time()
    self.enter_pool_time = self.create_time

    if rank then
        self.rank = rank
    else
        math.randomseed(os.time())
        self.rank = math.random(1, 50)
    end

    return self
end

function Player:get_wait_time()
    return get_current_time() - self.enter_pool_time
end

function Player:to_string()
    return string.format("%s(R%d)", self.player_id, self.rank)
end

-- ================================================================
-- 队伍类
-- ================================================================
local Team = {}
Team.__index = Team

function Team:new(players, team_name)
    local self = setmetatable({}, Team)
    self.players = players or {}
    self.size = #self.players
    self.create_time = get_current_time()
    self.enter_pool_time = self.create_time

    -- 计算平均段位
    local total_rank = 0
    for _, player in ipairs(self.players) do
        total_rank = total_rank + player.rank
    end
    self.avg_rank = self.size > 0 and total_rank / self.size or 0

    -- 生成队伍名称和ID
    if team_name and team_name ~= "" then
        self.team_name = team_name
        self.team_id = "team_" .. team_name
    else
        local player_ids = ""
        for _, player in ipairs(self.players) do
            player_ids = player_ids .. player.player_id .. ","
        end
        local hash = string.len(player_ids) % 10000
        self.team_name = "Team_" .. hash
        self.team_id = "team_" .. hash
    end

    return self
end

function Team:get_wait_time()
    return get_current_time() - self.enter_pool_time
end

function Team:get_detailed_info()
    local player_list = {}
    for _, player in ipairs(self.players) do
        table.insert(player_list, player:to_string())
    end
    return string.format("%s[%s]", self.team_name, table.concat(player_list, ", "))
end

function Team:to_string()
    return string.format("Team(Name:%s, Size:%d, AvgRank:%.1f)",
                        self.team_name, self.size, self.avg_rank)
end

-- ================================================================
-- 聚合队伍类
-- ================================================================
local AggregatedTeam = {}
AggregatedTeam.__index = AggregatedTeam

function AggregatedTeam:new(main_team)
    local self = setmetatable({}, AggregatedTeam)
    self.main_team = main_team
    self.merged_teams = {}
    self.all_players = table_copy(main_team.players)
    self.create_time = main_team.create_time
    self.enter_pool_time = main_team.enter_pool_time
    self.total_size = main_team.size
    self.avg_rank = main_team.avg_rank
    self.aggregated_id = "agg_" .. main_team.team_id

    return self
end

function AggregatedTeam:merge_team(team)
    table.insert(self.merged_teams, team)

    -- 合并玩家列表
    for _, player in ipairs(team.players) do
        table.insert(self.all_players, player)
    end

    -- 重新计算统计信息
    local old_total = self.total_size
    self.total_size = self.total_size + team.size

    -- 加权平均计算新的平均段位
    self.avg_rank = (self.avg_rank * old_total + team.avg_rank * team.size) / self.total_size

    printf("队伍 %s 融入到主队伍 %s，聚合队伍现有 %d 人，平均段位 %.1f",
           team.team_name, self.main_team.team_name, self.total_size, self.avg_rank)

    return true
end

function AggregatedTeam:get_wait_time()
    return self.main_team:get_wait_time()
end

function AggregatedTeam:get_detailed_info()
    local main_info = "[主队伍] " .. self.main_team:get_detailed_info()

    if #self.merged_teams == 0 then
        return main_info
    end

    local merged_info = {}
    for _, team in ipairs(self.merged_teams) do
        table.insert(merged_info, "[融入] " .. team:get_detailed_info())
    end

    return main_info .. " + " .. table.concat(merged_info, "; ")
end

function AggregatedTeam:to_string()
    return string.format("AggregatedTeam(Main:%s, Total:%d, AvgRank:%.1f)",
                        self.main_team.team_name, self.total_size, self.avg_rank)
end

-- ================================================================
-- 匹配结果类
-- ================================================================
local MatchResult = {}
MatchResult.__index = MatchResult

function MatchResult:new(teams, match_type)
    local self = setmetatable({}, MatchResult)
    self.teams = teams or {}
    self.match_type = match_type
    self.match_time = get_current_time()

    -- 计算总玩家数和平均段位
    self.total_players = 0
    local total_rank = 0
    for _, team in ipairs(self.teams) do
        self.total_players = self.total_players + team.size
        total_rank = total_rank + team.avg_rank
    end
    self.avg_team_rank = #self.teams > 0 and total_rank / #self.teams or 0
    self.rank_variance = self:calculate_rank_variance()

    -- 大乱斗模式特殊处理
    if match_type == "battle_royale" then
        self.individual_players = self:extract_individual_players()
        local player_rank_sum = 0
        for _, player in ipairs(self.individual_players) do
            player_rank_sum = player_rank_sum + player.rank
        end
        self.avg_player_rank = #self.individual_players > 0 and
                              player_rank_sum / #self.individual_players or 0
    else
        self.individual_players = {}
        self.avg_player_rank = self.avg_team_rank
    end

    return self
end

function MatchResult:extract_individual_players()
    local players = {}
    for _, team in ipairs(self.teams) do
        for _, player in ipairs(team.players) do
            table.insert(players, player)
        end
    end
    return players
end

function MatchResult:calculate_rank_variance()
    local all_ranks = {}
    for _, team in ipairs(self.teams) do
        for _, player in ipairs(team.players) do
            table.insert(all_ranks, player.rank)
        end
    end

    if #all_ranks <= 1 then return 0.0 end

    local mean_rank = 0
    for _, rank in ipairs(all_ranks) do
        mean_rank = mean_rank + rank
    end
    mean_rank = mean_rank / #all_ranks

    local variance = 0
    for _, rank in ipairs(all_ranks) do
        variance = variance + (rank - mean_rank) ^ 2
    end

    return variance / #all_ranks
end

function MatchResult:get_battle_royale_info()
    if self.match_type ~= "battle_royale" then
        return "非大乱斗模式"
    end

    local player_info = {}
    for _, player in ipairs(self.individual_players) do
        table.insert(player_info, player:to_string())
    end

    return "独立参战玩家: " .. table.concat(player_info, ", ")
end

function MatchResult:to_string()
    if self.match_type == "battle_royale" then
        return string.format("BattleRoyaleMatch(Players:%d, AvgRank:%.1f, Variance:%.2f)",
                           self.total_players, self.avg_player_rank, self.rank_variance)
    else
        return string.format("TeamVsTeamMatch(Teams:%d, Players:%d, AvgRank:%.1f, Variance:%.2f)",
                           #self.teams, self.total_players, self.avg_team_rank, self.rank_variance)
    end
end

-- ================================================================
-- 匹配器基类
-- ================================================================
local BaseMatcher = {}
BaseMatcher.__index = BaseMatcher

function BaseMatcher:new(name, config, timeout, initial_range, expansion, max_range)
    local self = setmetatable({}, BaseMatcher)
    self.mode_name = name
    self.game_config = config or {}
    self.match_timeout_seconds = timeout or 30
    self.initial_rank_range = initial_range or 10
    self.range_expansion_per_second = expansion or 1
    self.max_rank_range = max_range or 50

    -- 统计信息
    self.stats = {
        total_matches = 0,
        successful_matches = 0,
        timeout_count = 0,
        avg_wait_time = 0.0
    }

    printf("【%s】匹配器初始化完成。游戏配置:", self.mode_name)
    for k, v in pairs(self.game_config) do
        printf("  %s:%.1f", k, v)
    end

    return self
end

function BaseMatcher:calculate_dynamic_range(wait_time)
    return math.min(self.initial_rank_range + (self.range_expansion_per_second * wait_time),
                   self.max_rank_range)
end

-- 抽象方法，需要子类实现
function BaseMatcher:add_team_to_pool(team)
    error("BaseMatcher:add_team_to_pool must be implemented by subclass")
end

function BaseMatcher:try_match()
    error("BaseMatcher:try_match must be implemented by subclass")
end

function BaseMatcher:get_statistics()
    error("BaseMatcher:get_statistics must be implemented by subclass")
end

-- ================================================================
-- 团队对战匹配器
-- ================================================================
local TeamVsTeamMatcher = {}
TeamVsTeamMatcher.__index = TeamVsTeamMatcher
setmetatable(TeamVsTeamMatcher, {__index = BaseMatcher})

function TeamVsTeamMatcher:new(name, teams_per_game, players_per_team, allow_variation,
                               timeout, initial_range, expansion)
    teams_per_game = teams_per_game or 2
    players_per_team = players_per_team or 5
    allow_variation = allow_variation or false

    local config = {
        teams_per_game = teams_per_game,
        players_per_team = players_per_team,
        allow_variation = allow_variation and 1.0 or 0.0,
        total_players = teams_per_game * players_per_team
    }

    local self = BaseMatcher:new(name, config, timeout, initial_range or 5, expansion or 0.5)
    setmetatable(self, TeamVsTeamMatcher)

    self.teams_per_game = teams_per_game
    self.players_per_team = players_per_team
    self.allow_team_size_variation = allow_variation
    self.team_pool = {}

    return self
end

function TeamVsTeamMatcher:add_team_to_pool(team)
    -- 检查队伍人数
    if not self.allow_team_size_variation and team.size ~= self.players_per_team then
        printf("【%s】队伍 %s 人数不符合要求(需要%d人，实际%d人)",
               self.mode_name, team.team_name, self.players_per_team, team.size)
        return false
    end

    team.enter_pool_time = get_current_time()
    table.insert(self.team_pool, team)

    printf("【%s】队伍 %s 加入匹配池。当前等待队伍数: %d",
           self.mode_name, team:get_detailed_info(), #self.team_pool)
    return true
end

function TeamVsTeamMatcher:try_match()
    printf("\n【%s】开始团队对战匹配...", self.mode_name)

    -- 处理超时队伍
    self:handle_timeouts()

    local matched_results = {}

    -- 检查是否有足够的队伍
    if #self.team_pool < self.teams_per_game then
        printf("【%s】等待队伍数不足 (%d/%d)",
               self.mode_name, #self.team_pool, self.teams_per_game)
        return matched_results
    end

    -- 尝试匹配队伍
    while #self.team_pool >= self.teams_per_game do
        -- 选择基准队伍（等待最久的）
        local base_team = table.remove(self.team_pool, 1)

        -- 计算动态匹配范围
        local wait_time = base_team:get_wait_time()
        local current_allowed_range = self:calculate_dynamic_range(wait_time)

        -- 寻找匹配的队伍
        local matched_teams = self:find_matching_teams(base_team, current_allowed_range)

        if #matched_teams > 0 then
            -- 包含基准队伍
            local all_matched_teams = {base_team}
            for _, team in ipairs(matched_teams) do
                table.insert(all_matched_teams, team)
            end

            local result = MatchResult:new(all_matched_teams, "team_vs_team")
            table.insert(matched_results, result)

            local team_names = {}
            for _, team in ipairs(all_matched_teams) do
                table.insert(team_names, team.team_name)
            end

            printf("【%s】匹配成功！对战队伍: %s，平均队伍段位: %.1f",
                   self.mode_name, table.concat(team_names, ", "), result.avg_team_rank)

            self.stats.successful_matches = self.stats.successful_matches + 1
        else
            -- 没找到合适的对手，放回队列
            printf("【%s】暂时无法为队伍 %s 找到合适对手，放回队尾。当前允许段位差: %.1f",
                   self.mode_name, base_team.team_name, current_allowed_range)
            table.insert(self.team_pool, base_team)
            break -- 避免无限循环
        end
    end

    self.stats.total_matches = self.stats.total_matches + 1
    printf("【%s】本轮匹配结束，成功匹配 %d 场对战", self.mode_name, #matched_results)

    return matched_results
end

function TeamVsTeamMatcher:find_matching_teams(base_team, allowed_range)
    local matched_teams = {}
    local remaining_teams = {}
    local needed_teams = self.teams_per_game - 1 -- 除去基准队伍

    -- 遍历队伍池寻找合适的对手
    for _, team in ipairs(self.team_pool) do
        if #matched_teams < needed_teams then
            -- 检查段位差距
            local rank_diff = math.abs(base_team.avg_rank - team.avg_rank)
            if rank_diff <= allowed_range then
                -- 检查队伍大小（如果允许变化）
                if self.allow_team_size_variation or team.size == self.players_per_team then
                    table.insert(matched_teams, team)
                else
                    table.insert(remaining_teams, team)
                end
            else
                table.insert(remaining_teams, team)
            end
        else
            table.insert(remaining_teams, team)
        end
    end

    -- 更新队伍池（移除已匹配的队伍）
    self.team_pool = remaining_teams

    -- 如果没找到足够的队伍，将已选中的队伍也放回
    if #matched_teams < needed_teams then
        for _, team in ipairs(matched_teams) do
            table.insert(self.team_pool, 1, team)
        end
        return {}
    end

    return matched_teams
end

function TeamVsTeamMatcher:handle_timeouts()
    local current_time = get_current_time()
    local timeout_teams = {}
    local remaining_teams = {}

    for _, team in ipairs(self.team_pool) do
        local elapsed = current_time - team.enter_pool_time
        if elapsed > self.match_timeout_seconds then
            table.insert(timeout_teams, team)
        else
            table.insert(remaining_teams, team)
        end
    end

    self.team_pool = remaining_teams

    if #timeout_teams > 0 then
        self.stats.timeout_count = self.stats.timeout_count + #timeout_teams
        printf("【%s】移除 %d 个超时队伍", self.mode_name, #timeout_teams)
        for _, team in ipairs(timeout_teams) do
            printf("   超时队伍: %s (等待%.1fs)", team.team_name, team:get_wait_time())
        end
    end
end

function TeamVsTeamMatcher:get_statistics()
    local current_stats = {
        total_matches = self.stats.total_matches,
        successful_matches = self.stats.successful_matches,
        timeout_count = self.stats.timeout_count,
        current_waiting_teams = #self.team_pool,
        success_rate = 0.0
    }

    if self.stats.total_matches > 0 then
        current_stats.success_rate = self.stats.successful_matches / self.stats.total_matches * 100
    end

    return current_stats
end

-- ================================================================
-- 大乱斗匹配器（支持队伍聚合）
-- ================================================================
local BattleRoyaleMatcher = {}
BattleRoyaleMatcher.__index = BattleRoyaleMatcher
setmetatable(BattleRoyaleMatcher, {__index = BaseMatcher})

function BattleRoyaleMatcher:new(name, target_players, min_teams, max_teams, max_variance,
                                enable_aggregation, max_agg_size, timeout, initial_range, expansion)
    target_players = target_players or 20
    min_teams = min_teams or 4
    max_teams = max_teams or 10
    max_variance = max_variance or 100.0
    enable_aggregation = enable_aggregation ~= false  -- 默认true
    max_agg_size = max_agg_size or 8

    local config = {
        target_total_players = target_players,
        min_teams = min_teams,
        max_teams = max_teams,
        max_rank_variance = max_variance,
        enable_team_aggregation = enable_aggregation and 1.0 or 0.0,
        max_aggregated_size = max_agg_size
    }

    local self = BaseMatcher:new(name, config, timeout or 25, initial_range or 8, expansion or 1.0)
    setmetatable(self, BattleRoyaleMatcher)

    self.target_total_players = target_players
    self.min_teams = min_teams
    self.max_teams = max_teams
    self.max_rank_variance = max_variance
    self.enable_team_aggregation = enable_aggregation
    self.max_aggregated_size = max_agg_size

    self.team_pool = {}
    self.aggregated_pool = {}

    return self
end

function BattleRoyaleMatcher:add_team_to_pool(team)
    team.enter_pool_time = get_current_time()

    if self.enable_team_aggregation then
        -- 尝试队伍聚合
        local aggregated = self:try_aggregate_team(team)
        if not aggregated then
            -- 创建新的聚合队伍
            local agg_team = AggregatedTeam:new(team)
            table.insert(self.aggregated_pool, agg_team)
            printf("【%s】创建新聚合队伍: %s", self.mode_name, agg_team:to_string())
        end
    else
        -- 不使用聚合功能，直接添加到队伍池
        table.insert(self.team_pool, team)
    end

    local total_pools = #self.team_pool + #self.aggregated_pool
    printf("【%s】队伍 %s 加入匹配池。当前等待队伍数: %d",
           self.mode_name, team:get_detailed_info(), total_pools)
    return true
end

function BattleRoyaleMatcher:try_aggregate_team(new_team)
    for _, agg_team in ipairs(self.aggregated_pool) do
        if self:can_aggregate(agg_team, new_team) then
            agg_team:merge_team(new_team)
            return true
        end
    end
    return false
end

function BattleRoyaleMatcher:can_aggregate(agg_team, new_team)
    -- 1. 检查聚合后人数不超过限制
    if agg_team.total_size + new_team.size > self.max_aggregated_size then
        return false
    end

    -- 2. 检查段位差距
    local rank_diff = math.abs(agg_team.avg_rank - new_team.avg_rank)
    local max_wait_time = math.max(agg_team:get_wait_time(), new_team:get_wait_time())
    local allowed_range = self:calculate_dynamic_range(max_wait_time)

    if rank_diff > allowed_range then
        return false
    end

    -- 3. 检查聚合后的方差是否合理
    local temp_players = table_copy(agg_team.all_players)
    for _, player in ipairs(new_team.players) do
        table.insert(temp_players, player)
    end

    if #temp_players > 1 then
        local mean_rank = 0
        for _, player in ipairs(temp_players) do
            mean_rank = mean_rank + player.rank
        end
        mean_rank = mean_rank / #temp_players

        local variance = 0
        for _, player in ipairs(temp_players) do
            variance = variance + (player.rank - mean_rank) ^ 2
        end
        variance = variance / #temp_players

        -- 动态方差限制
        local max_wait = math.max(agg_team:get_wait_time(), new_team:get_wait_time())
        local allowed_variance = self:calculate_dynamic_variance(max_wait)

        if variance > allowed_variance then
            return false
        end
    end

    return true
end

function BattleRoyaleMatcher:calculate_dynamic_variance(max_wait_time)
    -- 基础方差 + 时间因子
    local base_variance = self.max_rank_variance * 0.3  -- 30%作为基础
    local time_factor = math.min(max_wait_time * 15, self.max_rank_variance * 0.7)  -- 最多70%
    return base_variance + time_factor
end

function BattleRoyaleMatcher:try_match()
    printf("\n【%s】开始大乱斗匹配...", self.mode_name)

    -- 处理超时队伍
    self:handle_timeouts()

    local matched_results = {}

    -- 根据聚合模式选择匹配池
    if self.enable_team_aggregation then
        -- 使用聚合队伍池
        if #self.aggregated_pool < self.min_teams then
            printf("【%s】等待聚合队伍数不足 (%d/%d)",
                   self.mode_name, #self.aggregated_pool, self.min_teams)
            return matched_results
        end

        -- 计算最长等待时间
        local max_wait_time = 0
        for _, agg in ipairs(self.aggregated_pool) do
            max_wait_time = math.max(max_wait_time, agg:get_wait_time())
        end
        local current_allowed_variance = self:calculate_dynamic_variance(max_wait_time)

        -- 寻找最佳聚合队伍组合
        local selected_agg_teams = self:find_balanced_aggregated_combination(
            self.aggregated_pool, current_allowed_variance)

        if #selected_agg_teams > 0 then
            -- 从聚合池中移除选中的队伍
            for _, agg_team in ipairs(selected_agg_teams) do
                table_remove_item(self.aggregated_pool, agg_team)
            end

            -- 构建最终的队伍列表（包含主队伍和融入队伍）
            local final_teams = {}
            for _, agg_team in ipairs(selected_agg_teams) do
                table.insert(final_teams, agg_team.main_team)
                for _, merged_team in ipairs(agg_team.merged_teams) do
                    table.insert(final_teams, merged_team)
                end
            end

            local result = MatchResult:new(final_teams, "battle_royale")
            table.insert(matched_results, result)

            local agg_info = {}
            for _, agg in ipairs(selected_agg_teams) do
                local info = string.format("%s(主)+%d融入=%d人",
                                         agg.main_team.team_name, #agg.merged_teams, agg.total_size)
                table.insert(agg_info, info)
            end

            printf("【%s】大乱斗匹配成功（聚合模式）！参与聚合队伍: %d个，总玩家: %d人，平均段位: %.1f，段位方差: %.2f",
                   self.mode_name, #selected_agg_teams, result.total_players,
                   result.avg_player_rank, result.rank_variance)
            printf("   聚合队伍详情: %s", table.concat(agg_info, "; "))

            self.stats.successful_matches = self.stats.successful_matches + 1
        else
            printf("【%s】暂时无法找到平衡的聚合队伍组合，当前允许方差: %.2f",
                   self.mode_name, current_allowed_variance)
        end
    else
        -- 使用普通队伍池
        if #self.team_pool < self.min_teams then
            printf("【%s】等待队伍数不足 (%d/%d)",
                   self.mode_name, #self.team_pool, self.min_teams)
            return matched_results
        end

        -- 计算最长等待时间，用于动态调整
        local max_wait_time = 0
        for _, team in ipairs(self.team_pool) do
            max_wait_time = math.max(max_wait_time, team:get_wait_time())
        end
        local current_allowed_variance = self:calculate_dynamic_variance(max_wait_time)

        -- 寻找最佳队伍组合
        local selected_teams = self:find_balanced_team_combination(
            self.team_pool, current_allowed_variance)

        if #selected_teams > 0 then
            -- 从匹配池中移除选中的队伍
            for _, team in ipairs(selected_teams) do
                table_remove_item(self.team_pool, team)
            end

            local result = MatchResult:new(selected_teams, "battle_royale")
            table.insert(matched_results, result)

            local team_info = {}
            for _, team in ipairs(selected_teams) do
                table.insert(team_info, string.format("%s(%d人)", team.team_name, team.size))
            end

            printf("【%s】大乱斗匹配成功！参与队伍: %d个，总玩家: %d人，平均段位: %.1f，段位方差: %.2f",
                   self.mode_name, #selected_teams, result.total_players,
                   result.avg_team_rank, result.rank_variance)
            printf("   队伍详情: %s", table.concat(team_info, ", "))

            self.stats.successful_matches = self.stats.successful_matches + 1
        else
            printf("【%s】暂时无法找到平衡的队伍组合，当前允许方差: %.2f",
                   self.mode_name, current_allowed_variance)
        end
    end

    self.stats.total_matches = self.stats.total_matches + 1
    printf("【%s】本轮匹配结束", self.mode_name)

    return matched_results
end

function BattleRoyaleMatcher:find_balanced_aggregated_combination(aggregated_teams, allowed_variance)
    if #aggregated_teams < self.min_teams then
        return {}
    end

    -- 按聚合队伍平均段位排序
    local sorted_agg_teams = table_copy(aggregated_teams)
    table.sort(sorted_agg_teams, function(a, b) return a.avg_rank < b.avg_rank end)

    -- 尝试找到最佳聚合队伍组合
    local best_combination = {}
    local best_score = math.huge

    for start_idx = 1, #sorted_agg_teams do
        local current_agg_teams = {}
        local current_players = 0

        for i = start_idx, math.min(start_idx + self.max_teams - 1, #sorted_agg_teams) do
            local agg_team = sorted_agg_teams[i]
            table.insert(current_agg_teams, agg_team)
            current_players = current_players + agg_team.total_size

            -- 检查是否满足条件
            if #current_agg_teams >= self.min_teams and
               current_players >= self.target_total_players * 0.7 then

                -- 计算所有聚合队伍中玩家的方差
                local all_players = {}
                for _, agg in ipairs(current_agg_teams) do
                    for _, player in ipairs(agg.all_players) do
                        table.insert(all_players, player)
                    end
                end

                if #all_players > 1 then
                    local mean_rank = 0
                    for _, player in ipairs(all_players) do
                        mean_rank = mean_rank + player.rank
                    end
                    mean_rank = mean_rank / #all_players

                    local variance = 0
                    for _, player in ipairs(all_players) do
                        variance = variance + (player.rank - mean_rank) ^ 2
                    end
                    variance = variance / #all_players

                    if variance <= allowed_variance then
                        -- 计算分数：人数偏差 + 方差权重
                        local player_diff = math.abs(current_players - self.target_total_players)
                        local score = player_diff + variance * 0.1

                        if score < best_score then
                            best_score = score
                            best_combination = table_copy(current_agg_teams)
                        end
                    end
                end
            end

            -- 如果人数已经超出太多，停止添加
            if current_players > self.target_total_players * 1.3 then
                break
            end
        end
    end

    return best_combination
end

function BattleRoyaleMatcher:find_balanced_team_combination(teams, allowed_variance)
    if #teams < self.min_teams then
        return {}
    end

    -- 按队伍平均段位排序
    local sorted_teams = table_copy(teams)
    table.sort(sorted_teams, function(a, b) return a.avg_rank < b.avg_rank end)

    -- 最优组合策略：寻找最接近目标人数且方差最小的组合
    local best_teams = {}
    local best_score = math.huge

    for start_idx = 1, #sorted_teams do
        local current_teams = {}
        local current_players = 0

        for i = start_idx, math.min(start_idx + self.max_teams - 1, #sorted_teams) do
            local team = sorted_teams[i]
            table.insert(current_teams, team)
            current_players = current_players + team.size

            -- 检查是否满足条件
            if #current_teams >= self.min_teams and
               current_players >= self.target_total_players * 0.7 then

                -- 计算方差
                local variance = self:calculate_team_combination_variance(current_teams)

                if variance <= allowed_variance then
                    -- 计算分数：人数偏差 + 方差权重
                    local player_diff = math.abs(current_players - self.target_total_players)
                    local score = player_diff + variance * 0.1

                    if score < best_score then
                        best_score = score
                        best_teams = table_copy(current_teams)
                    end
                end
            end

            -- 如果人数已经超出太多，停止添加
            if current_players > self.target_total_players * 1.3 then
                break
            end
        end
    end

    return best_teams
end

function BattleRoyaleMatcher:calculate_team_combination_variance(teams)
    local all_players = {}
    for _, team in ipairs(teams) do
        for _, player in ipairs(team.players) do
            table.insert(all_players, player)
        end
    end

    if #all_players <= 1 then return 0.0 end

    local mean_rank = 0
    for _, player in ipairs(all_players) do
        mean_rank = mean_rank + player.rank
    end
    mean_rank = mean_rank / #all_players

    local variance = 0
    for _, player in ipairs(all_players) do
        variance = variance + (player.rank - mean_rank) ^ 2
    end

    return variance / #all_players
end

function BattleRoyaleMatcher:handle_timeouts()
    local current_time = get_current_time()
    local timeout_teams = {}
    local remaining_teams = {}

    for _, team in ipairs(self.team_pool) do
        local elapsed = current_time - team.enter_pool_time
        if elapsed > self.match_timeout_seconds then
            table.insert(timeout_teams, team)
        else
            table.insert(remaining_teams, team)
        end
    end

    self.team_pool = remaining_teams

    if #timeout_teams > 0 then
        self.stats.timeout_count = self.stats.timeout_count + #timeout_teams
        printf("【%s】移除 %d 个超时队伍", self.mode_name, #timeout_teams)
        for _, team in ipairs(timeout_teams) do
            printf("   超时队伍: %s (等待%.1fs)", team.team_name, team:get_wait_time())
        end
    end
end

function BattleRoyaleMatcher:get_statistics()
    local current_stats = {
        total_matches = self.stats.total_matches,
        successful_matches = self.stats.successful_matches,
        timeout_count = self.stats.timeout_count,
        current_waiting_teams = #self.team_pool + #self.aggregated_pool,
        success_rate = 0.0
    }

    if self.stats.total_matches > 0 then
        current_stats.success_rate = self.stats.successful_matches / self.stats.total_matches * 100
    end

    return current_stats
end

-- ================================================================
-- 演示函数
-- ================================================================

-- 团队对战模式演示
local function demo_team_vs_team_mode()
    print(string.rep("=", 60))
    print("团队对战模式演示 (5v5)")
    print(string.rep("=", 60))

    -- 创建5v5对战匹配器
    local team_matcher = TeamVsTeamMatcher:new("5v5团队对战", 2, 5, false, 30, 5, 0.5)

    -- 模拟队伍加入
    local teams_data = {
        {{"Alpha1", "Alpha2", "Alpha3", "Alpha4", "Alpha5"}, {25, 27, 26, 28, 24}, "Alpha队"},
        {{"Beta1", "Beta2", "Beta3", "Beta4", "Beta5"}, {23, 25, 24, 26, 22}, "Beta队"},
        {{"Gamma1", "Gamma2", "Gamma3", "Gamma4", "Gamma5"}, {30, 32, 29, 31, 28}, "Gamma队"},
        {{"Delta1", "Delta2", "Delta3", "Delta4", "Delta5"}, {20, 22, 21, 19, 23}, "Delta队"},
        {{"Echo1", "Echo2", "Echo3", "Echo4", "Echo5"}, {35, 37, 36, 34, 38}, "Echo队"},
        {{"Foxtrot1", "Foxtrot2", "Foxtrot3", "Foxtrot4", "Foxtrot5"}, {33, 31, 32, 35, 34}, "Foxtrot队"}
    }

    for _, team_data in ipairs(teams_data) do
        local player_ids, ranks, team_name = team_data[1], team_data[2], team_data[3]

        local players = {}
        for i, player_id in ipairs(player_ids) do
            table.insert(players, Player:new(player_id, ranks[i]))
        end

        local team = Team:new(players, team_name)
        printf("添加队伍 %s: %s", team_name, team:to_string())
        team_matcher:add_team_to_pool(team)
        sleep(0.5)
    end

    -- 执行匹配
    for round_num = 1, 4 do
        printf("\n--- 第 %d 轮匹配 ---", round_num)
        local matches = team_matcher:try_match()

        for _, match in ipairs(matches) do
            printf("匹配成功: %s", match:to_string())
            local team_details = {}
            for i, team in ipairs(match.teams) do
                table.insert(team_details, team:get_detailed_info())
            end
            printf("   对战详情: %s", table.concat(team_details, " vs "))
        end

        -- 显示统计
        local stats = team_matcher:get_statistics()
        printf("统计: 成功%d场对战, 成功率%.1f%%, 等待队伍%d个",
               stats.successful_matches, stats.success_rate, stats.current_waiting_teams)

        sleep(2)
    end
end

-- 大乱斗模式演示
local function demo_battle_royale_mode()
    print("\n" .. string.rep("=", 60))
    print("大乱斗模式演示 (20人混战 + 队伍聚合)")
    print(string.rep("=", 60))

    -- 创建20人大乱斗匹配器（启用队伍聚合）
    local battle_matcher = BattleRoyaleMatcher:new("20人大乱斗", 20, 4, 8, 80.0, true, 6, 25, 8, 1.0)

    -- 模拟不同大小的队伍陆续加入
    local teams_data = {
        {{"Solo1"}, {25}, "独狼1队"},
        {{"Duo1", "Duo2"}, {23, 26}, "双人组1"},
        {{"Trio1", "Trio2", "Trio3"}, {28, 30, 29}, "三人组1"},
        {{"Squad1", "Squad2", "Squad3", "Squad4"}, {20, 22, 21, 24}, "四人组1"},
        {{"Solo2"}, {35}, "独狼2队"},
        {{"Duo3", "Duo4"}, {32, 34}, "双人组2"},
        {{"Trio2A", "Trio2B", "Trio2C"}, {18, 19, 17}, "三人组2"},
        {{"Solo3"}, {40}, "独狼3队"},
        {{"Duo5", "Duo6"}, {38, 36}, "双人组3"},
        {{"Trio3A", "Trio3B", "Trio3C"}, {42, 45, 43}, "三人组3"},
        {{"Solo4"}, {15}, "独狼4队"},
        {{"Duo7", "Duo8"}, {12, 16}, "双人组4"}
    }

    local teams_added = 0
    for _, team_data in ipairs(teams_data) do
        local player_ids, ranks, team_name = team_data[1], team_data[2], team_data[3]

        local players = {}
        for i, player_id in ipairs(player_ids) do
            table.insert(players, Player:new(player_id, ranks[i]))
        end

        local team = Team:new(players, team_name)
        printf("添加队伍 %s: %s", team_name, team:to_string())
        battle_matcher:add_team_to_pool(team)
        teams_added = teams_added + 1

        -- 每加入几个队伍就尝试匹配一次
        if teams_added % 4 == 0 then
            printf("\n--- 尝试匹配 (当前%d队) ---", teams_added)
            local matches = battle_matcher:try_match()

            for _, match in ipairs(matches) do
                printf("大乱斗匹配: %s", match:to_string())
                local team_details = {}
                for _, team in ipairs(match.teams) do
                    table.insert(team_details, team:get_detailed_info())
                end
                printf("   参战队伍: %s", table.concat(team_details, "; "))
                -- 显示大乱斗特性：所有玩家都是独立个体
                printf("   独立混战玩家: %s", match:get_battle_royale_info())
            end

            -- 显示统计
            local stats = battle_matcher:get_statistics()
            printf("统计: 成功%d场, 等待队伍%d个",
                   stats.successful_matches, stats.current_waiting_teams)
        end

        sleep(0.8)
    end

    -- 最后再尝试一次匹配
    print("\n--- 最终匹配尝试 ---")
    local matches = battle_matcher:try_match()
    for _, match in ipairs(matches) do
        printf("大乱斗匹配: %s", match:to_string())
        print("   游戏开始后，所有玩家都是独立个体进行混战")
        printf("   %s", match:get_battle_royale_info())
    end
end

-- ================================================================
-- 主程序
-- ================================================================
local function main()
    print("游戏匹配系统 - 正确的双模式演示 (Lua版本)")
    print("两种模式都是先组队，然后队伍进入匹配状态")

    -- 设置随机种子
    math.randomseed(os.time())

    local success, error_msg = pcall(function()
        -- 演示团队对战模式
        demo_team_vs_team_mode()

        -- 演示大乱斗模式
        demo_battle_royale_mode()

        print("\n" .. string.rep("=", 60))
        print("所有演示完成！")
        print(string.rep("=", 60))
    end)

    if not success then
        printf("\n❌ 演示过程中出现错误: %s", error_msg)
    end
end

-- 执行主程序
main()