添加投注记录

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; package com.tem.bocai;
import com.tem.bocai.schedules.*;
import com.tem.bocai.util.SQLiteUtil; import com.tem.bocai.util.SQLiteUtil;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@@ -10,7 +12,32 @@ import org.springframework.scheduling.annotation.EnableScheduling;
public class BocaiApplication { public class BocaiApplication {
public static void main(String[] args) { 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; private Date updateTime;
@Column(name = "bet_num") @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 com.tem.bocai.entity.BetRecord;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository @Repository
public interface BetRecordRepository extends JpaRepository<BetRecord, Long> { 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 com.tem.bocai.service.LoginService;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.FileReader; import java.io.FileReader;
@@ -14,13 +15,17 @@ import java.net.http.HttpResponse;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import com.tem.bocai.entity.LoginInfoResult; import com.tem.bocai.entity.LoginInfoResult;
import com.tem.bocai.entity.BetRecord;
import com.tem.bocai.repository.CompletedTodayRepository; import com.tem.bocai.repository.CompletedTodayRepository;
import com.tem.bocai.repository.LoginInfoRepository; import com.tem.bocai.repository.LoginInfoRepository;
import com.tem.bocai.repository.BetRecordRepository;
@Component @Component
public class BetSchedule { public class BetSchedule {
@@ -34,13 +39,11 @@ public class BetSchedule {
@Autowired @Autowired
private CompletedTodayRepository completedTodayRepository; private CompletedTodayRepository completedTodayRepository;
public static void main(String[] args) { @Autowired
BetSchedule betSchedule = new BetSchedule(); private BetRecordRepository betRecordRepository;
betSchedule.placeBet();
}
// 每天早上7.07分开始每5分钟执行一次到第二天早上6点结束7:07, 7:12, 7:17...23:57, 0:02, 0:07...5:57 // 每天早上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() { public void placeBet() {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
int hour = now.getHour(); int hour = now.getHour();
@@ -61,51 +64,50 @@ public class BetSchedule {
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
); );
// LoginInfoResult loginInfo = loginInfoRepository.findFirstByOrderByCreateTimeDesc().orElse(null); LoginInfoResult loginInfo = loginInfoRepository.findFirstByOrderByCreateTimeDesc().orElse(null);
// if (loginInfo == null) { if (loginInfo == null) {
// System.out.println(currentTime + " - 未找到登录信息,跳过执行"); System.out.println(currentTime + " - 未找到登录信息,跳过执行");
// return; return;
// } }
//
// // 检查onOff字段是否为1开启状态 // 检查onOff字段是否为1开启状态
// if (loginInfo.getOnOff() != 1) { if (loginInfo.getOnOff() != 1) {
// System.out.println(currentTime + " - 投注功能未开启,跳过执行"); System.out.println(currentTime + " - 投注功能未开启,跳过执行");
// return; return;
// } }
//
// // 检查winNum和loseNum字段是否合理 // 检查winNum和loseNum字段是否合理
// Integer winNum = loginInfo.getWinNum(); Integer winNum = loginInfo.getWinNum();
// Integer loseNum = loginInfo.getLoseNum(); Integer loseNum = loginInfo.getLoseNum();
//
// if (winNum != null || loseNum != null) { if (winNum != null || loseNum != null) {
// // 根据LoginInfo的startTime 查询CompletedToday的resultAmount总和 判断是否达到 winNum 和 loseNum的值 // 根据LoginInfo的startTime 查询CompletedToday的resultAmount总和 判断是否达到 winNum 和 loseNum的值
// Date startTime = loginInfo.getStartTime(); Date startTime = loginInfo.getStartTime();
// if (startTime != null) { if (startTime != null) {
// Double totalResultAmount = completedTodayRepository.sumResultAmountByCreateTimeAfter(startTime); Double totalResultAmount = completedTodayRepository.sumResultAmountByCreateTimeAfter(startTime);
// if (totalResultAmount != null) { if (totalResultAmount != null) {
// System.out.println(" - 今日盈亏总和: " + totalResultAmount); System.out.println(" - 今日盈亏总和: " + totalResultAmount);
//
// // 判断是否达到止盈点 // 判断是否达到止盈点
// if (totalResultAmount >= winNum) { if (totalResultAmount >= winNum) {
// System.out.println(currentTime + " - 已达到止盈点 " + winNum + ",跳过执行"); System.out.println(currentTime + " - 已达到止盈点 " + winNum + ",跳过执行");
// return; return;
// } }
//
// // 判断是否达到止亏点 // 判断是否达到止亏点
// if (totalResultAmount <= -loseNum) { if (totalResultAmount <= -loseNum) {
// System.out.println(currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行"); System.out.println(currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行");
// return; return;
// } }
// } }
// } }
// } }
System.out.println(currentTime + " - 开始执行投注..."); System.out.println(currentTime + " - 开始执行投注...");
// System.out.println(" - 投注设置: 止盈点=" + winNum + ", 止亏点=" + loseNum + ", 状态=" + (loginInfo.getOnOff() == 1 ? "开启" : "关闭"));
try { try {
// 执行投注逻辑 // 执行投注逻辑
executeBet(null); executeBet(loginInfo);
System.out.println(currentTime + " - 投注执行完成"); System.out.println(currentTime + " - 投注执行完成");
@@ -120,54 +122,38 @@ public class BetSchedule {
*/ */
private void executeBet(LoginInfoResult loginInfo) { private void executeBet(LoginInfoResult loginInfo) {
// 这里实现具体的投注逻辑 // 这里实现具体的投注逻辑
// 1. 获取投注号码 // 1. 从BetRecord中获取最新的一条记录
// 2. 计算投注金额 // 2. 计算投注金额
// 3. 执行投注操作 // 3. 执行投注操作
// 4. 记录投注结果 // 4. 记录投注结果
try { try {
// 1. 从json文件中获取投注数据 // 1. 获取当前时间格式化为与betTime相同的格式假设betTime格式为yyyy-MM-dd HH:mm:ss
System.out.println(" - 从json文件中获取投注数据..."); LocalDateTime now = LocalDateTime.now();
JSONArray betDataArray = readBetDataFromJson(); String currentTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 2. 遍历投注数据并执行投注 构建投注json // 2. 从BetRecord中获取最新的一条记录根据betTime排序且betTime大于等于当前时间
for (int i = 0; i < betDataArray.length(); i++) { System.out.println(" - 从BetRecord中获取最新的一条记录...");
JSONObject betData = betDataArray.getJSONObject(i); Optional<BetRecord> optionalBetRecord = betRecordRepository.findFirstByBetTimeGreaterThanEqualOrderByBetTimeDesc(currentTime);
String time = betData.getString("time");
System.out.println(" - 处理投注时间: " + time);
// 获取投注号码 if (optionalBetRecord.isPresent()) {
JSONObject result = betData.getJSONObject("result"); BetRecord betRecord = optionalBetRecord.get();
JSONArray betNumbers = new JSONArray(); String betData = betRecord.getBetData();
result.keySet().forEach(key -> { String betTime = betRecord.getBetTime();
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());
// 生成betNum (年月日+001-288) System.out.println(" - 投注时间: " + betTime);
Integer betNum = generateBetNum(); System.out.println(" - 投注数据: " + betData);
System.out.println(" - 投注编号: " + betNum);
// 计算投注金额
double betAmount = loginInfo.getAmount(); // 固定投注金额
System.out.println(" - 投注金额: " + betAmount);
// 调用投注接口 // 调用投注接口
System.out.println(" - 提交投注..."); System.out.println(" - 提交投注...");
String betResult = callBetApi(betNumbers, loginInfo); String betResult = callBetApi(betData, loginInfo);
System.out.println(" - 投注结果: " + betResult); System.out.println(" - 投注结果: " + betResult);
// 记录投注结果 // 记录投注结果
System.out.println(" - 记录投注结果..."); System.out.println(" - 记录投注结果...");
recordBetResult(betNumbers, betAmount, betResult, betNum); recordBetResult(betData, betResult);
} else {
System.out.println(" - 未找到投注记录");
} }
} catch (Exception e) { } 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 // 假设投注接口地址为http://localhost:8080/api/bet
String apiUrl = "https://4701268539-esh.qdk63ayw8g.com/member/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客户端和请求 // 创建HTTP客户端和请求
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
@@ -231,9 +176,8 @@ public class BetSchedule {
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.header("cookie", "token=" + loginService.completedToday()); .header("cookie", "token=" + loginService.completedToday());
HttpRequest request = requestBuilder HttpRequest request = requestBuilder
.POST(HttpRequest.BodyPublishers.ofString(requestBody.toString())) .POST(HttpRequest.BodyPublishers.ofString(betData))
.build(); .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")); 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秒执行一次爬取今日已经结算 // 每7秒执行一次爬取今日已经结算
@Scheduled(cron = "*/7 * * * * ?") // @Scheduled(cron = "*/7 * * * * ?")
public void executeSettlement() { public void executeSettlement() {
System.out.println("开始爬取今日已经结算..."); System.out.println("开始爬取今日已经结算...");
int retryCount = 0; int retryCount = 0;

View File

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

View File

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

View File

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