diff --git a/__tests__/Guesstimator__Test.re b/__tests__/Guesstimator__Test.re new file mode 100644 index 00000000..5cea654c --- /dev/null +++ b/__tests__/Guesstimator__Test.re @@ -0,0 +1,21 @@ +open Jest; +open Expect; + +let makeTest = (~only=false, str, item1, item2) => + only + ? Only.test(str, () => + expect(item1) |> toEqual(item2) + ) + : test(str, () => + expect(item1) |> toEqual(item2) + ) /* })*/; + +// These fail because of issues with Jest, Babel, and Bucklescript +// describe("XYShapes", () => { +// describe("logScorePoint", () => { +// makeTest( +// "When identical", +// Some(Guesstimator.stringToMixedShape(~string="5 to 20")), +// None, +// ) +// }) \ No newline at end of file diff --git a/package.json b/package.json index 5ffd925d..889d5eeb 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "@glennsl/bs-jest": "^0.4.9", "antd": "3.17.0", "autoprefixer": "9.7.4", - "babel-jest": "25.1.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", + "binary-search-tree": "0.2.6", "bs-ant-design-alt": "2.0.0-alpha.33", "bs-css": "11.0.0", "bs-moment": "0.4.4", @@ -42,9 +43,11 @@ "d3": "5.15.0", "gh-pages": "2.2.0", "jest": "^25.1.0", + "jstat": "1.9.2", "lenses-ppx": "5.1.0", "less": "3.10.3", "lodash": "4.17.15", + "mathjs": "6.6.0", "moduleserve": "0.9.1", "moment": "2.24.0", "parcel-bundler": "1.12.4", @@ -55,10 +58,7 @@ "react-dom": "16.12.0", "reason-react": ">=0.7.0", "reschema": "1.3.0", - "tailwindcss": "1.2.0", - "binary-search-tree": "0.2.6", - "jstat": "1.9.2", - "mathjs": "6.6.0" + "tailwindcss": "1.2.0" }, "alias": { "react": "./node_modules/react", diff --git a/src/components/DistBuilder.re b/src/components/DistBuilder.re index 3218a6f7..94dc47da 100644 --- a/src/components/DistBuilder.re +++ b/src/components/DistBuilder.re @@ -148,7 +148,7 @@ let make = () => { ~schema, ~onSubmit=({state}) => {None}, ~initialState={ - guesstimatorString: "mm(5 to 20, floor(normal(20,2)), [.5, .5])", + guesstimatorString: "50 to 50000", domainType: "Complete", xPoint: "50.0", xPoint2: "60.0", @@ -157,9 +157,9 @@ let make = () => { unitType: "UnspecifiedDistribution", zero: MomentRe.momentNow(), unit: "days", - sampleCount: "1000", - outputXYPoints: "2000", - truncateTo: "500", + sampleCount: "10000", + outputXYPoints: "5000", + truncateTo: "1000", }, (), ); @@ -465,4 +465,4 @@ let make = () => {
; -}; +}; \ No newline at end of file diff --git a/src/utility/Guesstimator.re b/src/utility/Guesstimator.re index 1e4bf9f4..81613ff4 100644 --- a/src/utility/Guesstimator.re +++ b/src/utility/Guesstimator.re @@ -26,7 +26,14 @@ module Internals = { discreteGet(r) |> jsToDistDiscrete; [@bs.module "./GuesstimatorLibrary.js"] - external toCombinedFormat: (string, int, int) => combined = "run"; + external toCombinedFormat: (string, int, int, int) => combined = "run"; + + [@bs.module "./GuesstimatorLibrary.js"] + external stringToSamples: (string, int) => array(float) = "stringToSamples"; + + [@bs.module "./GuesstimatorLibrary.js"] + external samplesToContinuousPdf: (array(float), int, int) => array(float) = + "samplesToContinuousPdf"; // todo: Format to correct mass, also normalize the pdf. let toMixedShape = @@ -44,8 +51,8 @@ module Internals = { // let discreteProb = // d |> Distributions.Discrete.T.Integral.sum(~cache=None); - let foo = MixedShapeBuilder.buildSimple(~continuous, ~discrete); - foo; + let shape = MixedShapeBuilder.buildSimple(~continuous, ~discrete); + shape; }; }; @@ -54,8 +61,9 @@ let stringToMixedShape = ~string, ~sampleCount=3000, ~outputXYPoints=3000, + ~width=3000, ~truncateTo=Some(500), (), ) => - Internals.toCombinedFormat(string, sampleCount, outputXYPoints) + Internals.toCombinedFormat(string, sampleCount, outputXYPoints, width) |> Internals.toMixedShape(~truncateTo); \ No newline at end of file diff --git a/src/utility/GuesstimatorLibrary.js b/src/utility/GuesstimatorLibrary.js index 8fdcb7f7..eda4803e 100644 --- a/src/utility/GuesstimatorLibrary.js +++ b/src/utility/GuesstimatorLibrary.js @@ -1,38 +1,8 @@ -import { Guesstimator } from '@foretold/guesstimator/src'; -import { Samples } from '@foretold/cdf/lib/samples'; -import _ from 'lodash'; - -/** - * - * @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 < 10000) { - return 'SMALL'; - } else if (ratio < 1000000) { - 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); -}; - +const { + Samples, +} = require("@foretold/cdf/lib/samples"); +const _ = require("lodash"); +const { Guesstimator } = require('@foretold/guesstimator/src'); /** * @param values @@ -41,7 +11,7 @@ const ratioSize = samples => { * @param max * @returns {{discrete: {ys: *, xs: *}, continuous: {ys: [], xs: []}}} */ -const toPdf = (values, outputResolutionCount, min, max) => { +const toPdf = (values, outputResolutionCount, width, min, max) => { let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value(); let totalLength = _.size(values); let frequencies = duplicateSamples.map(s => ({ @@ -57,12 +27,13 @@ const toPdf = (values, outputResolutionCount, min, max) => { let continuous = { ys: [], xs: [] }; if (continuousSamples.length > 20) { - const samples = new Samples(continuousSamples); - - const ratioSize$ = ratioSize(samples); - const width = ratioSize$ === 'SMALL' ? 60 : 1; + // let c = continuousSamples.map( r => (Math.log2(r)) * 1000); + let c = continuousSamples; + const samples = new Samples(c); + const pdf = samples.toPdf({ size: outputResolutionCount, width, min, max }); + // continuous = {xs: pdf.xs.map(r => Math.pow(2,r/1000)), ys: pdf.ys}; continuous = pdf; } @@ -82,6 +53,7 @@ const run = ( text, sampleCount, outputResolutionCount, + width, inputs = [], min = false, max = false, @@ -107,11 +79,46 @@ const run = ( } else if (values.length === 1) { update = blankResponse; } else { - update = toPdf(values, outputResolutionCount, min, max); + update = toPdf(values, outputResolutionCount, width, min, max); } return update; }; +const stringToSamples = ( + text, + sampleCount, + inputs = [], +) => { + const [_error, item] = Guesstimator.parse({ text }); + if (_error){ + return [] + } + const { parsedInput } = item; + + const guesstimator = new Guesstimator({ parsedInput }); + const value = guesstimator.sample( + sampleCount, + inputs, + ); + return value.values +}; + + +const samplesToContinuousPdf = ( + samples, + outputResolutionCount, + width, + min = false, + max = false, +) => { + const values = _.filter(samples, _.isFinite); + const _samples = new Samples(values); + const pdf = _samples.toPdf({ size: outputResolutionCount, width, min, max }); + return pdf; +}; + module.exports = { run, + stringToSamples, + samplesToContinuousPdf }; diff --git a/yarn.lock b/yarn.lock index 97f788e8..f536bd31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2146,18 +2146,14 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== -babel-jest@25.1.0, babel-jest@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.1.0.tgz#206093ac380a4b78c4404a05b3277391278f80fb" - integrity sha512-tz0VxUhhOE2y+g8R2oFrO/2VtVjA1lkJeavlhExuRBg3LdNJY9gwQ+Vcvqt9+cqy71MCTJhewvTB7Qtnnr9SWg== +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: - "@jest/transform" "^25.1.0" - "@jest/types" "^25.1.0" - "@types/babel__core" "^7.1.0" - babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^25.1.0" - chalk "^3.0.0" - slash "^3.0.0" + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" babel-jest@^24.9.0: version "24.9.0" @@ -2172,6 +2168,26 @@ babel-jest@^24.9.0: chalk "^2.4.2" slash "^2.0.0" +babel-jest@^25.1.0: + version "25.1.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.1.0.tgz#206093ac380a4b78c4404a05b3277391278f80fb" + integrity sha512-tz0VxUhhOE2y+g8R2oFrO/2VtVjA1lkJeavlhExuRBg3LdNJY9gwQ+Vcvqt9+cqy71MCTJhewvTB7Qtnnr9SWg== + dependencies: + "@jest/transform" "^25.1.0" + "@jest/types" "^25.1.0" + "@types/babel__core" "^7.1.0" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^25.1.0" + chalk "^3.0.0" + slash "^3.0.0" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" @@ -2244,6 +2260,24 @@ babel-plugin-syntax-jsx@^6.18.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= +babel-plugin-transform-es2015-modules-commonjs@^6.26.2: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + babel-preset-jest@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" @@ -2261,7 +2295,7 @@ babel-preset-jest@^25.1.0: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" babel-plugin-jest-hoist "^25.1.0" -babel-runtime@6.x, babel-runtime@^6.11.6, babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-runtime@6.x, babel-runtime@^6.11.6, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -2269,7 +2303,33 @@ babel-runtime@6.x, babel-runtime@^6.11.6, babel-runtime@^6.23.0, babel-runtime@^ core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-types@^6.15.0: +babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.15.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= @@ -2288,6 +2348,11 @@ babylon-walk@^1.0.2: babel-types "^6.15.0" lodash.clone "^4.5.0" +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + backo2@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -3620,7 +3685,7 @@ deasync@^0.1.14: bindings "^1.5.0" node-addon-api "^1.7.1" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -4589,6 +4654,11 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -6145,6 +6215,11 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + js-yaml@^3.10.0, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"