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 }