// Minimum keyword overlap score to consider a spec "relevant"
const RELEVANCE_THRESHOLD = 0.3;
// Minimum similarity score (0-1) to flag a pattern as a duplicate
const DEDUP_THRESHOLD = 0.8;
// ---------------------------------------------------------------------------
// extractKeywords
// ---------------------------------------------------------------------------
export function extractKeywords(text) {
    return text
        .toLowerCase()
        .replace(/[^a-z0-9\s]/g, ' ')
        .split(/\s+/)
        .filter((w) => w.length >= 3)
        .filter((w) => !STOP_WORDS.has(w));
}
// ---------------------------------------------------------------------------
// computeJaccardSimilarity
// ---------------------------------------------------------------------------
export function computeJaccardSimilarity(a, b) {
    if (a.length === 0 && b.length === 0) {
        return 1;
    }
    const setA = new Set(a);
    const setB = new Set(b);
    const intersection = [...setA].filter((w) => setB.has(w)).length;
    const union = new Set([...setA, ...setB]).size;
    return union === 0 ? 0 : intersection / union;
}
// ---------------------------------------------------------------------------
// findBestSpec
// Returns the specId with the best keyword overlap for the given pattern.
// Returns null if no spec scores above RELEVANCE_THRESHOLD.
// ROUTER / DISPATCHER PATTERN: Jaccard similarity routes patterns to the best-matching spec.
// See DESIGN_PATTERNS.md § Router / Dispatcher Pattern.
// ---------------------------------------------------------------------------
export function findBestSpec(patternKeywords, specs) {
    let bestId = null;
    let bestScore = RELEVANCE_THRESHOLD;
    for (const spec of specs) {
        const score = computeJaccardSimilarity(patternKeywords, spec.keywords);
        if (score > bestScore) {
            bestScore = score;
            bestId = spec.specId;
        }
    }
    return bestId;
}
// ---------------------------------------------------------------------------
// isDuplicate
// Returns true if the pattern is semantically equivalent (>80% Jaccard) to
// any existing criterion across all specs.
// ---------------------------------------------------------------------------
export function isDuplicate(patternKeywords, specs) {
    let bestSimilarity = 0;
    let existingSpecId = null;
    let existingCriterion = null;
    for (const spec of specs) {
        for (const criterion of spec.criteria) {
            const criterionKeywords = extractKeywords(criterion);
            const similarity = computeJaccardSimilarity(patternKeywords, criterionKeywords);
            if (similarity > bestSimilarity) {
                bestSimilarity = similarity;
                existingSpecId = spec.specId;
                existingCriterion = criterion;
            }
        }
    }
    return {
        isDuplicate: bestSimilarity >= DEDUP_THRESHOLD,
        existingSpecId,
        existingCriterion,
        similarity: Math.round(bestSimilarity * 100),
    };
}
// ---------------------------------------------------------------------------
// formatCriterion
// Converts a natural language description into a HU-style criterion.
// ---------------------------------------------------------------------------
export function formatCriterion(description) {
    const trimmed = description.trim();
    // If it already has "Si [...] entonces [...]" or "La herramienta..." format, keep it
    if (/^(si |la herramienta|el sistema|the system|if )/i.test(trimmed)) {
        return trimmed;
    }
    // Otherwise wrap in a simple imperative form
    return `El sistema ${trimmed.charAt(0).toLowerCase()}${trimmed.slice(1)}`;
}
// ---------------------------------------------------------------------------
// Stop words for keyword extraction
// ---------------------------------------------------------------------------
const STOP_WORDS = new Set([
    'the',
    'and',
    'for',
    'are',
    'but',
    'not',
    'you',
    'all',
    'can',
    'had',
    'her',
    'was',
    'one',
    'our',
    'out',
    'day',
    'get',
    'has',
    'him',
    'his',
    'how',
    'its',
    'may',
    'now',
    'old',
    'see',
    'two',
    'who',
    'did',
    'que',
    'con',
    'una',
    'los',
    'las',
    'del',
    'por',
    'para',
    'como',
    'este',
    'esta',
    'cuando',
    'desde',
    'hasta',
    'sobre',
    'cada',
    'debe',
    'should',
    'when',
    'with',
    'that',
    'this',
    'from',
    'have',
    'been',
    'will',
    'they',
    'were',
    'would',
    'could',
    'then',
    'than',
    'also',
    'into',
    'more',
]);
//# sourceMappingURL=learning-router.js.map