"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfidenceEngine = void 0;
const types_1 = require("../types");
class ConfidenceEngine {
    priorWeight;
    constructor(priorWeight = 10) {
        this.priorWeight = priorWeight;
    }
    computeConfidence(positiveSignals, negativeSignals, usageCount = 0, acceptanceRate = 0.5) {
        const priorAlpha = 0.5 * this.priorWeight;
        const priorBeta = 0.5 * this.priorWeight;
        const alpha = positiveSignals + priorAlpha;
        const beta = negativeSignals + priorBeta;
        const mean = alpha / (alpha + beta);
        const ci95Lower = this.betaPPF(0.025, alpha, beta);
        const ci95Upper = this.betaPPF(0.975, alpha, beta);
        const totalTrials = positiveSignals + negativeSignals;
        const frequency = totalTrials > 0 ? Math.min(totalTrials / 100, 1) : 0;
        const consistency = totalTrials > 0
            ? 1 - Math.abs(0.5 - positiveSignals / totalTrials) * 2
            : 0;
        const usage = Math.min(usageCount / 50, 1);
        return {
            distribution: 'beta',
            alpha,
            beta,
            mean: Math.round(mean * 1000) / 1000,
            ci95: [Math.round(ci95Lower * 1000) / 1000, Math.round(ci95Upper * 1000) / 1000],
            factors: {
                frequency: Math.round(frequency * 1000) / 1000,
                consistency: Math.round(consistency * 1000) / 1000,
                usageCount: usageCount,
                acceptanceRate: Math.round(acceptanceRate * 1000) / 1000,
            },
        };
    }
    computeCompositeScore(confidence) {
        const baseMean = confidence.mean * 100;
        const factors = confidence.factors;
        if (!factors)
            return Math.round(baseMean);
        const freqBonus = factors.frequency * 5;
        const consistBonus = factors.consistency * 10;
        const acceptBonus = factors.acceptanceRate * 5;
        const score = baseMean + freqBonus + consistBonus + acceptBonus;
        return Math.round(Math.min(score, 100));
    }
    getTier(confidence) {
        const mean = confidence.mean;
        if (mean >= types_1.CONFIDENCE_TIERS.strong.min)
            return 'strong';
        if (mean >= types_1.CONFIDENCE_TIERS.moderate.min)
            return 'moderate';
        if (mean >= types_1.CONFIDENCE_TIERS.weak.min)
            return 'weak';
        return 'uncertain';
    }
    betaPPF(p, alpha, beta) {
        if (p <= 0)
            return 0;
        if (p >= 1)
            return 1;
        let guess = alpha / (alpha + beta);
        for (let i = 0; i < 100; i++) {
            const cdf = this.betaCDF(guess, alpha, beta);
            const pdf = this.betaPDF(guess, alpha, beta);
            if (pdf === 0)
                break;
            const diff = cdf - p;
            if (Math.abs(diff) < 1e-10)
                break;
            guess = Math.max(1e-10, Math.min(1 - 1e-10, guess - diff / pdf));
        }
        return guess;
    }
    betaCDF(x, alpha, beta) {
        return this.regularizedIncompleteBeta(x, alpha, beta);
    }
    betaPDF(x, alpha, beta) {
        if (x <= 0 || x >= 1)
            return 0;
        const logPdf = (alpha - 1) * Math.log(x) +
            (beta - 1) * Math.log(1 - x) -
            this.logBeta(alpha, beta);
        return Math.exp(logPdf);
    }
    logBeta(a, b) {
        return this.logGamma(a) + this.logGamma(b) - this.logGamma(a + b);
    }
    logGamma(x) {
        if (x <= 0)
            throw new Error(`logGamma undefined for x=${x}`);
        let sum = (x - 0.5) * Math.log(x) - x + 0.5 * Math.log(2 * Math.PI);
        let term = x;
        sum += 1 / (12 * term);
        term *= x * x;
        sum -= 1 / (360 * term);
        term *= x * x;
        sum += 1 / (1260 * term);
        return sum;
    }
    regularizedIncompleteBeta(x, a, b) {
        if (x <= 0)
            return 0;
        if (x >= 1)
            return 1;
        const maxIterations = 200;
        const epsilon = 1e-10;
        const logFront = this.logGamma(a + b) - this.logGamma(a) - this.logGamma(b) + a * Math.log(x) + b * Math.log(1 - x);
        let front;
        if (logFront > 700)
            front = 1e300;
        else if (logFront < -700)
            front = 0;
        else
            front = Math.exp(logFront);
        let c = 1;
        let d = 1 - ((a + b) * x) / (a + 1);
        if (Math.abs(d) < epsilon)
            d = epsilon;
        d = 1 / d;
        let h = d;
        for (let m = 1; m <= maxIterations; m++) {
            const m2 = 2 * m;
            let aa = (m * (b - m) * x) / ((a + m2 - 1) * (a + m2));
            d = 1 + aa * d;
            if (Math.abs(d) < epsilon)
                d = epsilon;
            c = 1 + aa / c;
            if (Math.abs(c) < epsilon)
                c = epsilon;
            d = 1 / d;
            h *= d * c;
            aa = (-(a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
            d = 1 + aa * d;
            if (Math.abs(d) < epsilon)
                d = epsilon;
            c = 1 + aa / c;
            if (Math.abs(c) < epsilon)
                c = epsilon;
            d = 1 / d;
            const del = d * c;
            h *= del;
            if (Math.abs(del - 1) < epsilon)
                break;
        }
        return (front * h) / a;
    }
}
exports.ConfidenceEngine = ConfidenceEngine;
//# sourceMappingURL=confidence-engine.js.map