package com.xy.xyaicpzs.service.impl; import com.xy.xyaicpzs.domain.entity.DltDrawRecord; import com.xy.xyaicpzs.domain.entity.D9; import com.xy.xyaicpzs.domain.entity.D10; import com.xy.xyaicpzs.domain.entity.D11; import com.xy.xyaicpzs.domain.entity.D12; import com.xy.xyaicpzs.domain.vo.BallPersistenceAnalysisVO; import com.xy.xyaicpzs.service.DltPersistenceAnalysisService; import com.xy.xyaicpzs.service.DltDrawRecordService; import com.xy.xyaicpzs.service.D9Service; import com.xy.xyaicpzs.service.D10Service; import com.xy.xyaicpzs.service.D11Service; import com.xy.xyaicpzs.service.D12Service; 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 DltPersistenceAnalysisServiceImpl implements DltPersistenceAnalysisService { @Autowired private D9Service d9Service; @Autowired private D10Service d10Service; @Autowired private D11Service d11Service; @Autowired private D12Service d12Service; @Autowired private DltDrawRecordService dltDrawRecordService; @Override public BallPersistenceAnalysisVO analyzeFrontFrontPersistence(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 35, "主球(前区)"); validateBallRange(slaveBall, 1, 35, "随球(前区)"); // 查询指定组合记录 D9 targetRecord = d9Service.lambdaQuery() .eq(D9::getMasterBallNumber, masterBall) .eq(D9::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(前区)%d和随球(前区)%d的持续性记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d9Service.lambdaQuery() .eq(D9::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(前区)%d的持续性记录", masterBall)); } return buildPersistenceAnalysisVO( targetRecord.getCoefficient(), allCombinations, D9::getCoefficient, D9::getSlaveBallNumber ); } @Override public BallPersistenceAnalysisVO analyzeBackBackPersistence(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 12, "主球(后区)"); validateBallRange(slaveBall, 1, 12, "随球(后区)"); // 查询指定组合记录 D11 targetRecord = d11Service.lambdaQuery() .eq(D11::getMasterBallNumber, masterBall) .eq(D11::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(后区)%d和随球(后区)%d的持续性记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d11Service.lambdaQuery() .eq(D11::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(后区)%d的持续性记录", masterBall)); } return buildPersistenceAnalysisVO( targetRecord.getCoefficient(), allCombinations, D11::getCoefficient, D11::getSlaveBallNumber ); } @Override public BallPersistenceAnalysisVO analyzeFrontBackPersistence(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 35, "主球(前区)"); validateBallRange(slaveBall, 1, 12, "随球(后区)"); // 查询指定组合记录 D10 targetRecord = d10Service.lambdaQuery() .eq(D10::getMasterBallNumber, masterBall) .eq(D10::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(前区)%d和随球(后区)%d的持续性记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d10Service.lambdaQuery() .eq(D10::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(前区)%d的持续性记录", masterBall)); } return buildPersistenceAnalysisVO( targetRecord.getCoefficient(), allCombinations, D10::getCoefficient, D10::getSlaveBallNumber ); } @Override public BallPersistenceAnalysisVO analyzeBackFrontPersistence(Integer masterBall, Integer slaveBall) { // 参数校验 validateBallRange(masterBall, 1, 12, "主球(后区)"); validateBallRange(slaveBall, 1, 35, "随球(前区)"); // 查询指定组合记录 D12 targetRecord = d12Service.lambdaQuery() .eq(D12::getMasterBallNumber, masterBall) .eq(D12::getSlaveBallNumber, slaveBall) .one(); if (targetRecord == null) { throw new RuntimeException(String.format("未找到主球(后区)%d和随球(前区)%d的持续性记录", masterBall, slaveBall)); } // 查询主球与所有其他球的组合记录 List allCombinations = d12Service.lambdaQuery() .eq(D12::getMasterBallNumber, masterBall) .list(); if (allCombinations.isEmpty()) { throw new RuntimeException(String.format("未找到主球(后区)%d的持续性记录", masterBall)); } return buildPersistenceAnalysisVO( targetRecord.getCoefficient(), allCombinations, D12::getCoefficient, D12::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 BallPersistenceAnalysisVO buildPersistenceAnalysisVO( 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 BallPersistenceAnalysisVO.builder() .lineCoefficient(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; } }