This commit is contained in:
2026-01-14 14:17:38 +08:00
commit f1e2ff6563
126 changed files with 13636 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
package service
import (
"fmt"
"ssq-desk/internal/storage/models"
"ssq-desk/internal/storage/repository"
)
// QueryService 查询服务
type QueryService struct {
repo repository.SsqRepository
}
// NewQueryService 创建查询服务
func NewQueryService(repo repository.SsqRepository) *QueryService {
return &QueryService{repo: repo}
}
// QueryRequest 查询请求
type QueryRequest struct {
RedBalls []int `json:"red_balls"` // 红球列表最多6个
BlueBall int `json:"blue_ball"` // 蓝球0表示不限制
BlueBallRange []int `json:"blue_ball_range"` // 蓝球筛选范围
}
// QueryResult 查询结果
type QueryResult struct {
Total int64 `json:"total"` // 总记录数
Summary []MatchSummary `json:"summary"` // 分类统计
Details []models.SsqHistory `json:"details"` // 详细记录
}
// MatchSummary 匹配统计
type MatchSummary struct {
Type string `json:"type"` // 匹配类型:如 "6红1蓝"
Count int `json:"count"` // 匹配数量
Histories []models.SsqHistory `json:"histories"` // 匹配的记录
}
// Query 执行查询
func (s *QueryService) Query(req QueryRequest) (*QueryResult, error) {
// 验证输入
if err := s.validateRequest(req); err != nil {
return nil, err
}
// 查询数据
histories, err := s.repo.FindByRedAndBlue(req.RedBalls, req.BlueBall, req.BlueBallRange)
if err != nil {
return nil, fmt.Errorf("查询失败: %v", err)
}
// 处理结果:分类统计
summary := s.calculateSummary(histories, req.RedBalls, req.BlueBall)
return &QueryResult{
Total: int64(len(histories)),
Summary: summary,
Details: histories,
}, nil
}
// validateRequest 验证请求参数
func (s *QueryService) validateRequest(req QueryRequest) error {
// 验证红球
if len(req.RedBalls) > 6 {
return fmt.Errorf("红球数量不能超过6个")
}
for _, ball := range req.RedBalls {
if ball < 1 || ball > 33 {
return fmt.Errorf("红球号码必须在1-33之间: %d", ball)
}
}
// 验证蓝球
if req.BlueBall > 0 {
if req.BlueBall < 1 || req.BlueBall > 16 {
return fmt.Errorf("蓝球号码必须在1-16之间: %d", req.BlueBall)
}
}
// 验证蓝球范围
for _, ball := range req.BlueBallRange {
if ball < 1 || ball > 16 {
return fmt.Errorf("蓝球筛选范围必须在1-16之间: %d", ball)
}
}
return nil
}
// calculateSummary 计算分类统计
func (s *QueryService) calculateSummary(histories []models.SsqHistory, redBalls []int, blueBall int) []MatchSummary {
if len(redBalls) == 0 {
return []MatchSummary{}
}
// 创建红球集合,用于快速查找
redBallSet := make(map[int]bool)
for _, ball := range redBalls {
redBallSet[ball] = true
}
// 初始化统计
typeCounts := make(map[string][]models.SsqHistory)
// 遍历每条记录,计算匹配度
for _, history := range histories {
// 统计匹配的红球数量
matchedRedCount := 0
if redBallSet[history.RedBall1] {
matchedRedCount++
}
if redBallSet[history.RedBall2] {
matchedRedCount++
}
if redBallSet[history.RedBall3] {
matchedRedCount++
}
if redBallSet[history.RedBall4] {
matchedRedCount++
}
if redBallSet[history.RedBall5] {
matchedRedCount++
}
if redBallSet[history.RedBall6] {
matchedRedCount++
}
// 判断蓝球是否匹配
blueMatched := false
if blueBall > 0 {
blueMatched = history.BlueBall == blueBall
} else {
blueMatched = true // 未指定蓝球时,视为匹配
}
// 生成类型键
typeKey := fmt.Sprintf("%d红", matchedRedCount)
if blueMatched {
typeKey += "1蓝"
}
typeCounts[typeKey] = append(typeCounts[typeKey], history)
}
// 转换为结果格式,按匹配度排序
summary := make([]MatchSummary, 0)
types := []string{"6红1蓝", "6红", "5红1蓝", "5红", "4红1蓝", "4红", "3红1蓝", "3红", "2红1蓝", "2红", "1红1蓝", "1红", "0红1蓝", "0红"}
for _, t := range types {
if histories, ok := typeCounts[t]; ok {
summary = append(summary, MatchSummary{
Type: t,
Count: len(histories),
Histories: histories,
})
}
}
return summary
}