package usecase import ( "strings" "unicode/utf8" "apps/backend/internal/module/radar/domain" ) type priorityResult struct { Priority, PainFit, DemandIntent, EvidenceQuality, Freshness int Band string Evidence []string } func scoreOpportunityPriority(cand *domain.CandidatePost, result *JudgeResult) priorityResult { if cand == nil || result == nil { return priorityResult{} } intent, freshness, fit := 0, 0, 0 for _, reason := range result.Reasons { switch reason.Dimension { case domain.DimIntent: intent = reason.Score case domain.DimFreshness: freshness = reason.Score case domain.DimFit: fit = reason.Score } } if result.ProductMatch != nil { fit = result.ProductMatch.ProductFitScore } intent100 := intent * 100 / domain.WeightIntent fresh100 := freshness * 100 / domain.WeightFreshness evidence := make([]string, 0, 4) if strings.TrimSpace(cand.MatchedTerm) != "" { evidence = append(evidence, "命中詞:"+strings.TrimSpace(cand.MatchedTerm)) } for _, reason := range result.Reasons { if strings.TrimSpace(reason.Reason) == "" { continue } text := strings.TrimSpace(reason.Reason) if utf8.RuneCountInString(text) > 60 { text = string([]rune(text)[:60]) } evidence = append(evidence, text) if len(evidence) >= 4 { break } } evidenceQuality := len(evidence) * 20 if evidenceQuality > 100 { evidenceQuality = 100 } priority := (intent100*35 + fit*35 + evidenceQuality*20 + fresh100*10) / 100 band := "low" if priority >= 75 { band = "high" } else if priority >= 50 { band = "review" } return priorityResult{Priority: priority, Band: band, PainFit: fit, DemandIntent: intent100, EvidenceQuality: evidenceQuality, Freshness: fresh100, Evidence: evidence} }