"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sum = sum;
exports.average = average;
exports.median = median;
exports.min = min;
exports.max = max;
exports.range = range;
exports.countNonNull = countNonNull;
exports.distinctCount = distinctCount;
exports.nonNullArray = nonNullArray;
exports.variance = variance;
exports.stdDeviation = stdDeviation;
exports.firstNonNull = firstNonNull;
exports.lastNonNull = lastNonNull;
exports.difference = difference;
exports.differencePercent = differencePercent;
function sum(arr, accessor) {
    return arr.reduce((acc, d) => {
        const value = accessor(d);
        return {
            sum: acc.sum + (value !== null ? value : 0),
            validCount: value !== null ? acc.validCount + 1 : acc.validCount,
        };
    }, { sum: 0, validCount: 0 });
}
function average(arr, accessor) {
    const total = sum(arr, accessor);
    if (total.validCount === 0)
        return NaN;
    return total.sum / total.validCount;
}
function median(input, accessor) {
    const arr = input.reduce((acc, d) => {
        const value = accessor(d);
        if (value !== null) {
            acc.push(value);
        }
        return acc;
    }, []);
    if (!arr.length)
        return NaN;
    const s = arr.slice().sort((a, b) => a - b);
    const mid = Math.floor(s.length / 2);
    if (s.length % 2) {
        return s[mid] ?? NaN;
    }
    return ((s[mid - 1] ?? NaN) + (s[mid] ?? NaN)) / 2;
}
function min(arr, accessor) {
    if (arr.length === 0)
        return NaN;
    return arr.reduce((m, d) => {
        const value = accessor(d);
        return value !== null ? Math.min(m, value) : m;
    }, +Infinity);
}
function max(arr, accessor) {
    if (arr.length === 0)
        return NaN;
    return arr.reduce((m, d) => {
        const value = accessor(d);
        return value !== null ? Math.max(m, value) : m;
    }, -Infinity);
}
function range(arr, accessor) {
    if (arr.length === 0)
        return NaN;
    const minMax = arr.reduce((m, d) => {
        const value = accessor(d);
        return {
            max: value !== null ? Math.max(m.max, value) : m.max,
            min: value !== null ? Math.min(m.min, value) : m.min,
        };
    }, { min: +Infinity, max: -Infinity });
    return minMax.max - minMax.min;
}
function countNonNull(arr, accessor) {
    return arr.filter((d) => accessor(d) !== null).length;
}
function distinctCount(arr, accessor) {
    return new Set(nonNullArray(arr, accessor)).size;
}
function nonNullArray(arr, accessor) {
    return arr.reduce((acc, d) => {
        const value = accessor(d);
        if (value !== null) {
            acc.push(value);
        }
        return acc;
    }, []);
}
function variance(arr, accessor) {
    const nonNullArr = nonNullArray(arr, accessor);
    const ddof = 1;
    const total = sum(nonNullArr, (d) => d);
    const avg = total.sum / total.validCount;
    const squareDiffs = nonNullArr.map((d) => {
        return Math.abs(Math.pow(d - avg, 2));
    });
    const totalSumOfSquareDiffs = sum(squareDiffs, (d) => d);
    return totalSumOfSquareDiffs.sum / (totalSumOfSquareDiffs.validCount - ddof);
}
function stdDeviation(arr, accessor) {
    const v = variance(arr, accessor);
    const std = Math.sqrt(v);
    return std;
}
function firstNonNull(arr, accessor) {
    for (let i = 0; i < arr.length; i++) {
        const item = arr[i];
        if (!item)
            continue;
        const value = accessor(item);
        if (value) {
            return value;
        }
    }
    return null;
}
function lastNonNull(arr, accessor) {
    for (let i = arr.length - 1; i >= 0; i--) {
        const item = arr[i];
        if (!item)
            continue;
        const value = accessor(item);
        if (value) {
            return value;
        }
    }
    return null;
}
function difference(arr, accessor) {
    const first = firstNonNull(arr, accessor);
    const last = lastNonNull(arr, accessor);
    if (first !== null && last !== null) {
        return last - first;
    }
    return null;
}
function differencePercent(arr, accessor) {
    const first = firstNonNull(arr, accessor);
    const last = lastNonNull(arr, accessor);
    if (first !== null && last !== null) {
        return (last - first) / last;
    }
    return null;
}
//# sourceMappingURL=aggregations.js.map