package scheduler import ( "strings" "veola/internal/apify" ) // ShouldAlert returns true if the result should trigger an alert. // // - Result must not already be in DB (caller checks that first). // - If targetPrice is nil, alert on every new result. // - If targetPrice is non-nil, alert only when price <= targetPrice. // // price=0 is treated as "unknown" and never alerts under a target. func ShouldAlert(targetPrice *float64, price float64) bool { if targetPrice == nil { return true } if price <= 0 { return false } return price <= *targetPrice } // FilterResults applies match-confidence and out-of-stock filtering. Returns // a fresh slice; the input is not mutated. func FilterResults(in []apify.UnifiedResult, minConfidence float64, includeOOS bool) []apify.UnifiedResult { out := make([]apify.UnifiedResult, 0, len(in)) for _, r := range in { if !includeOOS && r.OutOfStock { continue } if r.MatchConfidence != 0 && r.MatchConfidence < minConfidence { continue } if r.URL == "" || r.Price <= 0 { continue } out = append(out, r) } return out } // ApplyItemFilters drops results below minPrice (when set) and any whose title // contains one of excludeKeywords (case-insensitive substring match). Pass nil // or empty for either to skip that filter. Returns a fresh slice. func ApplyItemFilters(in []apify.UnifiedResult, minPrice *float64, excludeKeywords []string) []apify.UnifiedResult { lowered := make([]string, 0, len(excludeKeywords)) for _, k := range excludeKeywords { k = strings.ToLower(strings.TrimSpace(k)) if k != "" { lowered = append(lowered, k) } } out := make([]apify.UnifiedResult, 0, len(in)) outer: for _, r := range in { if minPrice != nil && r.Price < *minPrice { continue } if len(lowered) > 0 { title := strings.ToLower(r.Title) for _, k := range lowered { if strings.Contains(title, k) { continue outer } } } out = append(out, r) } return out } // PickBest returns the index of the lowest-priced result, or -1 if none. func PickBest(rs []apify.UnifiedResult) int { best := -1 for i, r := range rs { if best == -1 || r.Price < rs[best].Price { best = i } } return best }