智能选号功能修正,样式调整
This commit is contained in:
parent
77d81ffa4b
commit
a093b50d5a
60
README.md
60
README.md
@ -219,4 +219,62 @@ MIT License
|
||||
- 系统会自动检查本地数据库中最新的开奖日期
|
||||
- 只获取并更新比本地数据更新的开奖记录
|
||||
- 更新过程会记录日志到 `lottery_update.log` 文件
|
||||
- 支持双色球和大乐透两种彩票的数据更新
|
||||
- 支持双色球和大乐透两种彩票的数据更新
|
||||
|
||||
## 分析功能说明
|
||||
|
||||
### 基础分析策略
|
||||
|
||||
#### 1. 冷热号码分析
|
||||
- 热号:统计近50期出现频率最高的号码
|
||||
- 冷号:统计超过平均遗漏期数的号码
|
||||
- API: GET `/api/analysis/hot-cold/{lottery_type}?periods=50`
|
||||
|
||||
#### 2. 号码分布分析
|
||||
- 分区统计:将号码划分为多个区间,分析各区出号比例
|
||||
- 奇偶比:分析奇偶数的分布规律
|
||||
- 大小比:统计大数和小数的分布规律
|
||||
- API: GET `/api/analysis/distribution/{lottery_type}?periods=100`
|
||||
|
||||
#### 3. 连号与重复号分析
|
||||
- 连号追踪:统计连号出现的频率和位置
|
||||
- 重复号观察:分析相邻期号码重复情况
|
||||
- API: GET `/api/analysis/consecutive/{lottery_type}?periods=100`
|
||||
|
||||
### 数学理论应用
|
||||
|
||||
#### 1. 数学统计特征
|
||||
- 计算红球总和的历史平均值和标准差
|
||||
- 分析号码组合的数学特征
|
||||
- API: GET `/api/analysis/math-stats/{lottery_type}?periods=100`
|
||||
|
||||
#### 2. 遗漏值分析
|
||||
- 计算每个号码的当前遗漏值
|
||||
- 分析历史最大遗漏
|
||||
- API: GET `/api/analysis/missing/{lottery_type}`
|
||||
|
||||
### 智能选号策略
|
||||
|
||||
系统提供多种智能选号策略:
|
||||
- 均衡策略:综合考虑号码分布特征
|
||||
- 热号策略:偏好选择近期高频号码
|
||||
- 冷号策略:偏好选择遗漏值较大的号码
|
||||
- 遗漏值策略:基于遗漏值分析选号
|
||||
- API: GET `/api/analysis/smart-numbers/{lottery_type}?strategy=balanced`
|
||||
|
||||
### 使用示例
|
||||
|
||||
1. 获取双色球热号冷号分析:
|
||||
```bash
|
||||
curl http://localhost:8000/api/analysis/hot-cold/ssq?periods=50
|
||||
```
|
||||
|
||||
2. 获取大乐透号码分布分析:
|
||||
```bash
|
||||
curl http://localhost:8000/api/analysis/distribution/dlt?periods=100
|
||||
```
|
||||
|
||||
3. 使用均衡策略生成双色球号码:
|
||||
```bash
|
||||
curl http://localhost:8000/api/analysis/smart-numbers/ssq?strategy=balanced
|
||||
```
|
||||
108
backend/app/api/endpoints/analysis.py
Normal file
108
backend/app/api/endpoints/analysis.py
Normal file
@ -0,0 +1,108 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import Optional
|
||||
|
||||
from ...core.database import get_db
|
||||
from ...services.analysis_service import LotteryAnalysisService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/hot-cold/{lottery_type}")
|
||||
def get_hot_cold_numbers(
|
||||
lottery_type: str,
|
||||
periods: Optional[int] = 50,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取热号和冷号分析"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.get_hot_cold_numbers(lottery_type, periods)
|
||||
|
||||
|
||||
@router.get("/distribution/{lottery_type}")
|
||||
def get_number_distribution(
|
||||
lottery_type: str,
|
||||
periods: Optional[int] = 100,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取号码分布分析"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.analyze_number_distribution(lottery_type, periods)
|
||||
|
||||
|
||||
@router.get("/consecutive/{lottery_type}")
|
||||
def get_consecutive_analysis(
|
||||
lottery_type: str,
|
||||
periods: Optional[int] = 100,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取连号和重复号分析"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.analyze_consecutive_numbers(lottery_type, periods)
|
||||
|
||||
|
||||
@router.get("/math-stats/{lottery_type}")
|
||||
def get_mathematical_stats(
|
||||
lottery_type: str,
|
||||
periods: Optional[int] = 100,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取数学统计特征"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.analyze_mathematical_stats(lottery_type, periods)
|
||||
|
||||
|
||||
@router.get("/missing/{lottery_type}")
|
||||
def get_missing_periods(
|
||||
lottery_type: str,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取号码遗漏值分析"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.get_missing_periods(lottery_type)
|
||||
|
||||
|
||||
@router.get("/smart-numbers/{lottery_type}")
|
||||
def generate_smart_numbers(
|
||||
lottery_type: str,
|
||||
strategy: Optional[str] = 'balanced',
|
||||
count: Optional[int] = 1,
|
||||
periods: Optional[int] = 100,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""智能选号
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
strategy: 选号策略 ('balanced', 'hot', 'cold', 'missing')
|
||||
count: 生成注数,默认1注
|
||||
periods: 分析期数,默认100期
|
||||
"""
|
||||
if lottery_type not in ['ssq', 'dlt']:
|
||||
raise HTTPException(status_code=400, detail="Invalid lottery type")
|
||||
if strategy not in ['balanced', 'hot', 'cold', 'missing']:
|
||||
raise HTTPException(status_code=400, detail="Invalid strategy")
|
||||
if count < 1 or count > 10:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Count must be between 1 and 10")
|
||||
if periods < 50 or periods > 200:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Periods must be between 50 and 200")
|
||||
|
||||
analysis_service = LotteryAnalysisService(db)
|
||||
return analysis_service.generate_smart_numbers(lottery_type, strategy, count, periods)
|
||||
@ -2,6 +2,7 @@ from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from app.core.config import settings
|
||||
from app.api.v1.lottery import router as lottery_router
|
||||
from app.api.endpoints.analysis import router as analysis_router
|
||||
from app.core.database import Base, engine
|
||||
|
||||
# 创建数据库表
|
||||
@ -15,7 +16,7 @@ app = FastAPI(
|
||||
# 配置CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.BACKEND_CORS_ORIGINS,
|
||||
allow_origins=["*"], # 允许所有来源
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
@ -24,6 +25,8 @@ app.add_middleware(
|
||||
# 注册路由
|
||||
app.include_router(
|
||||
lottery_router, prefix=f"{settings.API_V1_STR}/lottery", tags=["lottery"])
|
||||
app.include_router(
|
||||
analysis_router, prefix=f"{settings.API_V1_STR}/analysis", tags=["analysis"])
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
349
backend/app/services/analysis_service.py
Normal file
349
backend/app/services/analysis_service.py
Normal file
@ -0,0 +1,349 @@
|
||||
from typing import List, Dict, Tuple, Optional
|
||||
import numpy as np
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy.orm import Session
|
||||
from ..models.lottery import SSQLottery, DLTLottery
|
||||
|
||||
|
||||
class LotteryAnalysisService:
|
||||
def __init__(self, db: Session):
|
||||
self.db = db
|
||||
|
||||
def get_hot_cold_numbers(self, lottery_type: str, periods: int = 50) -> Dict:
|
||||
"""分析热号和冷号
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
periods: 分析期数,默认50期
|
||||
|
||||
Returns:
|
||||
Dict: 包含热号和冷号的字典
|
||||
"""
|
||||
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
||||
recent_draws = self.db.query(model).order_by(
|
||||
model.open_time.desc()).limit(periods).all()
|
||||
|
||||
# 初始化号码频率统计
|
||||
red_freq = defaultdict(int)
|
||||
blue_freq = defaultdict(int)
|
||||
|
||||
# 统计号码出现频率
|
||||
for draw in recent_draws:
|
||||
if lottery_type == 'ssq':
|
||||
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
||||
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
||||
for num in red_numbers:
|
||||
red_freq[num] += 1
|
||||
blue_freq[draw.blue_ball] += 1
|
||||
else:
|
||||
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
||||
draw.front_ball_4, draw.front_ball_5]
|
||||
for num in red_numbers:
|
||||
red_freq[num] += 1
|
||||
blue_freq[draw.back_ball_1] += 1
|
||||
blue_freq[draw.back_ball_2] += 1
|
||||
|
||||
# 计算平均出现次数
|
||||
red_avg = sum(red_freq.values()) / len(red_freq)
|
||||
blue_avg = sum(blue_freq.values()) / len(blue_freq)
|
||||
|
||||
# 定义热号和冷号
|
||||
hot_reds = [num for num, freq in red_freq.items() if freq > red_avg]
|
||||
cold_reds = [num for num, freq in red_freq.items() if freq < red_avg]
|
||||
hot_blues = [num for num, freq in blue_freq.items() if freq > blue_avg]
|
||||
cold_blues = [num for num, freq in blue_freq.items()
|
||||
if freq < blue_avg]
|
||||
|
||||
return {
|
||||
'hot_reds': sorted(hot_reds),
|
||||
'cold_reds': sorted(cold_reds),
|
||||
'hot_blues': sorted(hot_blues),
|
||||
'cold_blues': sorted(cold_blues),
|
||||
'red_frequencies': dict(red_freq),
|
||||
'blue_frequencies': dict(blue_freq)
|
||||
}
|
||||
|
||||
def analyze_number_distribution(self, lottery_type: str, periods: int = 100) -> Dict:
|
||||
"""分析号码分布(分区统计、奇偶比)
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
periods: 分析期数,默认100期
|
||||
|
||||
Returns:
|
||||
Dict: 包含各种分布统计的字典
|
||||
"""
|
||||
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
||||
recent_draws = self.db.query(model).order_by(
|
||||
model.open_time.desc()).limit(periods).all()
|
||||
|
||||
# 初始化统计数据
|
||||
zone_stats = defaultdict(int)
|
||||
odd_count = 0
|
||||
even_count = 0
|
||||
total_numbers = 0
|
||||
|
||||
for draw in recent_draws:
|
||||
if lottery_type == 'ssq':
|
||||
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
||||
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
||||
else:
|
||||
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
||||
draw.front_ball_4, draw.front_ball_5]
|
||||
|
||||
# 分区统计
|
||||
for num in red_numbers:
|
||||
# 对于双色球:每5个数字一个区,最后一个区是31-33
|
||||
# 对于大乐透:每5个数字一个区,最后一个区是31-35
|
||||
zone = (num - 1) // 5 + 1
|
||||
zone_stats[zone] += 1
|
||||
|
||||
# 奇偶统计
|
||||
if num % 2 == 0:
|
||||
even_count += 1
|
||||
else:
|
||||
odd_count += 1
|
||||
total_numbers += 1
|
||||
|
||||
# 计算比例
|
||||
zone_distribution = {str(zone): count for zone,
|
||||
count in zone_stats.items()}
|
||||
odd_even_distribution = {
|
||||
'odd': odd_count,
|
||||
'even': even_count
|
||||
}
|
||||
|
||||
return {
|
||||
'zone_distribution': zone_distribution,
|
||||
'odd_even_distribution': odd_even_distribution
|
||||
}
|
||||
|
||||
def analyze_consecutive_numbers(self, lottery_type: str, periods: int = 100) -> Dict:
|
||||
"""分析连号和重复号
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
periods: 分析期数,默认100期
|
||||
|
||||
Returns:
|
||||
Dict: 包含连号和重复号分析的字典
|
||||
"""
|
||||
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
||||
recent_draws = self.db.query(model).order_by(
|
||||
model.open_time.desc()).limit(periods).all()
|
||||
|
||||
consecutive_stats = defaultdict(int)
|
||||
repeat_stats = defaultdict(int)
|
||||
|
||||
prev_numbers = None
|
||||
for draw in recent_draws:
|
||||
if lottery_type == 'ssq':
|
||||
current_numbers = sorted([
|
||||
draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
||||
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6
|
||||
])
|
||||
else:
|
||||
current_numbers = sorted([
|
||||
draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
||||
draw.front_ball_4, draw.front_ball_5
|
||||
])
|
||||
|
||||
# 分析连号
|
||||
consecutive_count = 0
|
||||
for i in range(len(current_numbers)-1):
|
||||
if current_numbers[i+1] - current_numbers[i] == 1:
|
||||
consecutive_count += 1
|
||||
consecutive_stats[consecutive_count] += 1
|
||||
|
||||
# 分析重复号
|
||||
if prev_numbers:
|
||||
repeat_count = len(set(current_numbers) & set(prev_numbers))
|
||||
repeat_stats[repeat_count] += 1
|
||||
|
||||
prev_numbers = current_numbers
|
||||
|
||||
total_draws = len(recent_draws)
|
||||
return {
|
||||
'consecutive_distribution': {k: v/total_draws for k, v in consecutive_stats.items()},
|
||||
'repeat_distribution': {k: v/(total_draws-1) for k, v in repeat_stats.items()}
|
||||
}
|
||||
|
||||
def analyze_mathematical_stats(self, lottery_type: str, periods: int = 100) -> Dict:
|
||||
"""分析数学统计特征
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
periods: 分析期数,默认100期
|
||||
|
||||
Returns:
|
||||
Dict: 包含数学统计特征的字典
|
||||
"""
|
||||
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
||||
recent_draws = self.db.query(model).order_by(
|
||||
model.open_time.desc()).limit(periods).all()
|
||||
|
||||
sums = []
|
||||
for draw in recent_draws:
|
||||
if lottery_type == 'ssq':
|
||||
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
||||
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
||||
else:
|
||||
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
||||
draw.front_ball_4, draw.front_ball_5]
|
||||
sums.append(sum(red_numbers))
|
||||
|
||||
mean = np.mean(sums)
|
||||
std = np.std(sums)
|
||||
|
||||
return {
|
||||
'sum_mean': float(mean),
|
||||
'sum_std': float(std),
|
||||
'sum_range': {
|
||||
'min': float(mean - 2*std),
|
||||
'max': float(mean + 2*std)
|
||||
}
|
||||
}
|
||||
|
||||
def get_missing_periods(self, lottery_type: str, periods: int = 200) -> Dict:
|
||||
"""分析号码遗漏值(仅分析最近periods期,避免全表遍历)
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
periods: 分析期数,默认200期
|
||||
|
||||
Returns:
|
||||
Dict: 包含各号码当前遗漏值的字典
|
||||
"""
|
||||
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
||||
max_red = 33 if lottery_type == 'ssq' else 35
|
||||
max_blue = 16 if lottery_type == 'ssq' else 12
|
||||
|
||||
# 一次性查出最近periods期数据
|
||||
draws = self.db.query(model).order_by(
|
||||
model.open_time.desc()).limit(periods).all()
|
||||
|
||||
# 初始化遗漏值字典
|
||||
red_missing = {i: 0 for i in range(1, max_red + 1)}
|
||||
blue_missing = {i: 0 for i in range(1, max_blue + 1)}
|
||||
|
||||
# 标记号码是否已出现
|
||||
red_found = {i: False for i in range(1, max_red + 1)}
|
||||
blue_found = {i: False for i in range(1, max_blue + 1)}
|
||||
|
||||
for idx, draw in enumerate(draws):
|
||||
if lottery_type == 'ssq':
|
||||
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
||||
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
||||
blue_numbers = [draw.blue_ball]
|
||||
else:
|
||||
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
||||
draw.front_ball_4, draw.front_ball_5]
|
||||
blue_numbers = [draw.back_ball_1, draw.back_ball_2]
|
||||
|
||||
# 红球遗漏统计
|
||||
for i in range(1, max_red + 1):
|
||||
if not red_found[i]:
|
||||
if i in red_numbers:
|
||||
red_found[i] = True
|
||||
red_missing[i] = idx
|
||||
# 蓝球遗漏统计
|
||||
for i in range(1, max_blue + 1):
|
||||
if not blue_found[i]:
|
||||
if i in blue_numbers:
|
||||
blue_found[i] = True
|
||||
blue_missing[i] = idx
|
||||
|
||||
# 未出现过的号码,遗漏值为periods
|
||||
for i in range(1, max_red + 1):
|
||||
if not red_found[i]:
|
||||
red_missing[i] = periods
|
||||
for i in range(1, max_blue + 1):
|
||||
if not blue_found[i]:
|
||||
blue_missing[i] = periods
|
||||
|
||||
return {
|
||||
'red_missing': red_missing,
|
||||
'blue_missing': blue_missing
|
||||
}
|
||||
|
||||
def generate_smart_numbers(self, lottery_type: str, strategy: str = 'balanced', count: int = 1, periods: int = 100) -> List[Dict]:
|
||||
"""智能选号
|
||||
|
||||
Args:
|
||||
lottery_type: 彩票类型 ('ssq' 或 'dlt')
|
||||
strategy: 选号策略 ('balanced', 'hot', 'cold', 'missing')
|
||||
count: 生成注数
|
||||
periods: 分析期数,默认100期
|
||||
|
||||
Returns:
|
||||
List[Dict]: 生成的号码列表
|
||||
"""
|
||||
import random
|
||||
|
||||
# 获取分析数据
|
||||
hot_cold = self.get_hot_cold_numbers(lottery_type, periods)
|
||||
distribution = self.analyze_number_distribution(lottery_type, periods)
|
||||
missing = self.get_missing_periods(lottery_type, periods)
|
||||
|
||||
max_red = 33 if lottery_type == 'ssq' else 35
|
||||
max_blue = 16 if lottery_type == 'ssq' else 12
|
||||
red_count = 6 if lottery_type == 'ssq' else 5
|
||||
blue_count = 1 if lottery_type == 'ssq' else 2
|
||||
|
||||
results = []
|
||||
for _ in range(count):
|
||||
# 根据策略选择红球
|
||||
if strategy == 'hot':
|
||||
red_pool = hot_cold['hot_reds']
|
||||
elif strategy == 'cold':
|
||||
red_pool = hot_cold['cold_reds']
|
||||
elif strategy == 'missing':
|
||||
red_pool = sorted(missing['red_missing'].items(),
|
||||
key=lambda x: x[1], reverse=True)
|
||||
red_pool = [num for num, _ in red_pool[:max_red//2]]
|
||||
else: # balanced
|
||||
red_pool = list(range(1, max_red + 1))
|
||||
|
||||
# 确保红球池不为空且数量足够
|
||||
if not red_pool or len(red_pool) < red_count:
|
||||
red_pool = list(range(1, max_red + 1))
|
||||
|
||||
# 选择红球
|
||||
try:
|
||||
red_numbers = sorted(random.sample(red_pool, red_count))
|
||||
except ValueError:
|
||||
# 如果采样失败,使用全范围随机
|
||||
red_numbers = sorted(random.sample(
|
||||
range(1, max_red + 1), red_count))
|
||||
|
||||
# 选择蓝球
|
||||
if strategy == 'hot':
|
||||
blue_pool = hot_cold['hot_blues']
|
||||
elif strategy == 'cold':
|
||||
blue_pool = hot_cold['cold_blues']
|
||||
elif strategy == 'missing':
|
||||
blue_pool = sorted(missing['blue_missing'].items(),
|
||||
key=lambda x: x[1], reverse=True)
|
||||
blue_pool = [num for num, _ in blue_pool[:max_blue//2]]
|
||||
else: # balanced
|
||||
blue_pool = list(range(1, max_blue + 1))
|
||||
|
||||
# 确保蓝球池不为空且数量足够
|
||||
if not blue_pool or len(blue_pool) < blue_count:
|
||||
blue_pool = list(range(1, max_blue + 1))
|
||||
|
||||
# 选择蓝球
|
||||
try:
|
||||
blue_numbers = sorted(random.sample(blue_pool, blue_count))
|
||||
except ValueError:
|
||||
# 如果采样失败,使用全范围随机
|
||||
blue_numbers = sorted(random.sample(
|
||||
range(1, max_blue + 1), blue_count))
|
||||
|
||||
results.append({
|
||||
'red_numbers': red_numbers,
|
||||
'blue_numbers': blue_numbers
|
||||
})
|
||||
|
||||
return results
|
||||
26
backend/main.py
Normal file
26
backend/main.py
Normal file
@ -0,0 +1,26 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from app.api.endpoints import analysis
|
||||
|
||||
app = FastAPI(
|
||||
title="彩票数据分析系统",
|
||||
description="支持双色球和大乐透的数据管理、统计分析和智能选号功能",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# 配置CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 注册路由
|
||||
app.include_router(analysis.router, prefix="/api/analysis", tags=["analysis"])
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"message": "欢迎使用彩票数据分析系统"}
|
||||
@ -88,7 +88,7 @@ onUnmounted(() => {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
@media screen and (max-width: 1024px) {
|
||||
.el-header {
|
||||
flex-direction: row;
|
||||
height: 50px;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import request from '../utils/request'
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: '/api/v1/lottery'
|
||||
@ -89,5 +90,67 @@ export const lotteryApi = {
|
||||
|
||||
generateDLTNumbers(params) {
|
||||
return api.get('/dlt/generate', { params })
|
||||
},
|
||||
|
||||
// 获取热号冷号分析
|
||||
getHotColdNumbers(lotteryType, params) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/hot-cold/${lotteryType}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
},
|
||||
|
||||
// 获取号码分布分析
|
||||
getNumberDistribution(lotteryType, params) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/distribution/${lotteryType}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
},
|
||||
|
||||
// 获取连号分析
|
||||
getConsecutiveAnalysis(lotteryType, params) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/consecutive/${lotteryType}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
},
|
||||
|
||||
// 获取数学统计特征
|
||||
getMathematicalStats(lotteryType, params) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/math-stats/${lotteryType}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
},
|
||||
|
||||
// 获取遗漏值分析
|
||||
getMissingPeriods(lotteryType) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/missing/${lotteryType}`,
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
|
||||
// 智能选号
|
||||
generateSmartNumbers(lotteryType, params) {
|
||||
return request({
|
||||
url: `/api/v1/analysis/smart-numbers/${lotteryType}`,
|
||||
method: 'get',
|
||||
params: {
|
||||
strategy: params.strategy || 'balanced',
|
||||
count: params.count || 1,
|
||||
periods: params.periods || 100
|
||||
}
|
||||
}).then(response => {
|
||||
if (response && response.data) {
|
||||
return response
|
||||
}
|
||||
throw new Error('返回数据格式错误')
|
||||
})
|
||||
}
|
||||
}
|
||||
40
frontend/src/utils/request.js
Normal file
40
frontend/src/utils/request.js
Normal file
@ -0,0 +1,40 @@
|
||||
import axios from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
baseURL: 'http://localhost:8000', // API的基础URL
|
||||
timeout: 15000 // 请求超时时间
|
||||
})
|
||||
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// 在发送请求之前做些什么
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// 对请求错误做些什么
|
||||
console.error('Request error:', error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
// FastAPI 返回的数据在 response.data 中
|
||||
return response
|
||||
},
|
||||
error => {
|
||||
console.error('Response error:', error)
|
||||
ElMessage({
|
||||
message: error.message || 'Request failed',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user