/** * TypeScript mirror of the Python WoT threshold formula. * * Core formula: * Result = C + B^W + (M + (1-M) * (1 - (T/W)^G)) * max(0, T - C) * * Where: * C = constant_base * B = base_exponent * W = wot_size (corpus of eligible voters) * T = total_votes (for + against) * M = majority_ratio (majority_pct / 100) * G = gradient_exponent * * Inertia behaviour: * - Low participation (T << W) -> near-unanimity required * - High participation (T -> W) -> simple majority M suffices * * Reference test case: * wot_size=7224, votes_for=97, votes_against=23 (total=120) * params M50 B.1 G.2 => threshold=94, adopted (97 >= 94) */ export function wotThreshold( wotSize: number, totalVotes: number, majorityPct: number = 50, baseExponent: number = 0.1, gradientExponent: number = 0.2, constantBase: number = 0.0, ): number { if (wotSize <= 0) { throw new Error('wotSize doit etre strictement positif') } if (totalVotes < 0) { throw new Error('totalVotes ne peut pas etre negatif') } if (majorityPct < 0 || majorityPct > 100) { throw new Error('majorityPct doit etre entre 0 et 100') } const M = majorityPct / 100 const T = totalVotes const W = wotSize const C = constantBase const B = baseExponent const G = gradientExponent // Guard: if no votes, threshold is at least ceil(C + B^W) if (T === 0) { return Math.ceil(C + Math.pow(B, W)) } // Core formula const participationRatio = T / W const inertiaFactor = 1.0 - Math.pow(participationRatio, G) const requiredRatio = M + (1.0 - M) * inertiaFactor const result = C + Math.pow(B, W) + requiredRatio * Math.max(0, T - C) return Math.ceil(result) } /** * Compute the Smith criterion threshold. * * @param smithWotSize - Number of Smith members * @param smithExponent - Exponent S for the Smith criterion * @returns Minimum number of Smith votes required */ export function smithThreshold(smithWotSize: number, smithExponent: number): number { if (smithWotSize <= 0) return 0 return Math.ceil(Math.pow(smithWotSize, smithExponent)) } /** * Compute the TechComm criterion threshold. * * @param techcommSize - Number of TechComm members * @param techcommExponent - Exponent T for the TechComm criterion * @returns Minimum number of TechComm votes required */ export function techcommThreshold(techcommSize: number, techcommExponent: number): number { if (techcommSize <= 0) return 0 return Math.ceil(Math.pow(techcommSize, techcommExponent)) }