Files
cpzs-backend/src/main/java/com/xy/xyaicpzs/dlt/FirstBallPredictor.java
2025-11-04 17:18:21 +08:00

1355 lines
60 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 FirstBallPredictor {
@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 FirstBallPredictionResult {
private List<Integer> result;
private String filteringProcess;
public FirstBallPredictionResult(List<Integer> result, String filteringProcess) {
this.result = result;
this.filteringProcess = filteringProcess;
}
}
/**
* 首球预测主方法(带筛选过程)
* @param level 位置级别high/middle/low
* @param redBalls 前区号码
* @param blueBalls 后区号码
* @return 预测结果和筛选过程
*/
public FirstBallPredictionResult predictFirstBallWithProcess(String level, List<Integer> redBalls, List<Integer> blueBalls) {
// 参数验证
validateInputParams(level, redBalls, blueBalls);
// 根据不同级别处理
Map<Integer, List<BallWithCoefficient>> ballWithCoefficientMap = new HashMap<>();
List<Integer> allCandidateBalls = new ArrayList<>();
// Step 1: 根据5个前区号码获取候选球
for (Integer redBall : redBalls) {
List<BallWithCoefficient> ballsWithCoefficients;
if ("high".equalsIgnoreCase(level)) {
ballsWithCoefficients = getHighLevelBallsWithCoefficients(redBall);
} else if ("middle".equalsIgnoreCase(level)) {
ballsWithCoefficients = getMiddleLevelBallsWithCoefficients(redBall);
} else { // low
ballsWithCoefficients = getLowLevelBallsWithCoefficients(redBall);
}
for (BallWithCoefficient ball : ballsWithCoefficients) {
ballWithCoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
allCandidateBalls.add(ball.getBallNumber());
}
}
// Step 2: 从历史排行表获取前3个
List<Integer> top3HistoryTop = getTop3FromHistoryTop();
allCandidateBalls.addAll(top3HistoryTop);
// Step 3: 从百期排行表获取前3个
List<Integer> top3HistoryTop100 = getTop3FromHistoryTop100();
allCandidateBalls.addAll(top3HistoryTop100);
// Step 4: 从后区号码获取候选球
for (Integer blueBall : blueBalls) {
List<BallWithCoefficient> blueballsWithCoefficients = getTop17FromD12WithCoefficients(blueBall, level);
for (BallWithCoefficient ball : blueballsWithCoefficients) {
allCandidateBalls.add(ball.getBallNumber());
}
}
// 最终筛选12个球
return selectFinal12Balls(allCandidateBalls, ballWithCoefficientMap);
}
/**
* 首球预测主方法(原版本,保持兼容性)
* @param level 位置级别high/middle/low
* @param redBalls 前区号码
* @param blueBalls 后区号码
* @return 预测的12个首球号码
*/
public List<Integer> predictFirstBall(String level, List<Integer> redBalls, List<Integer> blueBalls) {
// 参数验证
validateInputParams(level, redBalls, blueBalls);
// 根据不同级别处理
List<Integer> result;
Map<Integer, List<BallWithCoefficient>> ballWithCoefficientMap = new HashMap<>();
List<Integer> allCandidateBalls = new ArrayList<>();
// Step 1: 根据5个前区号码获取候选球
for (Integer redBall : redBalls) {
List<BallWithCoefficient> ballsWithCoefficients;
if ("high".equalsIgnoreCase(level)) {
ballsWithCoefficients = getHighLevelBallsWithCoefficients(redBall);
} else if ("middle".equalsIgnoreCase(level)) {
ballsWithCoefficients = getMiddleLevelBallsWithCoefficients(redBall);
} else { // low
ballsWithCoefficients = getLowLevelBallsWithCoefficients(redBall);
}
for (BallWithCoefficient ball : ballsWithCoefficients) {
ballWithCoefficientMap.computeIfAbsent(ball.getBallNumber(), k -> new ArrayList<>()).add(ball);
allCandidateBalls.add(ball.getBallNumber());
}
}
// Step 2: 从历史排行表获取前3个
List<Integer> top3HistoryTop = getTop3FromHistoryTop();
allCandidateBalls.addAll(top3HistoryTop);
// Step 3: 从百期排行表获取前3个
List<Integer> top3HistoryTop100 = getTop3FromHistoryTop100();
allCandidateBalls.addAll(top3HistoryTop100);
// Step 4: 从后区号码获取候选球
for (Integer blueBall : blueBalls) {
List<BallWithCoefficient> blueballsWithCoefficients = getTop17FromD12WithCoefficients(blueBall, level);
for (BallWithCoefficient ball : blueballsWithCoefficients) {
allCandidateBalls.add(ball.getBallNumber());
}
}
// 最终筛选12个球
FirstBallPredictionResult predictionResult = selectFinal12Balls(allCandidateBalls, ballWithCoefficientMap);
result = predictionResult.getResult();
return result;
}
/**
* 高位策略获取D9表中系数最大的前17位球号
*/
private List<BallWithCoefficient> getHighLevelBallsWithCoefficients(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 < 17 && 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(17 - 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;
}
/**
* 中位策略获取D9表中平均值附近的17个球号
*/
private List<BallWithCoefficient> getMiddleLevelBallsWithCoefficients(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()));
// 计算平均系数
double avgCoefficient = d9List.stream()
.mapToDouble(D9::getCoefficient)
.average()
.orElse(0.0);
// 找到比平均值大且最接近平均值的位置(从下到上遍历)
int avgPosition = -1;
for (int i = d9List.size() - 1; i >= 0; i--) {
double diff = d9List.get(i).getCoefficient() - avgCoefficient;
if (diff >= 0) {
avgPosition = i;
break; // 找到第一个比平均值大的位置就停止
}
}
// 如果没找到大于平均值的系数,取第一个
if (avgPosition == -1) {
avgPosition = 0;
}
List<BallWithCoefficient> result = new ArrayList<>();
// 先加入平均值位置的球号
result.add(new BallWithCoefficient(d9List.get(avgPosition).getSlaveBallNumber(),
d9List.get(avgPosition).getCoefficient(), masterBallNumber));
// 向上取8个球号使用高位策略的毛边处理逻辑
List<BallWithCoefficient> upperBalls = getUpperBallsFromAverage(d9List, avgPosition, 8, masterBallNumber);
result.addAll(upperBalls);
// 向下取8个球号使用低位策略的毛边处理逻辑
List<BallWithCoefficient> lowerBalls = getLowerBallsFromAverage(d9List, avgPosition, 8, masterBallNumber);
result.addAll(lowerBalls);
return result;
}
/**
* 从平均值位置向上取指定数量的球号
*/
private List<BallWithCoefficient> getUpperBallsFromAverage(List<D9> d9List, 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 = d9List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向前收集)
int tempIndex = index;
while (tempIndex >= 0 &&
d9List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d9List.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;
}
/**
* 从平均值位置向下取指定数量的球号
*/
private List<BallWithCoefficient> getLowerBallsFromAverage(List<D9> d9List, int avgPosition, int needCount, Integer masterBallNumber) {
List<BallWithCoefficient> result = new ArrayList<>();
int index = avgPosition + 1; // 从平均值位置的下一个开始
int addedCount = 0;
// 从平均值向下遍历(使用低位策略的逻辑)
while (addedCount < needCount && index < d9List.size()) {
double currentCoefficient = d9List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向后收集)
int tempIndex = index;
while (tempIndex < d9List.size() &&
d9List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d9List.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;
}
/**
* 低位策略获取D9表中最小值向上17个球号
*/
private List<BallWithCoefficient> getLowLevelBallsWithCoefficients(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()));
// 找到最小值的位置
int minPosition = d9List.size() - 1;
List<BallWithCoefficient> result = new ArrayList<>();
int index = minPosition;
int addedCount = 0;
// 从最小值开始向上遍历
while (addedCount < 17 && index >= 0) {
double currentCoefficient = d9List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向前收集)
int tempIndex = index;
while (tempIndex >= 0 &&
d9List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d9List.get(tempIndex).getSlaveBallNumber());
tempIndex--;
}
// 更新index为下一个不同系数的位置
index = tempIndex;
// 计算还需要多少个球
int needCount = Math.min(17 - 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表获取前17位球号
*/
private List<BallWithCoefficient> getTop17FromD12WithCoefficients(Integer masterBallNumber, String level) {
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<>();
if ("high".equalsIgnoreCase(level)) {
// 高位取系数最大的前17位
int index = 0;
int addedCount = 0;
while (addedCount < 17 && 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(17 - 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++;
}
}
}
} else if ("middle".equalsIgnoreCase(level)) {
// 中位计算平均值取其附近的17个球
double avgCoefficient = d12List.stream()
.mapToDouble(D12::getCoefficient)
.average()
.orElse(0.0);
// 找到比平均值大且最接近平均值的位置(从下到上遍历)
int avgPosition = -1;
for (int i = d12List.size() - 1; i >= 0; i--) {
double diff = d12List.get(i).getCoefficient() - avgCoefficient;
if (diff >= 0) {
avgPosition = i;
break; // 找到第一个比平均值大的位置就停止
}
}
// 如果没找到大于平均值的系数,取第一个
if (avgPosition == -1) {
avgPosition = 0;
}
// 先加入平均值位置的球号
result.add(new BallWithCoefficient(d12List.get(avgPosition).getSlaveBallNumber(),
d12List.get(avgPosition).getCoefficient(), masterBallNumber));
// 向上取8个球号使用高位策略的毛边处理逻辑
List<BallWithCoefficient> upperBalls = getUpperBallsFromAverageD12(d12List, avgPosition, 8, masterBallNumber);
result.addAll(upperBalls);
// 向下取8个球号使用低位策略的毛边处理逻辑
List<BallWithCoefficient> lowerBalls = getLowerBallsFromAverageD12(d12List, avgPosition, 8, masterBallNumber);
result.addAll(lowerBalls);
} else { // low
// 低位取最小值向上的17个球
int minPosition = d12List.size() - 1;
int index = minPosition;
int addedCount = 0;
// 从最小值开始向上遍历
while (addedCount < 17 && index >= 0) {
double currentCoefficient = d12List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向前收集)
int tempIndex = index;
while (tempIndex >= 0 &&
d12List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d12List.get(tempIndex).getSlaveBallNumber());
tempIndex--;
}
// 更新index为下一个不同系数的位置
index = tempIndex;
// 计算还需要多少个球
int needCount = Math.min(17 - 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表平均值位置向上取指定数量的球号
*/
private List<BallWithCoefficient> getUpperBallsFromAverageD12(List<D12> d12List, 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 = d12List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向前收集)
int tempIndex = index;
while (tempIndex >= 0 &&
d12List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d12List.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;
}
/**
* 从D12表平均值位置向下取指定数量的球号
*/
private List<BallWithCoefficient> getLowerBallsFromAverageD12(List<D12> d12List, int avgPosition, int needCount, Integer masterBallNumber) {
List<BallWithCoefficient> result = new ArrayList<>();
int index = avgPosition + 1; // 从平均值位置的下一个开始
int addedCount = 0;
// 从平均值向下遍历(使用低位策略的逻辑)
while (addedCount < needCount && index < d12List.size()) {
double currentCoefficient = d12List.get(index).getCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号(向后收集)
int tempIndex = index;
while (tempIndex < d12List.size() &&
d12List.get(tempIndex).getCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(d12List.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;
}
/**
* 获取历史排行表中系数最大的前3位
*/
private List<Integer> getTop3FromHistoryTop() {
List<DltFrontendHistoryTop> historyTopList = dltFrontendHistoryTopMapper.selectList(
new LambdaQueryWrapper<DltFrontendHistoryTop>()
.orderByDesc(DltFrontendHistoryTop::getActiveCoefficient));
if (CollectionUtils.isEmpty(historyTopList)) {
return new ArrayList<>();
}
List<Integer> result = new ArrayList<>();
int size = Math.min(historyTopList.size(), 3);
for (int i = 0; i < size; 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<>();
}
// 取前3位
List<Integer> top3Balls = new ArrayList<>();
int count = 0;
int index = 0;
while (count < 3 && index < historyTop100List.size()) {
double currentCoefficient = historyTop100List.get(index).getActiveCoefficient();
List<Integer> sameCoefficientBalls = new ArrayList<>();
// 收集所有相同系数的球号
while (index < historyTop100List.size() &&
historyTop100List.get(index).getActiveCoefficient().equals(currentCoefficient)) {
sameCoefficientBalls.add(historyTop100List.get(index).getBallNumber());
index++;
}
// 根据需要选择的数量和当前可用数量处理
int needCount = Math.min(3 - count, sameCoefficientBalls.size());
if (sameCoefficientBalls.size() == 1) {
// 只有一个球号,直接加入
top3Balls.add(sameCoefficientBalls.get(0));
count++;
} else if (needCount == sameCoefficientBalls.size()) {
// 需要选择的数量等于可用数量,全部加入
top3Balls.addAll(sameCoefficientBalls);
count += needCount;
} else {
// 需要从多个相同系数的球号中选择部分使用dlt_frontend_history_all表比较
List<Integer> selectedBalls = selectBallsFromHistoryAll(sameCoefficientBalls, needCount);
top3Balls.addAll(selectedBalls);
count += selectedBalls.size();
}
}
return top3Balls;
}
/**
* 从dlt_frontend_history_all表中根据活跃系数选择指定数量的球号
* @param candidateBalls 候选球号列表
* @param selectCount 需要选择的数量
* @return 选中的球号列表
*/
private List<Integer> selectBallsFromHistoryAll(List<Integer> candidateBalls, int selectCount) {
if (CollectionUtils.isEmpty(candidateBalls) || selectCount <= 0) {
return new ArrayList<>();
}
// 获取所有候选球号在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);
}
// 按活跃系数降序排序
List<Map.Entry<Integer, Double>> sortedEntries = ballCoefficientMap.entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.collect(Collectors.toList());
// 选择前selectCount个球号
List<Integer> result = new ArrayList<>();
for (int i = 0; i < Math.min(selectCount, 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 ballWithCoefficientMap 球号对应的系数信息
* @return 最终选出的12个球和筛选过程
*/
private FirstBallPredictionResult selectFinal12Balls(List<Integer> allCandidateBalls, Map<Integer, List<BallWithCoefficient>> ballWithCoefficientMap) {
StringBuilder processBuilder = new StringBuilder();
// 统计球号出现次数
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<>((a, b) -> b.compareTo(a)); // 按频率降序
for (Map.Entry<Integer, Integer> entry : ballFrequencyMap.entrySet()) {
int ball = entry.getKey();
int frequency = entry.getValue();
frequencyGroups.computeIfAbsent(frequency, k -> new ArrayList<>()).add(ball);
}
// 预先确定最低筛选频率(即实际参与筛选的最低频率)
int minSelectedFrequency = Integer.MAX_VALUE;
int tempSelected = 0;
for (Map.Entry<Integer, List<Integer>> entry : frequencyGroups.entrySet()) {
int frequency = entry.getKey();
List<Integer> balls = entry.getValue();
if (tempSelected + balls.size() <= 12) {
// 这个频率组会全部被选中
minSelectedFrequency = Math.min(minSelectedFrequency, frequency);
tempSelected += balls.size();
} else {
// 这个频率组需要部分选择,说明这是最后一个参与筛选的频率组
minSelectedFrequency = Math.min(minSelectedFrequency, frequency);
break;
}
}
// 生成频率分布说明(只显示实际参与筛选的球号)
processBuilder.append("参与筛选的候选球号按频率分布为");
List<String> frequencyDescriptions = new ArrayList<>();
// 只显示频率大于等于最低筛选频率的球号
for (Map.Entry<Integer, List<Integer>> entry : frequencyGroups.entrySet()) {
int frequency = entry.getKey();
if (frequency >= minSelectedFrequency) {
List<Integer> balls = entry.getValue();
Collections.sort(balls); // 排序显示
if (balls.size() == 1) {
frequencyDescriptions.add(balls.get(0) + "(出现" + frequency + "次)");
} else {
String ballsStr = balls.stream().map(String::valueOf).collect(Collectors.joining(", "));
frequencyDescriptions.add(ballsStr + "(出现" + frequency + "次)");
}
}
}
processBuilder.append(String.join("", frequencyDescriptions));
processBuilder.append("");
List<Integer> resultBalls = new ArrayList<>();
List<Integer> directSelected = new ArrayList<>();
List<Integer> needFurtherSelection = new ArrayList<>();
boolean hasSecondarySelection = false;
String selectionSteps = "";
String detailedCoefficientInfo = "";
// 逐个处理每个频率组
for (Map.Entry<Integer, List<Integer>> frequencyGroup : frequencyGroups.entrySet()) {
List<Integer> ballsInGroup = frequencyGroup.getValue();
int remainingNeeded = 12 - resultBalls.size();
if (remainingNeeded <= 0) {
break;
}
if (ballsInGroup.size() <= remainingNeeded) {
// 组内球数小于等于剩余需要数,全部加入
resultBalls.addAll(ballsInGroup);
directSelected.addAll(ballsInGroup);
} else {
// 组内球数大于剩余需要数,需要筛选
hasSecondarySelection = true;
needFurtherSelection.addAll(ballsInGroup);
// 进行D9系数筛选
D9SelectionResult d9Result = selectBallsByD9CoefficientWithProcess(ballsInGroup, ballWithCoefficientMap, remainingNeeded);
resultBalls.addAll(d9Result.selectedBalls);
selectionSteps = d9Result.stepDescription;
detailedCoefficientInfo = d9Result.detailedInfo;
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("筛选步骤通过频率筛选确定所有球号无需进行D9系数筛选、百期排位、历史排位。");
}
return new FirstBallPredictionResult(resultBalls, processBuilder.toString());
}
/**
* D9系数筛选结果类
*/
@Data
private static class D9SelectionResult {
private List<Integer> selectedBalls;
private String stepDescription;
private String detailedInfo;
public D9SelectionResult(List<Integer> selectedBalls, String stepDescription, String detailedInfo) {
this.selectedBalls = selectedBalls;
this.stepDescription = stepDescription;
this.detailedInfo = detailedInfo;
}
}
/**
* 根据D9系数筛选球号带过程记录
*/
private D9SelectionResult selectBallsByD9CoefficientWithProcess(List<Integer> candidateBalls, Map<Integer, List<BallWithCoefficient>> ballWithCoefficientMap, int needCount) {
// 计算每个球的D9系数和
Map<Integer, Double> ballCoefficientSum = new HashMap<>();
for (Integer ball : candidateBalls) {
List<BallWithCoefficient> coefficients = ballWithCoefficientMap.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);
String detailedInfo = "T3系数和详情" + String.join("", coefficientDetails);
// 按D9系数分组
Map<Double, List<Integer>> coefficientGroups = new TreeMap<>((a, b) -> b.compareTo(a)); // 降序
for (Map.Entry<Integer, Double> entry : ballCoefficientSum.entrySet()) {
double coefficient = entry.getValue();
int ball = entry.getKey();
coefficientGroups.computeIfAbsent(coefficient, k -> new ArrayList<>()).add(ball);
}
List<Integer> result = new ArrayList<>();
String stepDescription = "";
boolean usedHistoryRanking = false;
// 逐个处理每个系数组
for (Map.Entry<Double, List<Integer>> coefficientGroup : coefficientGroups.entrySet()) {
List<Integer> ballsInGroup = coefficientGroup.getValue();
int remainingNeeded = needCount - result.size();
if (remainingNeeded <= 0) {
break;
}
if (ballsInGroup.size() <= remainingNeeded) {
// 组内球数小于等于剩余需要数,全部加入
result.addAll(ballsInGroup);
} else {
// 组内球数大于剩余需要数,按百期排行筛选
List<Integer> selectedFromGroup = selectBallsByHistoryRanking(ballsInGroup, remainingNeeded);
result.addAll(selectedFromGroup);
usedHistoryRanking = true;
break;
}
}
if (usedHistoryRanking) {
stepDescription = "通过频率筛选确定部分球号通过D9系数和筛选确定剩余球号需要进行百期排位、历史排位";
} else {
stepDescription = "通过频率筛选确定部分球号通过D9系数和筛选确定剩余球号无需进行百期排位、历史排位";
}
return new D9SelectionResult(result, stepDescription, detailedInfo);
}
/**
* 根据D9系数筛选球号原版本保持兼容
*/
private List<Integer> selectBallsByD9Coefficient(List<Integer> candidateBalls, Map<Integer, List<BallWithCoefficient>> ballWithCoefficientMap, int needCount) {
// 计算每个球的D9系数和
Map<Integer, Double> ballCoefficientSum = new HashMap<>();
for (Integer ball : candidateBalls) {
List<BallWithCoefficient> coefficients = ballWithCoefficientMap.getOrDefault(ball, new ArrayList<>());
double sum = coefficients.stream()
.mapToDouble(BallWithCoefficient::getCoefficient)
.sum();
ballCoefficientSum.put(ball, sum);
}
// 按D9系数分组
Map<Double, List<Integer>> coefficientGroups = new TreeMap<>((a, b) -> b.compareTo(a)); // 降序
for (Map.Entry<Integer, Double> entry : ballCoefficientSum.entrySet()) {
double coefficient = entry.getValue();
int ball = entry.getKey();
coefficientGroups.computeIfAbsent(coefficient, k -> new ArrayList<>()).add(ball);
}
List<Integer> result = new ArrayList<>();
// 逐个处理每个系数组
for (Map.Entry<Double, List<Integer>> coefficientGroup : coefficientGroups.entrySet()) {
List<Integer> ballsInGroup = coefficientGroup.getValue();
int remainingNeeded = needCount - result.size();
if (remainingNeeded <= 0) {
break;
}
if (ballsInGroup.size() <= remainingNeeded) {
// 组内球数小于等于剩余需要数,全部加入
result.addAll(ballsInGroup);
} else {
// 组内球数大于剩余需要数,按百期排行筛选
List<Integer> selectedFromGroup = selectBallsByHistoryRanking(ballsInGroup, remainingNeeded);
result.addAll(selectedFromGroup);
}
}
return result;
}
/**
* 根据历史排行筛选球号
*/
private List<Integer> selectBallsByHistoryRanking(List<Integer> candidateBalls, int needCount) {
// 先按百期排行筛选
Map<Integer, Double> top100Rankings = getHistoryTop100Rankings(candidateBalls);
// 按百期排行分组
Map<Double, List<Integer>> top100Groups = new TreeMap<>((a, b) -> b.compareTo(a)); // 降序
for (Map.Entry<Integer, Double> entry : top100Rankings.entrySet()) {
double ranking = entry.getValue();
int ball = entry.getKey();
top100Groups.computeIfAbsent(ranking, k -> new ArrayList<>()).add(ball);
}
List<Integer> result = new ArrayList<>();
// 逐个处理每个百期排行组
for (Map.Entry<Double, List<Integer>> rankingGroup : top100Groups.entrySet()) {
List<Integer> ballsInGroup = rankingGroup.getValue();
int remainingNeeded = needCount - result.size();
if (remainingNeeded <= 0) {
break;
}
if (ballsInGroup.size() <= remainingNeeded) {
// 组内球数小于等于剩余需要数,全部加入
result.addAll(ballsInGroup);
} else {
// 组内球数大于剩余需要数,按历史排行筛选
List<Integer> selectedFromGroup = selectTopBallsByRanking(ballsInGroup, remainingNeeded);
result.addAll(selectedFromGroup);
}
}
return result;
}
/**
* 根据历史排行筛选最优球号
*/
private List<Integer> selectTopBallsByRanking(List<Integer> candidateBalls, int needCount) {
Map<Integer, Double> topRankings = getHistoryTopRankings(candidateBalls);
return topRankings.entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.limit(needCount)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
/**
* 获取球号在百期排行表中的系数
*/
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> redBalls, List<Integer> blueBalls) {
if (!"high".equalsIgnoreCase(level) && !"middle".equalsIgnoreCase(level) && !"low".equalsIgnoreCase(level)) {
throw new IllegalArgumentException("位置级别必须是high/middle/low之一");
}
if (CollectionUtils.isEmpty(redBalls) || redBalls.size() != 5) {
throw new IllegalArgumentException("前区号码必须为5个");
}
if (CollectionUtils.isEmpty(blueBalls) || blueBalls.size() != 2) {
throw new IllegalArgumentException("后区号码必须为2个");
}
for (Integer redBall : redBalls) {
if (redBall < 1 || redBall > 35) {
throw new IllegalArgumentException("前区号码范围应为1-35");
}
}
for (Integer blueBall : blueBalls) {
if (blueBall < 1 || blueBall > 12) {
throw new IllegalArgumentException("后区号码范围应为1-12");
}
}
}
}