package com.xy.xyaicpzs.dlt;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xy.xyaicpzs.domain.entity.*;
import com.xy.xyaicpzs.mapper.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 前区随球预测器
 */
@Slf4j
@Component
public class FollowerBallPredictor {

    @Autowired
    private D5Mapper d5Mapper;

    @Autowired
    private D9Mapper d9Mapper;

    @Autowired
    private D12Mapper d12Mapper;

    @Autowired
    private DltFrontendHistoryTop100Mapper dltFrontendHistoryTop100Mapper;

    @Autowired
    private DltFrontendHistoryTopMapper dltFrontendHistoryTopMapper;

    @Autowired
    private DltFrontendHistoryAllMapper dltFrontendHistoryAllMapper;

    /**
     * 球号和系数的关联类
     */
    @Data
    public static class BallWithCoefficient {
        private Integer ballNumber;
        private Double coefficient;
        private Integer masterBallNumber; // 主球号，用于标识来源

        public BallWithCoefficient(Integer ballNumber, Double coefficient, Integer masterBallNumber) {
            this.ballNumber = ballNumber;
            this.coefficient = coefficient;
            this.masterBallNumber = masterBallNumber;
        }

        @Override
        public String toString() {
            return "Ball{" +
                    "ballNumber=" + ballNumber +
                    ", coefficient=" + coefficient +
                    ", masterBallNumber=" + masterBallNumber +
                    '}';
        }
    }

    /**
     * 前区随球预测结果类
     */
    @Data
    public static class FollowerBallPredictionResult {
        private List<Integer> result;
        private String filteringProcess;
        
        public FollowerBallPredictionResult(List<Integer> result, String filteringProcess) {
            this.result = result;
            this.filteringProcess = filteringProcess;
        }
    }
    
    /**
     * 前区随球预测（带过程）
     * @param level 位置级别（high/middle/low）
     * @param wellRegardedBalls 看好的4个号码
     * @param previousFrontBalls 上期前区5个号码
     * @param previousBackBalls 上期后区2个号码
     * @return 预测的10个随球号码和筛选过程
     */
    public FollowerBallPredictionResult predictFollowerBallWithProcess(String level, List<Integer> wellRegardedBalls, List<Integer> previousFrontBalls, List<Integer> previousBackBalls) {
        // 参数验证
        validateInputParams(level, wellRegardedBalls, previousFrontBalls, previousBackBalls);
        
        // 存放D5表中对应的系数，用于后续筛选
        Map<Integer, List<BallWithCoefficient>> d5CoefficientMap = new HashMap<>();
        
        // 所有候选球列表
        List<Integer> allCandidateBalls = new ArrayList<>();
        
        // 步骤一：处理第一个看好号码
        if (!wellRegardedBalls.isEmpty()) {
            Integer firstBall = wellRegardedBalls.get(0);
            List<BallWithCoefficient> firstBallCandidates;
            
            if ("high".equalsIgnoreCase(level)) {
                firstBallCandidates = getHighLevelBallsFromD5(firstBall);
            } else if ("middle".equalsIgnoreCase(level)) {
                firstBallCandidates = getMiddleLevelBallsFromD5(firstBall);
            } else { // low
                firstBallCandidates = getLowLevelBallsFromD5(firstBall);
            }
            
            for (BallWithCoefficient ball : firstBallCandidates) {
                d5CoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
                allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // 步骤二：处理上期前区5个号码
        for (Integer frontBall : previousFrontBalls) {
            List<BallWithCoefficient> frontBallCandidates = getTop30BallsFromD9(frontBall);
            for (BallWithCoefficient ball : frontBallCandidates) {
                allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // 步骤三：从历史排行表获取平均值向上的3个球
        List<Integer> top3HistoryTop = getTop3FromHistoryTop();
        allCandidateBalls.addAll(top3HistoryTop);
        
        // 步骤四：从百期排行表获取平均值向上的3个球
        List<Integer> top3HistoryTop100 = getTop3FromHistoryTop100();
        allCandidateBalls.addAll(top3HistoryTop100);
            
        // 步骤五：处理上期后区2个号码
        for (Integer backBall : previousBackBalls) {
            List<BallWithCoefficient> backBallCandidates = getTop30BallsFromD12(backBall);
            for (BallWithCoefficient ball : backBallCandidates) {
                allCandidateBalls.add(ball.getBallNumber());
            }
        }

        return selectFinal10BallsWithProcess(allCandidateBalls, d5CoefficientMap);
    }

    /**
     * 随球预测主方法
     * @param level 位置级别（high/middle/low）
     * @param wellRegardedBalls 看好的4个号码
     * @param previousFrontBalls 上期前区5个号码
     * @param previousBackBalls 上期后区2个号码
     * @return 预测的10个随球号码
     */
    public List<Integer> predictFollowerBall(String level, List<Integer> wellRegardedBalls, List<Integer> previousFrontBalls, List<Integer> previousBackBalls) {
        // 参数验证
        validateInputParams(level, wellRegardedBalls, previousFrontBalls, previousBackBalls);
        
        // 存放D5表中对应的系数，用于后续筛选
        Map<Integer, List<BallWithCoefficient>> d5CoefficientMap = new HashMap<>();
        
        // 所有候选球列表
        List<Integer> allCandidateBalls = new ArrayList<>();
        
        // 步骤一：处理第一个看好号码
        if (!wellRegardedBalls.isEmpty()) {
            Integer firstBall = wellRegardedBalls.get(0);
            List<BallWithCoefficient> firstBallCandidates;
            
            if ("high".equalsIgnoreCase(level)) {
                firstBallCandidates = getHighLevelBallsFromD5(firstBall);
            } else if ("middle".equalsIgnoreCase(level)) {
                firstBallCandidates = getMiddleLevelBallsFromD5(firstBall);
            } else { // low
                firstBallCandidates = getLowLevelBallsFromD5(firstBall);
            }
            
            for (BallWithCoefficient ball : firstBallCandidates) {
                d5CoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
                allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // 步骤二：处理上期前区5个号码
        for (Integer frontBall : previousFrontBalls) {
            List<BallWithCoefficient> frontBallCandidates = getTop30BallsFromD9(frontBall);
            for (BallWithCoefficient ball : frontBallCandidates) {
                    allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // 步骤三：从历史排行表获取平均值向上的3个球
        List<Integer> top3HistoryTop = getTop3FromHistoryTop();
        allCandidateBalls.addAll(top3HistoryTop);
        
        // 步骤四：从百期排行表获取平均值向上的3个球
        List<Integer> top3HistoryTop100 = getTop3FromHistoryTop100();
        allCandidateBalls.addAll(top3HistoryTop100);
            
        // 步骤五：处理上期后区2个号码
        for (Integer backBall : previousBackBalls) {
            List<BallWithCoefficient> backBallCandidates = getTop30BallsFromD12(backBall);
            for (BallWithCoefficient ball : backBallCandidates) {
                    allCandidateBalls.add(ball.getBallNumber());
            }
        }
        
        // 步骤六：加入看好的后3个号码
        for (int i = 1; i < wellRegardedBalls.size(); i++) {
            Integer wellBall = wellRegardedBalls.get(i);
                allCandidateBalls.add(wellBall);
        }
        
        // 最终筛选10个球
        return selectFinal10Balls(allCandidateBalls, d5CoefficientMap);
    }
    
    /**
     * 高位策略：从D5表中获取最大值向下的11个球号
     */
    private List<BallWithCoefficient> getHighLevelBallsFromD5(Integer masterBallNumber) {
        List<D5> d5List = d5Mapper.selectList(
            new LambdaQueryWrapper<D5>()
                .eq(D5::getMasterBallNumber, masterBallNumber));
        if (CollectionUtils.isEmpty(d5List)) {
            log.warn("No D5 records found for master ball: {}", masterBallNumber);
            return new ArrayList<>();
        }
        
        // 按系数从大到小排序
        d5List.sort((d1, d2) -> d2.getCoefficient().compareTo(d1.getCoefficient()));
        
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = 0;
        int addedCount = 0;
        
        while (addedCount < 11 && index < d5List.size()) {
            double currentCoefficient = d5List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号
            while (index < d5List.size() && 
                   d5List.get(index).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d5List.get(index).getSlaveBallNumber());
                index++;
            }
            
            // 计算还需要多少个球
            int needCount = Math.min(11 - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                addedCount++;
            } else if (needCount == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                }
                addedCount += sameCoefficientBalls.size();
            } else {
                // 需要从多个相同系数的球号中选择部分，处理毛边
                List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needCount);
                for (Integer selectedBall : selectedBalls) {
                    result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                    addedCount++;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 中位策略：从D5表中获取平均值及其附近的11个球号
     */
    private List<BallWithCoefficient> getMiddleLevelBallsFromD5(Integer masterBallNumber) {
        List<D5> d5List = d5Mapper.selectList(
            new LambdaQueryWrapper<D5>()
                .eq(D5::getMasterBallNumber, masterBallNumber));
        if (CollectionUtils.isEmpty(d5List)) {
            log.warn("No D5 records found for master ball: {}", masterBallNumber);
            return new ArrayList<>();
        }
        
        // 按系数从大到小排序
        d5List.sort((d1, d2) -> d2.getCoefficient().compareTo(d1.getCoefficient()));
        
        // 计算平均系数
        double avgCoefficient = d5List.stream()
                .mapToDouble(D5::getCoefficient)
                .average()
                .orElse(0.0);
        
        // 找到比平均值大且最接近平均值的位置（从下到上遍历）
        int avgPosition = -1;
        for (int i = d5List.size() - 1; i >= 0; i--) {
            double diff = d5List.get(i).getCoefficient() - avgCoefficient;
            if (diff >= 0) {
                avgPosition = i;
                break; // 找到第一个比平均值大的位置就停止
            }
        }
        
        // 如果没找到大于平均值的系数，取第一个
        if (avgPosition == -1) {
            avgPosition = 0;
        }
        
        List<BallWithCoefficient> result = new ArrayList<>();
        
        // 先加入平均值位置的球号
        result.add(new BallWithCoefficient(d5List.get(avgPosition).getSlaveBallNumber(), 
                d5List.get(avgPosition).getCoefficient(), masterBallNumber));
        
        // 向上取5个球号（使用高位策略的毛边处理逻辑）
        List<BallWithCoefficient> upperBalls = getUpperBallsFromAverageD5(d5List, avgPosition, 5, masterBallNumber);
        result.addAll(upperBalls);
        
        // 向下取5个球号（使用低位策略的毛边处理逻辑）
        List<BallWithCoefficient> lowerBalls = getLowerBallsFromAverageD5(d5List, avgPosition, 5, masterBallNumber);
        result.addAll(lowerBalls);
        
        return result;
    }
    
    /**
     * 从D5表平均值位置向上取指定数量的球号
     */
    private List<BallWithCoefficient> getUpperBallsFromAverageD5(List<D5> d5List, int avgPosition, int needCount, Integer masterBallNumber) {
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = avgPosition - 1; // 从平均值位置的上一个开始
        int addedCount = 0;
        
        // 从平均值向上遍历（使用高位策略的逻辑）
        while (addedCount < needCount && index >= 0) {
            double currentCoefficient = d5List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号（向前收集）
            int tempIndex = index;
            while (tempIndex >= 0 && 
                   d5List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d5List.get(tempIndex).getSlaveBallNumber());
                tempIndex--;
            }
            
            // 更新index为下一个不同系数的位置
            index = tempIndex;
            
            // 计算还需要多少个球
            int needFromGroup = Math.min(needCount - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                addedCount++;
            } else if (needFromGroup == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                }
                addedCount += sameCoefficientBalls.size();
        } else {
                // 需要从多个相同系数的球号中选择部分，处理毛边（向上使用高位策略）
                List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needFromGroup);
                for (Integer selectedBall : selectedBalls) {
                    result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                    addedCount++;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 从D5表平均值位置向下取指定数量的球号
     */
    private List<BallWithCoefficient> getLowerBallsFromAverageD5(List<D5> d5List, int avgPosition, int needCount, Integer masterBallNumber) {
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = avgPosition + 1; // 从平均值位置的下一个开始
        int addedCount = 0;
        
        // 从平均值向下遍历（使用低位策略的逻辑）
        while (addedCount < needCount && index < d5List.size()) {
            double currentCoefficient = d5List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号（向后收集）
            int tempIndex = index;
            while (tempIndex < d5List.size() && 
                   d5List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d5List.get(tempIndex).getSlaveBallNumber());
                tempIndex++;
            }
            
            // 更新index为下一个不同系数的位置
            index = tempIndex;
            
            // 计算还需要多少个球
            int needFromGroup = Math.min(needCount - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                addedCount++;
            } else if (needFromGroup == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                }
                addedCount += sameCoefficientBalls.size();
        } else {
                // 需要从多个相同系数的球号中选择部分，处理毛边（向下使用前区策略）
                List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needFromGroup);
                for (Integer selectedBall : selectedBalls) {
                    result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                    addedCount++;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 低位策略：从D5表中获取最小值向上第3-13位的11个球号
     */
    private List<BallWithCoefficient> getLowLevelBallsFromD5(Integer masterBallNumber) {
        List<D5> d5List = d5Mapper.selectList(
            new LambdaQueryWrapper<D5>()
                .eq(D5::getMasterBallNumber, masterBallNumber));
        if (CollectionUtils.isEmpty(d5List)) {
            log.warn("No D5 records found for master ball: {}", masterBallNumber);
            return new ArrayList<>();
        }
        
        // 按系数从大到小排序
        d5List.sort((d1, d2) -> d2.getCoefficient().compareTo(d1.getCoefficient()));
        
        // 从最小值开始，跳过前2个位置，取第3-13位共11个球号
        int minPosition = d5List.size() - 1;
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = minPosition;
        int positionCount = 1; // 当前位置计数
        int addedCount = 0;    // 已加入球号数量
        
        // 从最小值开始向上遍历
        while (addedCount < 11 && index >= 0) {
            double currentCoefficient = d5List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号（向前收集）
            int tempIndex = index;
            while (tempIndex >= 0 && 
                   d5List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d5List.get(tempIndex).getSlaveBallNumber());
                tempIndex--;
            }
            
            // 更新index为下一个不同系数的位置
            index = tempIndex;
            
            // 计算当前系数组占据的位置数
            int currentGroupPositions = sameCoefficientBalls.size();
            
            // 判断当前组是否在第3-13位范围内
            int groupStartPosition = positionCount;
            int groupEndPosition = positionCount + currentGroupPositions - 1;
            
            if (groupEndPosition < 3) {
                // 整个组都在第3位之前，跳过
                positionCount += currentGroupPositions;
                continue;
            }
            
            if (groupStartPosition > 13) {
                // 整个组都在第13位之后，结束
                break;
            }
            
            // 计算需要从当前组中选择多少个球号
            int validStartPosition = Math.max(groupStartPosition, 3);
            int validEndPosition = Math.min(groupEndPosition, 13);
            int needCount = validEndPosition - validStartPosition + 1;
            needCount = Math.min(needCount, 11 - addedCount);
            
            if (needCount > 0) {
                if (sameCoefficientBalls.size() == 1) {
                    // 只有一个球号，直接加入
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                    addedCount++;
                } else if (needCount == sameCoefficientBalls.size()) {
                    // 需要选择的数量等于可用数量，全部加入
                    for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                        result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                    }
                    addedCount += sameCoefficientBalls.size();
        } else {
                    // 需要从多个相同系数的球号中选择部分，处理毛边
                    List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needCount);
                    for (Integer selectedBall : selectedBalls) {
                        result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                        addedCount++;
                    }
                }
            }
            
            positionCount += currentGroupPositions;
        }
        
        return result;
    }
    
    /**
     * 从D9表中获取最大值向下的30个球号
     */
    private List<BallWithCoefficient> getTop30BallsFromD9(Integer masterBallNumber) {
        List<D9> d9List = d9Mapper.selectList(
            new LambdaQueryWrapper<D9>()
                .eq(D9::getMasterBallNumber, masterBallNumber));
        if (CollectionUtils.isEmpty(d9List)) {
            log.warn("No D9 records found for master ball: {}", masterBallNumber);
            return new ArrayList<>();
        }
        
        // 按系数从大到小排序
        d9List.sort((d1, d2) -> d2.getCoefficient().compareTo(d1.getCoefficient()));
        
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = 0;
        int addedCount = 0;
        
        while (addedCount < 30 && index < d9List.size()) {
            double currentCoefficient = d9List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号
            while (index < d9List.size() && 
                   d9List.get(index).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d9List.get(index).getSlaveBallNumber());
                index++;
            }
            
            // 计算还需要多少个球
            int needCount = Math.min(30 - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                addedCount++;
            } else if (needCount == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                }
                addedCount += sameCoefficientBalls.size();
            } else {
                // 需要从多个相同系数的球号中选择部分，处理毛边
                List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needCount);
                for (Integer selectedBall : selectedBalls) {
                    result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                    addedCount++;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 从D12表中获取最大值向下的30个球号
     */
    private List<BallWithCoefficient> getTop30BallsFromD12(Integer masterBallNumber) {
        List<D12> d12List = d12Mapper.selectList(
            new LambdaQueryWrapper<D12>()
                .eq(D12::getMasterBallNumber, masterBallNumber));
        if (CollectionUtils.isEmpty(d12List)) {
            log.warn("No D12 records found for master ball: {}", masterBallNumber);
            return new ArrayList<>();
        }
        
        // 按系数从大到小排序
        d12List.sort((d1, d2) -> d2.getCoefficient().compareTo(d1.getCoefficient()));
        
        List<BallWithCoefficient> result = new ArrayList<>();
        int index = 0;
        int addedCount = 0;
        
        while (addedCount < 30 && index < d12List.size()) {
            double currentCoefficient = d12List.get(index).getCoefficient();
            List<Integer> sameCoefficientBalls = new ArrayList<>();
            
            // 收集所有相同系数的球号
            while (index < d12List.size() && 
                   d12List.get(index).getCoefficient().equals(currentCoefficient)) {
                sameCoefficientBalls.add(d12List.get(index).getSlaveBallNumber());
                index++;
            }
            
            // 计算还需要多少个球
            int needCount = Math.min(30 - addedCount, sameCoefficientBalls.size());
            
            if (sameCoefficientBalls.size() == 1) {
                // 只有一个球号，直接加入
                result.add(new BallWithCoefficient(sameCoefficientBalls.get(0), currentCoefficient, masterBallNumber));
                addedCount++;
            } else if (needCount == sameCoefficientBalls.size()) {
                // 需要选择的数量等于可用数量，全部加入
                for (int i = 0; i < sameCoefficientBalls.size(); i++) {
                    result.add(new BallWithCoefficient(sameCoefficientBalls.get(i), currentCoefficient, masterBallNumber));
                }
                addedCount += sameCoefficientBalls.size();
            } else {
                // 需要从多个相同系数的球号中选择部分，处理毛边
                List<Integer> selectedBalls = handleMultipleBoundaryConflicts(sameCoefficientBalls, needCount);
                for (Integer selectedBall : selectedBalls) {
                    result.add(new BallWithCoefficient(selectedBall, currentCoefficient, masterBallNumber));
                    addedCount++;
                }
            }
        }
        
        return result;
    }

    /**
     * 获取历史排行表中平均值向上的3位
     */
    private List<Integer> getTop3FromHistoryTop() {
        List<DltFrontendHistoryTop> historyTopList = dltFrontendHistoryTopMapper.selectList(
            new LambdaQueryWrapper<DltFrontendHistoryTop>()
                .orderByDesc(DltFrontendHistoryTop::getActiveCoefficient));
        if (CollectionUtils.isEmpty(historyTopList)) {
            return new ArrayList<>();
        }
        
        // 计算平均系数
        double avgCoefficient = historyTopList.stream()
                                 .mapToDouble(DltFrontendHistoryTop::getActiveCoefficient)
                .average()
                .orElse(0.0);
        
        // 找出比平均值大且最接近平均值的球号位置
        int startIndex = -1;
        double minDiffAboveAvg = Double.MAX_VALUE;
        
        for (int i = historyTopList.size() - 1; i >= 0; i--) {
            double coefficient = historyTopList.get(i).getActiveCoefficient();
            if (coefficient > avgCoefficient) {
                double diff = coefficient - avgCoefficient;
                if (diff < minDiffAboveAvg) {
                    minDiffAboveAvg = diff;
                    startIndex = i;
                }
            }
        }
        
        List<Integer> result = new ArrayList<>();
        if (startIndex != -1) {
            // 从找到的位置向上取3个球号
            int endIndex = Math.max(0, startIndex - 2);
            for (int i = startIndex; i >= endIndex; i--) {
                result.add(historyTopList.get(i).getBallNumber());
            }
        }
        
        return result;
    }

    /**
     * 获取百期排行表中平均值向上的3位
     */
    private List<Integer> getTop3FromHistoryTop100() {
        List<DltFrontendHistoryTop100> historyTop100List = dltFrontendHistoryTop100Mapper.selectList(
            new LambdaQueryWrapper<DltFrontendHistoryTop100>()
                .orderByDesc(DltFrontendHistoryTop100::getActiveCoefficient));
        if (CollectionUtils.isEmpty(historyTop100List)) {
            return new ArrayList<>();
        }
        
        // 计算平均系数
        double avgCoefficient = historyTop100List.stream()
                                 .mapToDouble(DltFrontendHistoryTop100::getActiveCoefficient)
                .average()
                .orElse(0.0);
        
        // 找出比平均值大且差值最小的所有球号
        double minDiffAboveAvg = Double.MAX_VALUE;
        List<Integer> closestBalls = new ArrayList<>();
        
        for (DltFrontendHistoryTop100 ball : historyTop100List) {
            double coefficient = ball.getActiveCoefficient();
            if (coefficient > avgCoefficient) {
                double diff = coefficient - avgCoefficient;
                if (diff < minDiffAboveAvg) {
                    minDiffAboveAvg = diff;
                    closestBalls.clear();
                    closestBalls.add(ball.getBallNumber());
                } else if (diff == minDiffAboveAvg) {
                    closestBalls.add(ball.getBallNumber());
                }
            }
        }
        
        // 如果没有比平均值大的球号，返回空列表
        if (closestBalls.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 如果比平均值大且差值最小的球号数量 <= 3，直接返回
        if (closestBalls.size() <= 3) {
            return closestBalls;
        }
        
        // 如果比平均值大且差值最小的球号数量 > 3，通过dlt_frontend_history_all表筛选
        return selectTop3FromHistoryAll(closestBalls);
    }
    
    /**
     * 从dlt_frontend_history_all表中选择前3个球号
     */
    private List<Integer> selectTop3FromHistoryAll(List<Integer> candidateBalls) {
        // 获取候选球号在dlt_frontend_history_all表中的活跃系数
        Map<Integer, Double> ballCoefficientMap = new HashMap<>();
        for (Integer ballNumber : candidateBalls) {
            DltFrontendHistoryAll record = dltFrontendHistoryAllMapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryAll>()
                    .eq(DltFrontendHistoryAll::getBallNumber, ballNumber));
            double coefficient = (record != null) ? record.getActiveCoefficient() : 0.0;
            ballCoefficientMap.put(ballNumber, coefficient);
        }
        
        // 按活跃系数降序排序，选择前3个
        List<Map.Entry<Integer, Double>> sortedEntries = ballCoefficientMap.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .collect(Collectors.toList());
        
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < Math.min(3, sortedEntries.size()); i++) {
            result.add(sortedEntries.get(i).getKey());
        }
        
        return result;
    }
    
    /**
     * 处理多个边界冲突，选择指定数量的球号
     * @param candidateBalls 候选球号列表
     * @param selectCount 需要选择的数量
     * @return 选中的球号列表
     */
    private List<Integer> handleMultipleBoundaryConflicts(List<Integer> candidateBalls, int selectCount) {
        if (CollectionUtils.isEmpty(candidateBalls) || selectCount <= 0) {
            return new ArrayList<>();
        }
        
        if (selectCount >= candidateBalls.size()) {
            return new ArrayList<>(candidateBalls);
        }
        
        // 1. 先从dlt_frontend_history_top_100比较
        Map<Integer, Double> top100Coefficients = new HashMap<>();
        for (Integer ball : candidateBalls) {
            DltFrontendHistoryTop100 record = dltFrontendHistoryTop100Mapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryTop100>()
                    .eq(DltFrontendHistoryTop100::getBallNumber, ball));
            if (record != null) {
                top100Coefficients.put(ball, record.getActiveCoefficient());
                    } else {
                top100Coefficients.put(ball, 0.0);
            }
        }
        
        // 按系数降序排序
        List<Map.Entry<Integer, Double>> sortedByTop100 = top100Coefficients.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .collect(Collectors.toList());
        
        List<Integer> result = new ArrayList<>();
        
        // 按系数分组处理
        int currentIndex = 0;
        while (result.size() < selectCount && currentIndex < sortedByTop100.size()) {
            Double currentCoefficient = sortedByTop100.get(currentIndex).getValue();
            List<Integer> sameTop100CoefficientBalls = new ArrayList<>();
            
            // 收集相同系数的球号
            while (currentIndex < sortedByTop100.size() && 
                   sortedByTop100.get(currentIndex).getValue().equals(currentCoefficient)) {
                sameTop100CoefficientBalls.add(sortedByTop100.get(currentIndex).getKey());
                currentIndex++;
            }
            
            int needFromThisGroup = Math.min(selectCount - result.size(), sameTop100CoefficientBalls.size());
            
            if (sameTop100CoefficientBalls.size() == 1 || needFromThisGroup == sameTop100CoefficientBalls.size()) {
                // 只有一个球或者需要全部选择
                for (int i = 0; i < needFromThisGroup; i++) {
                    result.add(sameTop100CoefficientBalls.get(i));
                }
            } else {
                // 需要进一步筛选，使用dlt_frontend_history_top表
                List<Integer> selectedFromTop = selectFromHistoryTop(sameTop100CoefficientBalls, needFromThisGroup);
                result.addAll(selectedFromTop);
            }
        }
        
        return result;
    }
    
    /**
     * 从dlt_frontend_history_top表中选择指定数量的球号
     */
    private List<Integer> selectFromHistoryTop(List<Integer> candidateBalls, int selectCount) {
        if (CollectionUtils.isEmpty(candidateBalls) || selectCount <= 0) {
            return new ArrayList<>();
        }
        
        if (selectCount >= candidateBalls.size()) {
            return new ArrayList<>(candidateBalls);
        }
        
        // 获取在dlt_frontend_history_top表中的系数
        Map<Integer, Double> topCoefficients = new HashMap<>();
        for (Integer ball : candidateBalls) {
            DltFrontendHistoryTop record = dltFrontendHistoryTopMapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryTop>()
                    .eq(DltFrontendHistoryTop::getBallNumber, ball));
            if (record != null) {
                topCoefficients.put(ball, record.getActiveCoefficient());
            } else {
                topCoefficients.put(ball, 0.0);
            }
        }
        
        // 按系数降序排序，选择前selectCount个
        List<Map.Entry<Integer, Double>> sortedByTop = topCoefficients.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .collect(Collectors.toList());
        
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < Math.min(selectCount, sortedByTop.size()); i++) {
            result.add(sortedByTop.get(i).getKey());
        }
        
        // 如果仍然不够，按原始顺序补充
        while (result.size() < selectCount && result.size() < candidateBalls.size()) {
            for (Integer ball : candidateBalls) {
                if (!result.contains(ball) && result.size() < selectCount) {
                    result.add(ball);
                }
            }
        }
        
        return result;
    }
    
    /**
     * 处理边界冲突（毛边）
     */
    private Integer handleBoundaryConflicts(List<Integer> candidateBalls) {
        if (CollectionUtils.isEmpty(candidateBalls)) {
            return null;
        }
        
        if (candidateBalls.size() == 1) {
            return candidateBalls.get(0);
        }
        
        // 1. 先从dlt_frontend_history_top_100比较
        Map<Integer, Double> top100Coefficients = new HashMap<>();
        for (Integer ball : candidateBalls) {
            DltFrontendHistoryTop100 record = dltFrontendHistoryTop100Mapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryTop100>()
                    .eq(DltFrontendHistoryTop100::getBallNumber, ball));
            if (record != null) {
                                 top100Coefficients.put(ball, record.getActiveCoefficient());
            } else {
                top100Coefficients.put(ball, 0.0);
            }
        }
        
        // 找出系数最大的球
        Optional<Map.Entry<Integer, Double>> maxTop100Entry = top100Coefficients.entrySet().stream()
                .max(Map.Entry.comparingByValue());
        
        if (maxTop100Entry.isPresent()) {
            Double maxCoefficient = maxTop100Entry.get().getValue();
            List<Integer> maxCoefficientBalls = top100Coefficients.entrySet().stream()
                    .filter(e -> e.getValue().equals(maxCoefficient))
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
            
            if (maxCoefficientBalls.size() == 1) {
                return maxCoefficientBalls.get(0);
            }
            
            // 2. 如果仍有多个球系数相同，从dlt_frontend_history_top比较
            Map<Integer, Double> topCoefficients = new HashMap<>();
            for (Integer ball : maxCoefficientBalls) {
                DltFrontendHistoryTop record = dltFrontendHistoryTopMapper.selectOne(
                    new LambdaQueryWrapper<DltFrontendHistoryTop>()
                        .eq(DltFrontendHistoryTop::getBallNumber, ball));
                if (record != null) {
                                         topCoefficients.put(ball, record.getActiveCoefficient());
                } else {
                    topCoefficients.put(ball, 0.0);
                }
            }
            
            Optional<Map.Entry<Integer, Double>> maxTopEntry = topCoefficients.entrySet().stream()
                    .max(Map.Entry.comparingByValue());
            
            if (maxTopEntry.isPresent()) {
                Double maxTopCoefficient = maxTopEntry.get().getValue();
                List<Integer> maxTopCoefficientBalls = topCoefficients.entrySet().stream()
                        .filter(e -> e.getValue().equals(maxTopCoefficient))
                        .map(Map.Entry::getKey)
                        .collect(Collectors.toList());
                
                if (maxTopCoefficientBalls.size() == 1) {
                    return maxTopCoefficientBalls.get(0);
                }
            }
        }
        
        // 3. 如果仍无法区分，默认选择第一位
        return candidateBalls.get(0);
    }
    
    /**
     * 从所有候选球中筛选最终的12个球（带过程）
     * @param allCandidateBalls 所有候选球
     * @param d5CoefficientMap D5表中的系数信息
     * @return 最终选出的12个球和筛选过程
     */
    private FollowerBallPredictionResult selectFinal10BallsWithProcess(List<Integer> allCandidateBalls, Map<Integer, List<BallWithCoefficient>> d5CoefficientMap) {
        // 统计球号出现次数
        Map<Integer, Integer> ballFrequencyMap = new HashMap<>();
        for (Integer ball : allCandidateBalls) {
            ballFrequencyMap.put(ball, ballFrequencyMap.getOrDefault(ball, 0) + 1);
        }
        
        // 按频率分组
        Map<Integer, List<Integer>> frequencyGroups = new TreeMap<>((f1, f2) -> f2.compareTo(f1)); // 降序
        for (Map.Entry<Integer, Integer> entry : ballFrequencyMap.entrySet()) {
            frequencyGroups.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
        }
        
        StringBuilder processBuilder = new StringBuilder();
        List<Integer> resultBalls = new ArrayList<>();
        List<Integer> directSelected = new ArrayList<>();
        List<Integer> needFurtherSelection = new ArrayList<>();
        boolean hasSecondarySelection = false;
        String selectionSteps = "";
        String detailedCoefficientInfo = "";
        
        // 首先确定实际参与筛选的最低频率
        int currentSelected = 0;
        int minSelectedFrequency = 0;
        for (Map.Entry<Integer, List<Integer>> frequencyGroup : frequencyGroups.entrySet()) {
            int frequency = frequencyGroup.getKey();
            int ballsInGroup = frequencyGroup.getValue().size();
            
            if (currentSelected + ballsInGroup <= 12) {
                // 这个频率组的球全部入选
                currentSelected += ballsInGroup;
                minSelectedFrequency = frequency;
            } else {
                // 这个频率组只有部分球入选
                minSelectedFrequency = frequency;
                break;
            }
        }
        
        // 生成频率分布描述
        List<String> frequencyDescriptions = new ArrayList<>();
        for (Map.Entry<Integer, List<Integer>> frequencyGroup : frequencyGroups.entrySet()) {
            int frequency = frequencyGroup.getKey();
            if (frequency >= minSelectedFrequency) {
                List<Integer> ballsInGroup = new ArrayList<>(frequencyGroup.getValue());
                Collections.sort(ballsInGroup);
                String ballsStr = ballsInGroup.stream().map(String::valueOf).collect(Collectors.joining(", "));
                frequencyDescriptions.add(ballsStr + "（出现" + frequency + "次）");
            }
        }
        processBuilder.append("参与筛选的候选球号按频率分布为").append(String.join("，", frequencyDescriptions)).append("；");
        
        // 按频率从高到低处理每个频率组
        for (Map.Entry<Integer, List<Integer>> frequencyGroup : frequencyGroups.entrySet()) {
            if (resultBalls.size() >= 12) {
                break;
            }
            
            List<Integer> ballsInGroup = frequencyGroup.getValue();
            int needCount = Math.min(12 - resultBalls.size(), ballsInGroup.size());
            
            if (ballsInGroup.size() <= needCount) {
                // 如果这个频率组的球数量 <= 需要的数量，全部加入
                resultBalls.addAll(ballsInGroup);
                directSelected.addAll(ballsInGroup);
            } else {
                // 需要从这个频率组中选择部分球号，使用D5系数筛选
                List<Integer> selectedFromGroup = selectBallsByD5Coefficient(ballsInGroup, needCount, d5CoefficientMap);
                resultBalls.addAll(selectedFromGroup);
                needFurtherSelection.addAll(ballsInGroup);
                hasSecondarySelection = true;
                selectionSteps = "通过频率筛选确定部分球号，通过D5系数和筛选确定剩余球号，无需进行百期排位、历史排位";
                
                // 生成系数详情信息
                Map<Integer, Double> ballCoefficientSum = new HashMap<>();
                for (Integer ball : ballsInGroup) {
                List<BallWithCoefficient> coefficients = d5CoefficientMap.getOrDefault(ball, new ArrayList<>());
                    double sum = coefficients.stream().mapToDouble(BallWithCoefficient::getCoefficient).sum();
                ballCoefficientSum.put(ball, sum);
            }
            
                List<String> coefficientDetails = new ArrayList<>();
                for (Map.Entry<Integer, Double> entry : ballCoefficientSum.entrySet()) {
                    coefficientDetails.add(entry.getKey() + "（系数和" + String.format("%.2f", entry.getValue()) + "）");
                }
                Collections.sort(coefficientDetails);
                detailedCoefficientInfo = "D5系数和详情：" + String.join("，", coefficientDetails);
                
                break; // 只处理需要筛选的第一组
            }
        }
        
        // 生成筛选过程说明
        if (hasSecondarySelection) {
            processBuilder.append("无法直接筛选出前12个，其中");
            Collections.sort(directSelected);
            String directSelectedStr = directSelected.stream().map(String::valueOf).collect(Collectors.joining(", "));
            processBuilder.append(directSelectedStr).append("直接入选，");
            
            Collections.sort(needFurtherSelection);
            String needFurtherStr = needFurtherSelection.stream().map(String::valueOf).collect(Collectors.joining(", "));
            processBuilder.append(needFurtherStr).append("需要进行二次筛选，");
            
            List<Integer> finalSelected = new ArrayList<>(resultBalls);
            finalSelected.removeAll(directSelected);
            Collections.sort(finalSelected);
            String finalSelectedStr = finalSelected.stream().map(String::valueOf).collect(Collectors.joining(", "));
            processBuilder.append("最终筛选出").append(finalSelectedStr).append("，");
            
            String allResultStr = resultBalls.stream().map(String::valueOf).collect(Collectors.joining(", "));
            processBuilder.append("组成前12个球号：").append(allResultStr).append("。");
            
            processBuilder.append("筛选步骤：").append(selectionSteps).append("。");
            if (!detailedCoefficientInfo.isEmpty()) {
                processBuilder.append(" ").append(detailedCoefficientInfo).append("。");
            }
        } else {
            String allResultStr = resultBalls.stream().map(String::valueOf).collect(Collectors.joining(", "));
            processBuilder.append("直接筛选出前12个球号：").append(allResultStr).append("。");
        }
        
        // 无论是否有二次筛选，都要显示筛选步骤
        if (!hasSecondarySelection || selectionSteps.isEmpty()) {
            processBuilder.append("筛选步骤：通过频率筛选确定所有球号，无需进行D5系数筛选、百期排位、历史排位。");
        }
        
        return new FollowerBallPredictionResult(resultBalls, processBuilder.toString());
    }
    
    /**
     * 从所有候选球中筛选最终的10个球
     * @param allCandidateBalls 所有候选球
     * @param d5CoefficientMap D5表中的系数信息
     * @return 最终选出的10个球
     */
    private List<Integer> selectFinal10Balls(List<Integer> allCandidateBalls, Map<Integer, List<BallWithCoefficient>> d5CoefficientMap) {
        // 统计球号出现次数
        Map<Integer, Integer> ballFrequencyMap = new HashMap<>();
        for (Integer ball : allCandidateBalls) {
            ballFrequencyMap.put(ball, ballFrequencyMap.getOrDefault(ball, 0) + 1);
        }
        
        // 按频率分组
        Map<Integer, List<Integer>> frequencyGroups = new TreeMap<>((f1, f2) -> f2.compareTo(f1)); // 降序
        for (Map.Entry<Integer, Integer> entry : ballFrequencyMap.entrySet()) {
            frequencyGroups.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
        }
        
        List<Integer> resultBalls = new ArrayList<>();
        
        // 按频率从高到低处理每个频率组
        for (Map.Entry<Integer, List<Integer>> frequencyGroup : frequencyGroups.entrySet()) {
                if (resultBalls.size() >= 10) {
                    break;
                }
                
            List<Integer> ballsInGroup = frequencyGroup.getValue();
            int needCount = Math.min(10 - resultBalls.size(), ballsInGroup.size());
            
            if (ballsInGroup.size() <= needCount) {
                // 如果这个频率组的球数量 <= 需要的数量，全部加入
                resultBalls.addAll(ballsInGroup);
            } else {
                // 需要从这个频率组中选择部分球号，使用D5系数筛选
                List<Integer> selectedFromGroup = selectBallsByD5Coefficient(ballsInGroup, needCount, d5CoefficientMap);
                resultBalls.addAll(selectedFromGroup);
            }
        }
        
        return resultBalls;
    }
    
    /**
     * 根据D5系数从候选球中选择指定数量的球号
     */
    private List<Integer> selectBallsByD5Coefficient(List<Integer> candidateBalls, int needCount, Map<Integer, List<BallWithCoefficient>> d5CoefficientMap) {
        // 计算每个球号的D5系数和
        Map<Integer, Double> ballCoefficientSum = new HashMap<>();
        for (Integer ball : candidateBalls) {
            List<BallWithCoefficient> coefficients = d5CoefficientMap.getOrDefault(ball, new ArrayList<>());
            double sum = coefficients.stream()
                    .mapToDouble(BallWithCoefficient::getCoefficient)
                    .sum();
            ballCoefficientSum.put(ball, sum);
        }
        
        // 按D5系数分组
        Map<Double, List<Integer>> coefficientGroups = new TreeMap<>((c1, c2) -> c2.compareTo(c1)); // 降序
        for (Map.Entry<Integer, Double> entry : ballCoefficientSum.entrySet()) {
            coefficientGroups.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
        }
        
        List<Integer> result = new ArrayList<>();
        
        // 按系数从高到低处理每个系数组
        for (Map.Entry<Double, List<Integer>> coefficientGroup : coefficientGroups.entrySet()) {
            if (result.size() >= needCount) {
                    break;
                }
                
            List<Integer> ballsInGroup = coefficientGroup.getValue();
            int needFromThisGroup = Math.min(needCount - result.size(), ballsInGroup.size());
            
            if (ballsInGroup.size() <= needFromThisGroup) {
                // 如果这个系数组的球数量 <= 需要的数量，全部加入
                result.addAll(ballsInGroup);
            } else {
                // 需要从这个系数组中选择部分球号，使用历史排行筛选
                List<Integer> selectedFromGroup = selectBallsByHistoryRanking(ballsInGroup, needFromThisGroup);
                result.addAll(selectedFromGroup);
            }
        }
        
        return result;
    }
    
    /**
     * 根据历史排行从候选球中选择指定数量的球号
     */
    private List<Integer> selectBallsByHistoryRanking(List<Integer> candidateBalls, int needCount) {
        if (candidateBalls.size() <= needCount) {
            return new ArrayList<>(candidateBalls);
        }
        
        // 先尝试百期排行筛选
        Map<Integer, Double> top100Rankings = getHistoryTop100Rankings(candidateBalls);
        List<Integer> result = selectTopBallsByRanking(top100Rankings, needCount);
        
        // 如果百期排行筛选后仍有相同系数的球号，使用历史排行进一步筛选
        if (result.size() < needCount) {
            List<Integer> remaining = new ArrayList<>(candidateBalls);
            remaining.removeAll(result);
            
            Map<Integer, Double> topRankings = getHistoryTopRankings(remaining);
            List<Integer> additionalBalls = selectTopBallsByRanking(topRankings, needCount - result.size());
            result.addAll(additionalBalls);
        }
        
        return result;
    }
    
    /**
     * 根据系数排序选择指定数量的球号
     */
    private List<Integer> selectTopBallsByRanking(Map<Integer, Double> rankings, int needCount) {
        List<Map.Entry<Integer, Double>> sortedEntries = rankings.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .collect(Collectors.toList());
        
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < Math.min(needCount, sortedEntries.size()); i++) {
            result.add(sortedEntries.get(i).getKey());
        }
        
        return result;
    }

    /**
     * 获取球号在百期排行表中的系数
     */
    private Map<Integer, Double> getHistoryTop100Rankings(List<Integer> balls) {
        Map<Integer, Double> result = new HashMap<>();
        for (Integer ball : balls) {
            DltFrontendHistoryTop100 record = dltFrontendHistoryTop100Mapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryTop100>()
                    .eq(DltFrontendHistoryTop100::getBallNumber, ball));
                         result.put(ball, record != null ? record.getActiveCoefficient() : 0.0);
        }
        return result;
    }

    /**
     * 获取球号在历史排行表中的系数
     */
    private Map<Integer, Double> getHistoryTopRankings(List<Integer> balls) {
        Map<Integer, Double> result = new HashMap<>();
        for (Integer ball : balls) {
            DltFrontendHistoryTop record = dltFrontendHistoryTopMapper.selectOne(
                new LambdaQueryWrapper<DltFrontendHistoryTop>()
                    .eq(DltFrontendHistoryTop::getBallNumber, ball));
                         result.put(ball, record != null ? record.getActiveCoefficient() : 0.0);
        }
        return result;
    }

    /**
     * 验证输入参数
     */
    private void validateInputParams(String level, List<Integer> wellRegardedBalls, List<Integer> previousFrontBalls, List<Integer> previousBackBalls) {
        if (!"high".equalsIgnoreCase(level) && !"middle".equalsIgnoreCase(level) && !"low".equalsIgnoreCase(level)) {
            throw new IllegalArgumentException("位置级别必须是high/middle/low之一");
        }
        
        if (CollectionUtils.isEmpty(wellRegardedBalls) || wellRegardedBalls.size() != 4) {
            throw new IllegalArgumentException("看好的号码必须为4个");
        }
        
        if (CollectionUtils.isEmpty(previousFrontBalls) || previousFrontBalls.size() != 5) {
            throw new IllegalArgumentException("上期前区号码必须为5个");
        }
        
        if (CollectionUtils.isEmpty(previousBackBalls) || previousBackBalls.size() != 2) {
            throw new IllegalArgumentException("上期后区号码必须为2个");
        }
        
        for (Integer frontBall : wellRegardedBalls) {
            if (frontBall < 1 || frontBall > 35) {
                throw new IllegalArgumentException("前区号码范围应为1-35");
            }
        }
        
        for (Integer frontBall : previousFrontBalls) {
            if (frontBall < 1 || frontBall > 35) {
                throw new IllegalArgumentException("前区号码范围应为1-35");
            }
        }
        
        for (Integer backBall : previousBackBalls) {
            if (backBall < 1 || backBall > 12) {
                throw new IllegalArgumentException("后区号码范围应为1-12");
            }
        }
    }
}