// ─── CAPACITY ESTIMATION ALGORITHM ───function estimateCapacity(threads, avgResponseMs, targetPerDay) {const SECONDS_PER_DAY = 86400;const responseTimeSec = avgResponseMs / 1000;// Core throughput calculationconst rps = threads / responseTimeSec;const dailyCapacity = rps * SECONDS_PER_DAY;// Utilization & headroomconst utilization = targetPerDay / dailyCapacity;const headroom = Math.max(0, 1 - utilization);return {
rps,
dailyCapacity,
utilization,// ≤1.0 means OKheadroom,// spare capacity %isOverloaded: utilization > 1.0};
}// ─── MONTE CARLO SUPPLIER SIMULATION ───function simulateSuppliers(suppliers, samples, threads) {const latencies = [];let successCount = 0;for (let i = 0; i < samples; i++) {let requestSuccess = true;let maxLatency = 0;for (const supplier of suppliers) {// Bernoulli trial for success/failureif (Math.random() > supplier.successRate) {
requestSuccess = false;break;
}// Log-normal latency sampling// Derive σ and μ from mean & P95const sigma = deriveSigma(supplier.mean, supplier.p95);const mu = Math.log(supplier.mean) - (sigma² / 2);const latency = logNormalSample(mu, sigma);
maxLatency = Math.max(maxLatency, latency);
}if (requestSuccess) {
successCount++;
latencies.push(maxLatency);
}
}// Calculate percentileslatencies.sort((a, b) => a - b);const p = (pct) => latencies[Math.floor(pct * latencies.length)];const meanLatency = average(latencies);const rps = threads / (meanLatency / 1000);const dailyCapacity = rps * 86400;return {
successRate: successCount / samples,
meanLatency,
p50: p(0.50),
p90: p(0.90),
p95: p(0.95),
p99: p(0.99),
rps,
dailyCapacity
};
}// ─── ANNUAL IMPACT CALCULATION ───function calculateBusinessImpact(fastCapacity, slowCapacity, revenuePerRequest) {const lostPerDay = fastCapacity - slowCapacity;const lostPerYear = lostPerDay * 365;const lostRevenue = lostPerYear * revenuePerRequest;return {
lostPerDay,// e.g. 200,000lostPerYear,// e.g. 73,000,000lostRevenue,// e.g. $3,650,000percentageLoss: ((fastCapacity - slowCapacity) / fastCapacity * 100).toFixed(1) + "%"};
}