402 lines
18 KiB
Plaintext
402 lines
18 KiB
Plaintext
|
|
package com.xy.xyaicpzs.controller;
|
|||
|
|
|
|||
|
|
import com.xy.xyaicpzs.common.ErrorCode;
|
|||
|
|
import com.xy.xyaicpzs.common.ResultUtils;
|
|||
|
|
import com.xy.xyaicpzs.common.response.ApiResponse;
|
|||
|
|
import com.xy.xyaicpzs.domain.entity.LotteryDraws;
|
|||
|
|
import com.xy.xyaicpzs.domain.entity.PredictRecord;
|
|||
|
|
import com.xy.xyaicpzs.service.BallAnalysisService;
|
|||
|
|
import com.xy.xyaicpzs.service.LotteryDrawsService;
|
|||
|
|
import com.xy.xyaicpzs.service.PredictRecordService;
|
|||
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|||
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
|||
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
|
|
import lombok.extern.slf4j.Slf4j;
|
|||
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|||
|
|
import org.springframework.format.annotation.DateTimeFormat;
|
|||
|
|
import org.springframework.web.bind.annotation.*;
|
|||
|
|
|
|||
|
|
import java.util.Arrays;
|
|||
|
|
import java.util.Date;
|
|||
|
|
import java.util.List;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 球号分析控制器
|
|||
|
|
* 提供球号分析算法的API接口
|
|||
|
|
*/
|
|||
|
|
@Slf4j
|
|||
|
|
@RestController
|
|||
|
|
@RequestMapping("/ball-analysis")
|
|||
|
|
@Tag(name = "球号分析", description = "球号分析算法API")
|
|||
|
|
public class BallAnalysisController {
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private BallAnalysisService ballAnalysisService;
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private LotteryDrawsService lotteryDrawsService;
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private PredictRecordService predictRecordService;
|
|||
|
|
|
|||
|
|
@GetMapping("/predict-records/{userId}")
|
|||
|
|
@Operation(summary = "获取用户推测记录", description = "根据用户ID获取该用户的所有推测记录,按推测时间倒序排列")
|
|||
|
|
public ApiResponse<List<PredictRecord>> getPredictRecordsByUserId(
|
|||
|
|
@Parameter(description = "用户ID,例如:1001", required = true)
|
|||
|
|
@PathVariable Long userId
|
|||
|
|
, HttpServletRequest request) {
|
|||
|
|
User loginUser = userService.getLoginUser(request);
|
|||
|
|
if (loginUser == null){
|
|||
|
|
return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到获取用户推测记录请求:用户ID={}", userId);
|
|||
|
|
|
|||
|
|
// 调用服务获取用户推测记录
|
|||
|
|
List<PredictRecord> result = predictRecordService.getPredictRecordsByUserId(userId);
|
|||
|
|
|
|||
|
|
log.info("获取用户推测记录完成,用户ID:{},返回{}条记录", userId, result.size());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("获取用户推测记录失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取用户推测记录失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取近期开奖信息
|
|||
|
|
* @param limit 获取条数,可选参数,默认15条
|
|||
|
|
* @return 近期开奖信息列表
|
|||
|
|
*/
|
|||
|
|
@GetMapping("/recent-draws")
|
|||
|
|
@Operation(summary = "获取近期开奖信息", description = "获取最近的开奖信息,默认返回15条,按开奖期号倒序排列")
|
|||
|
|
public ApiResponse<List<LotteryDraws>> getRecentDraws(
|
|||
|
|
@Parameter(description = "获取条数,默认15条", required = false)
|
|||
|
|
@RequestParam(required = false, defaultValue = "15") Integer limit) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到获取近期开奖信息请求:条数={}", limit);
|
|||
|
|
|
|||
|
|
// 调用服务获取近期开奖信息
|
|||
|
|
List<LotteryDraws> result = lotteryDrawsService.getRecentDraws(limit);
|
|||
|
|
|
|||
|
|
log.info("获取近期开奖信息完成,返回{}条记录", result.size());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("获取近期开奖信息失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "获取近期开奖信息失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据日期范围查询开奖信息
|
|||
|
|
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
|||
|
|
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
|||
|
|
* @return 开奖信息列表
|
|||
|
|
*/
|
|||
|
|
@GetMapping("/query-draws")
|
|||
|
|
@Operation(summary = "按日期范围查询开奖信息", description = "根据日期范围查询开奖信息,支持单边日期查询")
|
|||
|
|
public ApiResponse<List<LotteryDraws>> queryDraws(
|
|||
|
|
@Parameter(description = "开始日期,格式:yyyy-MM-dd,例如:2025-01-01", required = false)
|
|||
|
|
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
|||
|
|
|
|||
|
|
@Parameter(description = "结束日期,格式:yyyy-MM-dd,例如:2025-01-31", required = false)
|
|||
|
|
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到按日期范围查询开奖信息请求:开始日期={},结束日期={}", startDate, endDate);
|
|||
|
|
|
|||
|
|
// 日期范围验证
|
|||
|
|
if (startDate != null && endDate != null && startDate.after(endDate)) {
|
|||
|
|
return ResultUtils.error(ErrorCode.PARAMS_ERROR, "开始日期不能晚于结束日期");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 调用服务按日期范围查询开奖信息
|
|||
|
|
List<LotteryDraws> result = lotteryDrawsService.getByDateRange(startDate, endDate);
|
|||
|
|
|
|||
|
|
log.info("按日期范围查询开奖信息完成,返回{}条记录", result.size());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("按日期范围查询开奖信息失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据期号精准查询单条开奖信息
|
|||
|
|
* @param drawId 开奖期号
|
|||
|
|
* @return 开奖信息
|
|||
|
|
*/
|
|||
|
|
@GetMapping("/draw/{drawId}")
|
|||
|
|
@Operation(summary = "根据期号查询开奖信息", description = "根据期号精准查询单条开奖信息")
|
|||
|
|
public ApiResponse<LotteryDraws> getDrawById(
|
|||
|
|
@Parameter(description = "开奖期号,例如:2025056", required = true)
|
|||
|
|
@PathVariable Long drawId) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到根据期号查询开奖信息请求:期号={}", drawId);
|
|||
|
|
|
|||
|
|
// 调用服务查询开奖信息
|
|||
|
|
LotteryDraws result = lotteryDrawsService.getByDrawId(drawId);
|
|||
|
|
|
|||
|
|
if (result == null) {
|
|||
|
|
log.warn("未找到期号为{}的开奖信息", drawId);
|
|||
|
|
return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "未找到期号为" + drawId + "的开奖信息");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log.info("根据期号查询开奖信息完成:{}", result.getDrawId());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("根据期号查询开奖信息失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "查询开奖信息失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建推测记录
|
|||
|
|
* @param userId 用户ID
|
|||
|
|
* @param drawId 开奖期号
|
|||
|
|
* @param drawDate 开奖日期
|
|||
|
|
* @param redBalls 6个红球号码,用逗号分隔
|
|||
|
|
* @param blueBall 蓝球号码
|
|||
|
|
* @return 创建的推测记录
|
|||
|
|
*/
|
|||
|
|
@PostMapping("/create-predict")
|
|||
|
|
@Operation(summary = "创建推测记录", description = "向predict_record表插入一条推测记录数据")
|
|||
|
|
public ApiResponse<PredictRecord> createPredictRecord(
|
|||
|
|
@Parameter(description = "用户ID,例如:1001", required = true)
|
|||
|
|
@RequestParam Long userId,
|
|||
|
|
|
|||
|
|
@Parameter(description = "开奖期号,例如:2025056", required = true)
|
|||
|
|
@RequestParam Long drawId,
|
|||
|
|
|
|||
|
|
@Parameter(description = "开奖日期,格式:yyyy-MM-dd", required = true)
|
|||
|
|
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date drawDate,
|
|||
|
|
|
|||
|
|
@Parameter(description = "6个红球号码,用逗号分隔,例如:1,5,12,18,25,33", required = true)
|
|||
|
|
@RequestParam String redBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "蓝球号码,例如:8", required = true)
|
|||
|
|
@RequestParam Integer blueBall) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到创建推测记录请求:用户ID={},期号={},开奖日期={},红球={},蓝球={}",
|
|||
|
|
userId, drawId, drawDate, redBalls, blueBall);
|
|||
|
|
|
|||
|
|
// 解析红球号码
|
|||
|
|
List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
|
|||
|
|
|
|||
|
|
// 调用服务创建推测记录
|
|||
|
|
PredictRecord result = predictRecordService.createPredictRecord(userId, drawId, drawDate, redBallList, blueBall);
|
|||
|
|
|
|||
|
|
log.info("创建推测记录完成,用户ID:{},记录ID:{}", userId, result.getId());
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("创建推测记录失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "创建推测记录失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 球号分析算法
|
|||
|
|
* @param level 高位/中位/低位标识 (H/M/L)
|
|||
|
|
* @param redBalls 6个红球号码,用逗号分隔
|
|||
|
|
* @param blueBall 蓝球号码
|
|||
|
|
* @return 分析结果:出现频率最高的前11位数字
|
|||
|
|
*/
|
|||
|
|
@PostMapping("/analyze")
|
|||
|
|
@Operation(summary = "首球算法", description = "根据输入的级别、红球和蓝球,分析出现频率最高的前11位数字")
|
|||
|
|
public ApiResponse<List<Integer>> analyzeBalls(
|
|||
|
|
@Parameter(description = "级别:H(高位)/M(中位)/L(低位)", required = true)
|
|||
|
|
@RequestParam String level,
|
|||
|
|
|
|||
|
|
@Parameter(description = "6个红球号码,用逗号分隔,例如:1,5,12,18,25,33", required = true)
|
|||
|
|
@RequestParam String redBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "蓝球号码,例如:8", required = true)
|
|||
|
|
@RequestParam Integer blueBall) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到球号分析请求:级别={},红球={},蓝球={}", level, redBalls, blueBall);
|
|||
|
|
|
|||
|
|
// 解析红球号码
|
|||
|
|
List<Integer> redBallList = parseRedBalls(redBalls, 6, "红球");
|
|||
|
|
|
|||
|
|
// 调用分析服务
|
|||
|
|
List<Integer> result = ballAnalysisService.analyzeBalls(level, redBallList, blueBall);
|
|||
|
|
|
|||
|
|
log.info("球号分析完成,结果:{}", result);
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("球号分析失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "球号分析失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 跟随球号分析算法
|
|||
|
|
* @param level 高位/中位/低位标识 (H/M/L)
|
|||
|
|
* @param firstThreeRedBalls 前3个红球号码,用逗号分隔
|
|||
|
|
* @param lastSixRedBalls 后6个红球号码,用逗号分隔
|
|||
|
|
* @param blueBall 蓝球号码
|
|||
|
|
* @return 分析结果:出现频率最高的前8位数字
|
|||
|
|
*/
|
|||
|
|
@PostMapping("/fallow")
|
|||
|
|
@Operation(summary = "跟随球号分析算法", description = "根据输入的级别、前3个红球、后6个红球和蓝球,分析出现频率最高的前8位数字")
|
|||
|
|
public ApiResponse<List<Integer>> fallowBallAnalysis(
|
|||
|
|
@Parameter(description = "级别:H(高位)/M(中位)/L(低位)", required = true)
|
|||
|
|
@RequestParam String level,
|
|||
|
|
|
|||
|
|
@Parameter(description = "前3个红球号码,用逗号分隔,例如:7,24,27", required = true)
|
|||
|
|
@RequestParam String firstThreeRedBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "后6个红球号码,用逗号分隔,例如:21,10,5,15,23,28", required = true)
|
|||
|
|
@RequestParam String lastSixRedBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "蓝球号码,例如:16", required = true)
|
|||
|
|
@RequestParam Integer blueBall) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到跟随球号分析请求:级别={},前3个红球={},后6个红球={},蓝球={}",
|
|||
|
|
level, firstThreeRedBalls, lastSixRedBalls, blueBall);
|
|||
|
|
|
|||
|
|
// 解析红球号码
|
|||
|
|
List<Integer> firstThreeRedBallList = parseRedBalls(firstThreeRedBalls, 3, "前3个红球");
|
|||
|
|
List<Integer> lastSixRedBallList = parseRedBalls(lastSixRedBalls, 6, "后6个红球");
|
|||
|
|
|
|||
|
|
// 调用分析服务
|
|||
|
|
List<Integer> result = ballAnalysisService.fallowBallAnalysis(level, firstThreeRedBallList, lastSixRedBallList, blueBall);
|
|||
|
|
|
|||
|
|
log.info("跟随球号分析完成,结果:{}", result);
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("跟随球号分析失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "跟随球号分析失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 解析红球号码字符串
|
|||
|
|
*/
|
|||
|
|
private List<Integer> parseRedBalls(String redBalls, int expectedCount, String ballType) {
|
|||
|
|
if (redBalls == null || redBalls.trim().isEmpty()) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码不能为空");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
String[] parts = redBalls.split(",");
|
|||
|
|
if (parts.length != expectedCount) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个,实际:" + parts.length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
List<Integer> result = Arrays.stream(parts)
|
|||
|
|
.map(String::trim)
|
|||
|
|
.map(Integer::parseInt)
|
|||
|
|
.collect(java.util.stream.Collectors.toList());
|
|||
|
|
|
|||
|
|
// 验证红球号码范围
|
|||
|
|
for (Integer ball : result) {
|
|||
|
|
if (ball < 1 || ball > 33) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码必须在1-33范围内,错误值:" + ball);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
} catch (NumberFormatException e) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码格式错误,请使用逗号分隔的数字");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 蓝球分析算法
|
|||
|
|
* @param level 高位/中位/低位标识 (H/M/L)
|
|||
|
|
* @param predictedRedBalls 6个推测红球号码,用逗号分隔
|
|||
|
|
* @param predictedBlueBalls 2个推测蓝球号码,用逗号分隔
|
|||
|
|
* @param lastRedBalls 6个上期红球号码,用逗号分隔
|
|||
|
|
* @param lastBlueBall 上期蓝球号码
|
|||
|
|
* @return 分析结果:频率最高的前4个蓝球号码
|
|||
|
|
*/
|
|||
|
|
@PostMapping("/blue-ball")
|
|||
|
|
@Operation(summary = "蓝球分析算法", description = "根据输入的级别、推测红球、推测蓝球、上期红球和上期蓝球,分析出频率最高的前4个蓝球号码")
|
|||
|
|
public ApiResponse<List<Integer>> blueBallAnalysis(
|
|||
|
|
@Parameter(description = "级别:H(高位)/M(中位)/L(低位)", required = true)
|
|||
|
|
@RequestParam String level,
|
|||
|
|
|
|||
|
|
@Parameter(description = "6个推测红球号码,用逗号分隔,例如:26,20,18,32,10,14", required = true)
|
|||
|
|
@RequestParam String predictedRedBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "2个推测蓝球号码,用逗号分隔,例如:5,8", required = true)
|
|||
|
|
@RequestParam String predictedBlueBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "6个上期红球号码,用逗号分隔,例如:7,24,27,21,10,5", required = true)
|
|||
|
|
@RequestParam String lastRedBalls,
|
|||
|
|
|
|||
|
|
@Parameter(description = "上期蓝球号码,例如:16", required = true)
|
|||
|
|
@RequestParam Integer lastBlueBall) {
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
log.info("接收到蓝球分析请求:级别={},推测红球={},推测蓝球={},上期红球={},上期蓝球={}",
|
|||
|
|
level, predictedRedBalls, predictedBlueBalls, lastRedBalls, lastBlueBall);
|
|||
|
|
|
|||
|
|
// 解析球号
|
|||
|
|
List<Integer> predictedRedBallList = parseRedBalls(predictedRedBalls, 6, "推测红球");
|
|||
|
|
List<Integer> predictedBlueBallList = parseBlueBalls(predictedBlueBalls, 2, "推测蓝球");
|
|||
|
|
List<Integer> lastRedBallList = parseRedBalls(lastRedBalls, 6, "上期红球");
|
|||
|
|
|
|||
|
|
// 调用分析服务
|
|||
|
|
List<Integer> result = ballAnalysisService.blueBallAnalysis(
|
|||
|
|
level, predictedRedBallList, predictedBlueBallList, lastRedBallList, lastBlueBall);
|
|||
|
|
|
|||
|
|
log.info("蓝球分析完成,结果:{}", result);
|
|||
|
|
return ResultUtils.success(result);
|
|||
|
|
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("蓝球分析失败:{}", e.getMessage(), e);
|
|||
|
|
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "蓝球分析失败:" + e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 解析蓝球号码字符串
|
|||
|
|
*/
|
|||
|
|
private List<Integer> parseBlueBalls(String blueBalls, int expectedCount, String ballType) {
|
|||
|
|
if (blueBalls == null || blueBalls.trim().isEmpty()) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码不能为空");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
String[] parts = blueBalls.split(",");
|
|||
|
|
if (parts.length != expectedCount) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "数量必须为" + expectedCount + "个,实际:" + parts.length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
List<Integer> result = Arrays.stream(parts)
|
|||
|
|
.map(String::trim)
|
|||
|
|
.map(Integer::parseInt)
|
|||
|
|
.collect(java.util.stream.Collectors.toList());
|
|||
|
|
|
|||
|
|
// 验证蓝球号码范围
|
|||
|
|
for (Integer ball : result) {
|
|||
|
|
if (ball < 1 || ball > 16) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码必须在1-16范围内,错误值:" + ball);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
} catch (NumberFormatException e) {
|
|||
|
|
throw new IllegalArgumentException(ballType + "号码格式错误,请使用逗号分隔的数字");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|