"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatSignificanceLevel = exports.computeChi2PValue = void 0; var _constants = require("./constants"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const criticalTableLookup = (chi2Statistic, df) => { if (df < 1) return 1; if (!Number.isInteger(df)) throw Error('Degrees of freedom must be a valid integer'); // Get the row index const rowIndex = df - 1; // Get the column index let minDiff = Math.abs(_constants.CRITICAL_VALUES_TABLE[rowIndex][0] - chi2Statistic); let columnIndex = 0; for (let j = 1; j < _constants.CRITICAL_VALUES_TABLE[rowIndex].length; j++) { const diff = Math.abs(_constants.CRITICAL_VALUES_TABLE[rowIndex][j] - chi2Statistic); if (diff < minDiff) { minDiff = diff; columnIndex = j; } } const significanceLevel = _constants.SIGNIFICANCE_LEVELS[columnIndex]; return significanceLevel; }; /** * Compute the p-value for how similar the datasets are. * Returned value ranges from 0 to 1, with 1 meaning the datasets are identical. * @param normalizedBaselineTerms * @param normalizedDriftedTerms */ const computeChi2PValue = (normalizedBaselineTerms, normalizedDriftedTerms) => { // Get all unique keys from both arrays const allKeys = Array.from(new Set([...normalizedBaselineTerms.map(term => term.key.toString()), ...normalizedDriftedTerms.map(term => term.key.toString())])).slice(0, 100); // Calculate the chi-squared statistic and degrees of freedom let chiSquared = 0; const degreesOfFreedom = allKeys.length - 1; if (degreesOfFreedom === 0) return 1; allKeys.forEach(key => { var _driftedTerm$percenta, _baselineTerm$percent; const baselineTerm = normalizedBaselineTerms.find(term => term.key === key); const driftedTerm = normalizedDriftedTerms.find(term => term.key === key); const observed = (_driftedTerm$percenta = driftedTerm === null || driftedTerm === void 0 ? void 0 : driftedTerm.percentage) !== null && _driftedTerm$percenta !== void 0 ? _driftedTerm$percenta : 0; const expected = (_baselineTerm$percent = baselineTerm === null || baselineTerm === void 0 ? void 0 : baselineTerm.percentage) !== null && _baselineTerm$percent !== void 0 ? _baselineTerm$percent : 0; chiSquared += Math.pow(observed - expected, 2) / (expected > 0 ? expected : 1e-6); // Prevent divide by zero }); return criticalTableLookup(chiSquared, degreesOfFreedom); }; /** * formatSignificanceLevel * @param significanceLevel */ exports.computeChi2PValue = computeChi2PValue; const formatSignificanceLevel = significanceLevel => { if (typeof significanceLevel !== 'number' || isNaN(significanceLevel)) return ''; if (significanceLevel < 1e-6) { return '< 0.000001'; } else if (significanceLevel < 0.01) { return significanceLevel.toExponential(0); } else { return significanceLevel.toFixed(2); } }; exports.formatSignificanceLevel = formatSignificanceLevel;