package com.xy.xyaicpzs.service.impl; import com.xy.xyaicpzs.domain.entity.DltDrawRecord; import com.xy.xyaicpzs.domain.entity.D5; import com.xy.xyaicpzs.domain.entity.D6; import com.xy.xyaicpzs.domain.entity.D7; import com.xy.xyaicpzs.domain.entity.D8; import com.xy.xyaicpzs.domain.vo.BallCombinationAnalysisVO; import com.xy.xyaicpzs.service.DltCombinationAnalysisService; import com.xy.xyaicpzs.service.DltDrawRecordService; import com.xy.xyaicpzs.service.D5Service; import com.xy.xyaicpzs.service.D6Service; import com.xy.xyaicpzs.service.D7Service; import com.xy.xyaicpzs.service.D8Service; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Comparator; import java.util.List; import java.util.function.Function; /** * 大乐透组合分析服务实现类 */ @Slf4j @Service public class DltCombinationAnalysisServiceImpl implements DltCombinationAnalysisService { @Autowired private D5Service d5Service; @Autowired private D6Service d6Service; @Autowired private D7Service d7Service; @Autowired private D8Service d8Service; @Autowired private DltDrawRecordService dltDrawRecordService; @Override public BallCombinationAnalysisVO analyzeFrontFrontCombination(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 35, "主球(前区)"); validateBallRange(slaveBall, 1, 35, "随球(前区)"); // 查询指定组合记录 D5 targetRecord = d5Service.lambdaQuery() .eq(D5::getMasterBallNumber, masterBall) .eq(D5::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(前区)%d和随球(前区)%d的组合记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d5Service.lambdaQuery() .eq(D5::getMasterBallNumber, masterBall) .ne(D5::getSlaveBallNumber, masterBall) // 排除自身 .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(前区)%d的组合记录", masterBall)); } return buildCombinationAnalysisVO( targetRecord.getCoefficient(), allCombinations, D5::getCoefficient, D5::getSlaveBallNumber ); } @Override public BallCombinationAnalysisVO analyzeFrontBackCombination(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 35, "主球(前区)"); validateBallRange(slaveBall, 1, 12, "随球(后区)"); // 查询指定组合记录 D6 targetRecord = d6Service.lambdaQuery() .eq(D6::getMasterBallNumber, masterBall) .eq(D6::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(前区)%d和随球(后区)%d的组合记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d6Service.lambdaQuery() .eq(D6::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(前区)%d的组合记录", masterBall)); } return buildCombinationAnalysisVO( targetRecord.getCoefficient(), allCombinations, D6::getCoefficient, D6::getSlaveBallNumber ); } @Override public BallCombinationAnalysisVO analyzeBackBackCombination(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 12, "主球(后区)"); validateBallRange(slaveBall, 1, 12, "随球(后区)"); // 查询指定组合记录 D7 targetRecord = d7Service.lambdaQuery() .eq(D7::getMasterBallNumber, masterBall) .eq(D7::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(后区)%d和随球(后区)%d的组合记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d7Service.lambdaQuery() .eq(D7::getMasterBallNumber, masterBall) .ne(D7::getSlaveBallNumber, masterBall) // 排除自身 .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(后区)%d的组合记录", masterBall)); } return buildCombinationAnalysisVO( targetRecord.getCoefficient(), allCombinations, D7::getCoefficient, D7::getSlaveBallNumber ); } @Override public BallCombinationAnalysisVO analyzeBackFrontCombination(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 12, "主球(后区)"); validateBallRange(slaveBall, 1, 35, "随球(前区)"); // 查询指定组合记录 D8 targetRecord = d8Service.lambdaQuery() .eq(D8::getMasterBallNumber, masterBall) .eq(D8::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(后区)%d和随球(前区)%d的组合记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d8Service.lambdaQuery() .eq(D8::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(后区)%d的组合记录", masterBall)); } return buildCombinationAnalysisVO( targetRecord.getCoefficient(), allCombinations, D8::getCoefficient, D8::getSlaveBallNumber ); } /** * 验证球号范围 */ private void validateBallRange(Integer ballNumber, int minValue, int maxValue, String ballType) { if (ballNumber == null) { throw new IllegalArgumentException(ballType + "号码不能为空"); } if (ballNumber < minValue || ballNumber > maxValue) { throw new IllegalArgumentException(String.format("%s号码必须在%d-%d范围内,错误值:%d", ballType, minValue, maxValue, ballNumber)); } } /** * 构建组合分析结果VO */ private BallCombinationAnalysisVO buildCombinationAnalysisVO( Double targetCoefficient, List allCombinations, Function coefficientGetter, Function ballNumberGetter) { // 找出系数最高的球号 T highest = allCombinations.stream() .max(Comparator.comparing(coefficientGetter)) .orElse(null); // 找出系数最低的球号 T lowest = allCombinations.stream() .min(Comparator.comparing(coefficientGetter)) .orElse(null); // 计算平均系数 double avgCoefficient = allCombinations.stream() .mapToDouble(coefficientGetter::apply) .average() .orElse(0.0); // 获取最新开奖期号 Long latestDrawId = getLatestDrawId(); return BallCombinationAnalysisVO.builder() .faceCoefficient(targetCoefficient) .highestBall(highest != null ? ballNumberGetter.apply(highest) : null) .highestCoefficient(highest != null ? coefficientGetter.apply(highest) : null) .lowestBall(lowest != null ? ballNumberGetter.apply(lowest) : null) .lowestCoefficient(lowest != null ? coefficientGetter.apply(lowest) : null) .averageCoefficient(avgCoefficient) .latestDrawId(latestDrawId) .build(); } /** * 获取最新开奖期号 */ private Long getLatestDrawId() { String latestDrawId = dltDrawRecordService.lambdaQuery() .orderByDesc(DltDrawRecord::getDrawId) .last("LIMIT 1") .oneOpt() .map(DltDrawRecord::getDrawId) .orElse(null); if (latestDrawId != null) { try { return Long.parseLong(latestDrawId); } catch (NumberFormatException e) { log.warn("开奖期号格式转换失败:{}", latestDrawId); } } return null; } }