添加投注记录

This commit is contained in:
2026-01-27 09:28:20 +08:00
parent c39cf2cc8a
commit 6e6e9d71f9
12 changed files with 6876 additions and 7275 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

BIN
bocai.db

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +1,10 @@
package com.tem.bocai;
import com.tem.bocai.schedules.*;
import com.tem.bocai.util.SQLiteUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@@ -10,7 +12,32 @@ import org.springframework.scheduling.annotation.EnableScheduling;
public class BocaiApplication {
public static void main(String[] args) {
SpringApplication.run(BocaiApplication.class, args);
ApplicationContext context = SpringApplication.run(BocaiApplication.class, args);
BetSchedule betSchedule = context.getBean(BetSchedule.class);
betSchedule.placeBet();
// // 依次执行三个任务
//
// // 1. 执行CrawlerSchedule方法
// System.out.println("\n=== 开始执行CrawlerSchedule任务 ===");
// CrawlerSchedule crawlerSchedule = context.getBean(CrawlerSchedule.class);
// crawlerSchedule.executeLotteryDraw();
//
// // 2. 执行ExAggregateDataScriptSchedule方法
// System.out.println("\n=== 开始执行ExAggregateDataScriptSchedule任务 ===");
// ExAggregateDataScriptSchedule exAggregateDataScriptSchedule = context.getBean(ExAggregateDataScriptSchedule.class);
// exAggregateDataScriptSchedule.executePythonScript();
//
// // 3. 执行ExBetScriptSchedule方法
// System.out.println("\n=== 开始执行ExBetScriptSchedule任务 ===");
// ExBetScriptSchedule exBetScriptSchedule = context.getBean(ExBetScriptSchedule.class);
// exBetScriptSchedule.executePythonScript();
//
// // 4. 执行GenBetRecordSchedule方法
// System.out.println("\n=== 开始执行GenBetRecordSchedule任务 ===");
// GenBetRecordSchedule genBetRecordSchedule = context.getBean(GenBetRecordSchedule.class);
// genBetRecordSchedule.processBetPredictions();
}
}

View File

@@ -26,5 +26,5 @@ public class BetRecord {
private Date updateTime;
@Column(name = "bet_num")
private Integer betNum;
private String betNum;
}

View File

@@ -3,7 +3,32 @@ package com.tem.bocai.repository;
import com.tem.bocai.entity.BetRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface BetRecordRepository extends JpaRepository<BetRecord, Long> {
/**
* 根据betNum查询记录
*/
boolean existsByBetNum(String betNum);
/**
* 删除所有记录
*/
void deleteAll();
/**
* 根据当前时间获取最新的一条记录
*/
Optional<BetRecord> findFirstByOrderByCreateTimeDesc();
/**
* 根据betTime获取最新的一条记录
*/
Optional<BetRecord> findFirstByOrderByBetTimeDesc();
/**
* 根据当前时间获取最新的一条记录betTime大于等于当前时间
*/
Optional<BetRecord> findFirstByBetTimeGreaterThanEqualOrderByBetTimeDesc(String currentTime);
}

View File

@@ -3,6 +3,7 @@ package com.tem.bocai.schedules;
import com.tem.bocai.service.LoginService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.FileReader;
@@ -14,13 +15,17 @@ import java.net.http.HttpResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.tem.bocai.entity.LoginInfoResult;
import com.tem.bocai.entity.BetRecord;
import com.tem.bocai.repository.CompletedTodayRepository;
import com.tem.bocai.repository.LoginInfoRepository;
import com.tem.bocai.repository.BetRecordRepository;
@Component
public class BetSchedule {
@@ -34,13 +39,11 @@ public class BetSchedule {
@Autowired
private CompletedTodayRepository completedTodayRepository;
public static void main(String[] args) {
BetSchedule betSchedule = new BetSchedule();
betSchedule.placeBet();
}
@Autowired
private BetRecordRepository betRecordRepository;
// 每天早上7.07分开始每5分钟执行一次到第二天早上6点结束7:07, 7:12, 7:17...23:57, 0:02, 0:07...5:57
// @Scheduled(cron = "0 7/5 7-23,0-6 * * ?")
@Scheduled(cron = "0 7/5 7-23,0-6 * * ?")
public void placeBet() {
LocalDateTime now = LocalDateTime.now();
int hour = now.getHour();
@@ -61,51 +64,50 @@ public class BetSchedule {
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
);
// LoginInfoResult loginInfo = loginInfoRepository.findFirstByOrderByCreateTimeDesc().orElse(null);
// if (loginInfo == null) {
// System.out.println(currentTime + " - 未找到登录信息,跳过执行");
// return;
// }
//
// // 检查onOff字段是否为1开启状态
// if (loginInfo.getOnOff() != 1) {
// System.out.println(currentTime + " - 投注功能未开启,跳过执行");
// return;
// }
//
// // 检查winNum和loseNum字段是否合理
// Integer winNum = loginInfo.getWinNum();
// Integer loseNum = loginInfo.getLoseNum();
//
// if (winNum != null || loseNum != null) {
// // 根据LoginInfo的startTime 查询CompletedToday的resultAmount总和 判断是否达到 winNum 和 loseNum的值
// Date startTime = loginInfo.getStartTime();
// if (startTime != null) {
// Double totalResultAmount = completedTodayRepository.sumResultAmountByCreateTimeAfter(startTime);
// if (totalResultAmount != null) {
// System.out.println(" - 今日盈亏总和: " + totalResultAmount);
//
// // 判断是否达到止盈点
// if (totalResultAmount >= winNum) {
// System.out.println(currentTime + " - 已达到止盈点 " + winNum + ",跳过执行");
// return;
// }
//
// // 判断是否达到止亏点
// if (totalResultAmount <= -loseNum) {
// System.out.println(currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行");
// return;
// }
// }
// }
// }
LoginInfoResult loginInfo = loginInfoRepository.findFirstByOrderByCreateTimeDesc().orElse(null);
if (loginInfo == null) {
System.out.println(currentTime + " - 未找到登录信息,跳过执行");
return;
}
// 检查onOff字段是否为1开启状态
if (loginInfo.getOnOff() != 1) {
System.out.println(currentTime + " - 投注功能未开启,跳过执行");
return;
}
// 检查winNum和loseNum字段是否合理
Integer winNum = loginInfo.getWinNum();
Integer loseNum = loginInfo.getLoseNum();
if (winNum != null || loseNum != null) {
// 根据LoginInfo的startTime 查询CompletedToday的resultAmount总和 判断是否达到 winNum 和 loseNum的值
Date startTime = loginInfo.getStartTime();
if (startTime != null) {
Double totalResultAmount = completedTodayRepository.sumResultAmountByCreateTimeAfter(startTime);
if (totalResultAmount != null) {
System.out.println(" - 今日盈亏总和: " + totalResultAmount);
// 判断是否达到止盈点
if (totalResultAmount >= winNum) {
System.out.println(currentTime + " - 已达到止盈点 " + winNum + ",跳过执行");
return;
}
// 判断是否达到止亏点
if (totalResultAmount <= -loseNum) {
System.out.println(currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行");
return;
}
}
}
}
System.out.println(currentTime + " - 开始执行投注...");
// System.out.println(" - 投注设置: 止盈点=" + winNum + ", 止亏点=" + loseNum + ", 状态=" + (loginInfo.getOnOff() == 1 ? "开启" : "关闭"));
try {
// 执行投注逻辑
executeBet(null);
executeBet(loginInfo);
System.out.println(currentTime + " - 投注执行完成");
@@ -120,54 +122,38 @@ public class BetSchedule {
*/
private void executeBet(LoginInfoResult loginInfo) {
// 这里实现具体的投注逻辑
// 1. 获取投注号码
// 1. 从BetRecord中获取最新的一条记录
// 2. 计算投注金额
// 3. 执行投注操作
// 4. 记录投注结果
try {
// 1. 从json文件中获取投注数据
System.out.println(" - 从json文件中获取投注数据...");
JSONArray betDataArray = readBetDataFromJson();
// 1. 获取当前时间格式化为与betTime相同的格式假设betTime格式为yyyy-MM-dd HH:mm:ss
LocalDateTime now = LocalDateTime.now();
String currentTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 2. 遍历投注数据并执行投注 构建投注json
for (int i = 0; i < betDataArray.length(); i++) {
JSONObject betData = betDataArray.getJSONObject(i);
String time = betData.getString("time");
System.out.println(" - 处理投注时间: " + time);
// 2. 从BetRecord中获取最新的一条记录根据betTime排序且betTime大于等于当前时间
System.out.println(" - 从BetRecord中获取最新的一条记录...");
Optional<BetRecord> optionalBetRecord = betRecordRepository.findFirstByBetTimeGreaterThanEqualOrderByBetTimeDesc(currentTime);
// 获取投注号码
JSONObject result = betData.getJSONObject("result");
JSONArray betNumbers = new JSONArray();
result.keySet().forEach(key -> {
JSONObject betNumber = new JSONObject();
JSONObject posData = result.getJSONObject(key);
posData.keySet().forEach(num -> {
Object o = posData.get(num);
if (ObjectUtils.isNotEmpty(o) && !o.toString().equals("null")) {
betNumber.put(num, posData.get(num));
}
});
betNumbers.put(betNumber);
});
System.out.println(" - 投注号码: " + betNumbers.toString());
if (optionalBetRecord.isPresent()) {
BetRecord betRecord = optionalBetRecord.get();
String betData = betRecord.getBetData();
String betTime = betRecord.getBetTime();
// 生成betNum (年月日+001-288)
Integer betNum = generateBetNum();
System.out.println(" - 投注编号: " + betNum);
// 计算投注金额
double betAmount = loginInfo.getAmount(); // 固定投注金额
System.out.println(" - 投注金额: " + betAmount);
System.out.println(" - 投注时间: " + betTime);
System.out.println(" - 投注数据: " + betData);
// 调用投注接口
System.out.println(" - 提交投注...");
String betResult = callBetApi(betNumbers, loginInfo);
String betResult = callBetApi(betData, loginInfo);
System.out.println(" - 投注结果: " + betResult);
// 记录投注结果
System.out.println(" - 记录投注结果...");
recordBetResult(betNumbers, betAmount, betResult, betNum);
recordBetResult(betData, betResult);
} else {
System.out.println(" - 未找到投注记录");
}
} catch (Exception e) {
@@ -176,54 +162,13 @@ public class BetSchedule {
}
}
/**
* 生成betNum格式为年月日+001-288
*/
private Integer generateBetNum() {
// 获取当前日期格式为YYYYMMDD
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 生成001-288的序号
int seq = (int) (Math.random() * 288) + 1;
String seqStr = String.format("%03d", seq);
// 组合成betNum
String betNumStr = dateStr + seqStr;
return Integer.parseInt(betNumStr);
}
/**
* 从json文件中读取投注数据
*/
private JSONArray readBetDataFromJson() throws IOException {
// 使用绝对路径读取文件
String projectRoot = System.getProperty("user.dir");
String filePath = projectRoot + "/PyModel/data_test_predict/betting_predictions_final_1_20.json";
System.out.println(" - 读取投注数据文件: " + filePath);
FileReader reader = new FileReader(filePath);
JSONTokener tokener = new JSONTokener(reader);
JSONArray betData = new JSONArray(tokener);
reader.close();
System.out.println(" - 成功读取投注数据,共" + betData.length() + "条记录");
return betData;
}
/**
* 调用投注接口
*/
private String callBetApi(JSONArray betNumbers, LoginInfoResult loginInfo) throws IOException, InterruptedException {
private String callBetApi(String betData, LoginInfoResult loginInfo) throws IOException, InterruptedException {
// 假设投注接口地址为http://localhost:8080/api/bet
String apiUrl = "https://4701268539-esh.qdk63ayw8g.com/member/bet";
// 构建请求体
JSONObject requestBody = new JSONObject();
requestBody.put("lottery", "SGFT");
requestBody.put("drawNumber", 0);
requestBody.put("fastBets", false);
requestBody.put("ignore", false);
requestBody.put("bets", betNumbers);
// 创建HTTP客户端和请求
HttpClient client = HttpClient.newHttpClient();
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
@@ -231,9 +176,8 @@ public class BetSchedule {
.header("Content-Type", "application/json")
.header("cookie", "token=" + loginService.completedToday());
HttpRequest request = requestBuilder
.POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
.POST(HttpRequest.BodyPublishers.ofString(betData))
.build();
// 发送请求并获取响应
@@ -251,10 +195,10 @@ public class BetSchedule {
/**
* 记录投注结果
*/
private void recordBetResult(JSONArray betNumbers, double betAmount, String betResult, Integer betNum) {
private void recordBetResult(String betData, String betResult) {
// 这里可以实现将投注结果记录到数据库或日志文件的逻辑
// 为了简单起见,我们这里只打印日志
String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(" - 投注记录: [" + currentTime + "] 号码: " + betNumbers.toString() + ", 金额: " + betAmount + ", 结果: " + betResult + ", 编号: " + betNum);
System.out.println(" - 投注记录: [" + currentTime + "] 数据: " + betData + ", 结果: " + betResult);
}
}

View File

@@ -111,7 +111,7 @@ public class CrawlerSchedule {
// 每7秒执行一次爬取今日已经结算
@Scheduled(cron = "*/7 * * * * ?")
// @Scheduled(cron = "*/7 * * * * ?")
public void executeSettlement() {
System.out.println("开始爬取今日已经结算...");
int retryCount = 0;

View File

@@ -34,7 +34,7 @@ public class ExAggregateDataScriptSchedule {
}
// 每天凌晨2点执行
@Scheduled(cron = "0 10 6 * * ?")
// @Scheduled(cron = "0 10 6 * * ?")
public void executePythonScript() {
System.out.println("开始执行Python脚本...");

View File

@@ -35,7 +35,7 @@ public class ExBetScriptSchedule {
}
// 每天凌晨2点执行
@Scheduled(cron = "0 10 6 * * ?")
// @Scheduled(cron = "0 10 6 * * ?")
public void executePythonScript() {
System.out.println("开始执行Python脚本...");

View File

@@ -24,14 +24,17 @@ public class GenBetRecordSchedule {
@Autowired
private BetRecordRepository betRecordRepository;
// 静态变量,用于跟踪顺序序号
private static int seqCounter = 1;
public static void main(String[] args) {
GenBetRecordSchedule genBetRecordSchedule = new GenBetRecordSchedule();
genBetRecordSchedule.processBetPredictions();
// 注意直接运行此方法会导致betRecordRepository为null
// 请通过BocaiApplication的main方法运行或使用Spring Boot启动
System.out.println("请通过BocaiApplication的main方法运行或使用Spring Boot启动");
}
// 每天00:01执行
@Scheduled(cron = "0 1 00 * * ?")
// @Scheduled(cron = "0 * * * * ?")
// 每天6:30执行
@Scheduled(cron = "0 30 6 * * ?")
public void processBetPredictions() {
LocalDateTime now = LocalDateTime.now();
String currentTime = now.format(
@@ -40,6 +43,10 @@ public class GenBetRecordSchedule {
System.out.println(currentTime + " - 开始处理投注预测数据...");
try {
// 删除所有旧数据
betRecordRepository.deleteAll();
System.out.println(" - 已删除所有旧数据");
// 读取投注预测数据
JSONArray betDataArray = readBetDataFromJson();
System.out.println(" - 成功读取投注预测数据,共" + betDataArray.length() + "条记录");
@@ -57,7 +64,7 @@ public class GenBetRecordSchedule {
JSONObject outputData = generateOutputData(betData, result);
// 打印处理结果
System.out.println(" - 生成的投注数据: " + outputData.toString());
System.out.println(" - 生成的投注数据: " + outputData);
// 保存处理结果到数据库
saveToDatabase(outputData, time);
@@ -80,9 +87,22 @@ public class GenBetRecordSchedule {
// 设置固定字段
outputData.put("lottery", "SGFT");
// 生成drawNumber: 年份月份日期序号
String id = betData.getString("id");
outputData.put("drawNumber", id);
// 生成drawNumber: 年月日+001-288
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 确保seqCounter在1-288之间循环
if (seqCounter > 288) {
seqCounter = 1;
}
// 使用顺序序号
String seqStr = String.format("%03d", seqCounter);
String drawNumber = dateStr + seqStr;
// 序号自增
seqCounter++;
outputData.put("drawNumber", drawNumber);
// 生成bets数组
JSONArray betsArray = new JSONArray();
@@ -162,16 +182,26 @@ public class GenBetRecordSchedule {
*/
private void saveToDatabase(JSONObject validResults, String time) {
try {
// 从validResults中获取drawNumber作为betNum
String drawNumber = validResults.getString("drawNumber");
// 检查betNum是否已存在
if (betRecordRepository.existsByBetNum(drawNumber)) {
System.out.println(" - 投注编号已存在,跳过保存: " + drawNumber);
return;
}
// 创建BetRecord实体
BetRecord betRecord = new BetRecord();
betRecord.setBetTime(time);
betRecord.setBetData(validResults.toString());
betRecord.setBetNum(drawNumber);
betRecord.setCreateTime(new Date());
betRecord.setUpdateTime(new Date());
// 保存到数据库
BetRecord savedRecord = betRecordRepository.save(betRecord);
System.out.println(" - 保存有效投注结果到数据库ID: " + savedRecord.getId());
System.out.println(" - 保存有效投注结果到数据库ID: " + savedRecord.getId() + ", 投注编号: " + drawNumber);
} catch (Exception e) {
System.err.println(" - 保存有效投注结果到数据库失败: " + e.getMessage());
e.printStackTrace();