2020-02-13 11:29:06 +00:00
|
|
|
import { Guesstimator } from '@foretold/guesstimator';
|
|
|
|
import { Samples } from '@foretold/cdf';
|
2020-02-13 12:20:46 +00:00
|
|
|
import _ from 'lodash';
|
2020-02-13 11:29:06 +00:00
|
|
|
|
2020-02-13 12:20:46 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param {number} minValue
|
|
|
|
* @param {number} maxValue
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
const minMaxRatio = (minValue, maxValue) => {
|
|
|
|
if (minValue === 0 || maxValue === 0) {
|
|
|
|
return 'SMALL';
|
|
|
|
}
|
|
|
|
const ratio = maxValue / minValue;
|
|
|
|
if (ratio < 100000) {
|
|
|
|
return 'SMALL';
|
|
|
|
} else if (ratio < 10000000) {
|
|
|
|
return 'MEDIUM';
|
|
|
|
} else {
|
|
|
|
return 'LARGE';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param samples
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const ratioSize = samples => {
|
|
|
|
samples.sort();
|
|
|
|
const minValue = samples.getPercentile(2);
|
|
|
|
const maxValue = samples.getPercentile(98);
|
|
|
|
return minMaxRatio(minValue, maxValue);
|
|
|
|
};
|
|
|
|
|
2020-02-15 19:44:18 +00:00
|
|
|
|
2020-02-13 12:20:46 +00:00
|
|
|
const toPdf = (values, sampleCount, min, max) => {
|
2020-02-15 19:44:18 +00:00
|
|
|
let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value();
|
|
|
|
let totalLength = _.size(values);
|
|
|
|
let frequencies = duplicateSamples.map(s => ({value: parseFloat(s), percentage: totalLength/_(values).filter(x => x ==s).size()}));
|
|
|
|
let continuousSamples = _.difference(values, frequencies.map(f => f.value));
|
|
|
|
const samples = new Samples(continuousSamples);
|
2020-02-13 11:29:06 +00:00
|
|
|
|
|
|
|
const ratioSize$ = ratioSize(samples);
|
|
|
|
const width = ratioSize$ === 'SMALL' ? 20 : 1;
|
|
|
|
|
2020-02-13 12:20:46 +00:00
|
|
|
const cdf = samples.toCdf({ size: sampleCount, width, min, max });
|
2020-02-15 19:44:18 +00:00
|
|
|
return {continuous:{ys:cdf.ys, xs:cdf.xs}, discrete: {xs: frequencies.map(f => f.value), ys: frequencies.map(f => f.percentage)}};
|
2020-02-13 11:29:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
2020-02-13 12:20:46 +00:00
|
|
|
let [_error, item] = Guesstimator.parse({ text: "=" + text });
|
2020-02-13 11:29:06 +00:00
|
|
|
const { parsedInput } = item;
|
|
|
|
const { guesstimateType } = parsedInput;
|
|
|
|
|
|
|
|
const guesstimator = new Guesstimator({ parsedInput });
|
|
|
|
const value = guesstimator.sample(
|
|
|
|
sampleCount,
|
|
|
|
inputs,
|
|
|
|
);
|
|
|
|
const samplerType = guesstimator.samplerType();
|
|
|
|
|
|
|
|
const values = _.filter(value.values, _.isFinite);
|
|
|
|
|
|
|
|
let update;
|
|
|
|
if (values.length === 0) {
|
|
|
|
update = {xs: [], ys: []};
|
|
|
|
} else if (values.length === 1) {
|
|
|
|
update = {xs: [], ys: []};
|
|
|
|
} else {
|
2020-02-13 12:20:46 +00:00
|
|
|
update = toPdf(values, sampleCount, min, max);
|
2020-02-13 11:29:06 +00:00
|
|
|
}
|
|
|
|
return update;
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
run,
|
|
|
|
};
|