From c99a7c508574b924447523e77da70aed90c9f806 Mon Sep 17 00:00:00 2001 From: Roman Galochkin Date: Thu, 27 Feb 2020 15:09:04 +0300 Subject: [PATCH] Works, the first step --- src/App.re | 7 + src/components/DistBuilder2.re | 149 ++++++++++++++++++ .../DistributionPlot/DistributionPlot.re | 2 +- src/components/editor/distribution.js | 8 + src/components/editor/index.js | 31 ---- src/components/editor/main.js | 2 + 6 files changed, 167 insertions(+), 32 deletions(-) create mode 100644 src/components/DistBuilder2.re delete mode 100644 src/components/editor/index.js diff --git a/src/App.re b/src/App.re index 95c76f31..058f25fa 100644 --- a/src/App.re +++ b/src/App.re @@ -1,6 +1,7 @@ type route = | Model(string) | DistBuilder + | DistBuilder2 | Home | NotFound; @@ -8,6 +9,7 @@ let routeToPath = route => switch (route) { | Model(modelId) => "/m/" ++ modelId | DistBuilder => "/dist-builder" + | DistBuilder2 => "/dist-builder2" | Home => "/" | _ => "/" }; @@ -76,6 +78,9 @@ module Menu = { {"Dist Builder" |> E.ste} + + {"Dist Builder 2" |> E.ste} + ; }; }; @@ -88,6 +93,7 @@ let make = () => { switch (url.path) { | ["m", modelId] => Model(modelId) | ["dist-builder"] => DistBuilder + | ["dist-builder2"] => DistBuilder2 | [] => Home | _ => NotFound }; @@ -101,6 +107,7 @@ let make = () => { | None =>
{"Page is not found" |> E.ste}
} | DistBuilder => + | DistBuilder2 => | Home =>
{"Welcome" |> E.ste}
| _ =>
{"Page is not found" |> E.ste}
}} diff --git a/src/components/DistBuilder2.re b/src/components/DistBuilder2.re new file mode 100644 index 00000000..56986523 --- /dev/null +++ b/src/components/DistBuilder2.re @@ -0,0 +1,149 @@ +open BsReform; +open Antd.Grid; + +type shape = (array(float), array(float)); + +[@bs.module "./editor/main.js"] +external getPdfFromUserInput: string => shape = "get_pdf_from_user_input"; + +module FormConfig = [%lenses type state = {guesstimatorString: string}]; + +module Form = ReForm.Make(FormConfig); + +let schema = Form.Validation.Schema([||]); + +module FieldString = { + [@react.component] + let make = (~field, ~label) => { + + E.ste}> + validate()} + /> + + } + />; + }; +}; + +module Styles = { + open Css; + let rows = + style([ + selector( + ">.ant-col:first-child", + [paddingLeft(em(0.25)), paddingRight(em(0.125))], + ), + selector( + ">.ant-col:last-child", + [paddingLeft(em(0.125)), paddingRight(em(0.25))], + ), + selector( + ">.ant-col:not(:first-child):not(:last-child)", + [paddingLeft(em(0.125)), paddingRight(em(0.125))], + ), + ]); + let parent = + style([ + selector(".ant-input-number", [width(`percent(100.))]), + selector(".anticon", [verticalAlign(`zero)]), + ]); + let form = style([backgroundColor(hex("eee")), padding(em(1.))]); + let dist = style([padding(em(1.))]); + let spacer = style([marginTop(em(1.))]); + let groupA = + style([ + selector( + ".ant-input-number-input", + [backgroundColor(hex("fff7db"))], + ), + ]); + let groupB = + style([ + selector( + ".ant-input-number-input", + [backgroundColor(hex("eaf4ff"))], + ), + ]); +}; + +module DemoDist = { + [@react.component] + let make = (~guesstimatorString: string) => { + let (ys, xs) = getPdfFromUserInput("normal(1, 1) / normal(10, 1)"); + let continuous: DistTypes.xyShape = {xs, ys}; + E.ste}> +
+ + ; + }; +}; + +[@react.component] +let make = () => { + let (reloader, setRealoader) = React.useState(() => 1); + let reform = + Form.use( + ~validationStrategy=OnDemand, + ~schema, + ~onSubmit=({state}) => {None}, + ~initialState={guesstimatorString: "normal(1, 1) / normal(10, 1)"}, + (), + ); + + let onSubmit = e => { + e->ReactEvent.Synthetic.preventDefault; + reform.submit(); + }; + + let demoDist = + React.useMemo1( + () => { + + }, + [|reform.state.values.guesstimatorString|], + ); + + let onRealod = _ => { + setRealoader(_ => reloader + 1); + }; + +
+
+ demoDist +
+ E.ste} + extra={ + + }> + + + + + + + + + {"Update Distribution" |> E.ste} + + + + +
+
; +}; diff --git a/src/components/charts/DistributionPlot/DistributionPlot.re b/src/components/charts/DistributionPlot/DistributionPlot.re index 7de5506e..ea4064ed 100644 --- a/src/components/charts/DistributionPlot/DistributionPlot.re +++ b/src/components/charts/DistributionPlot/DistributionPlot.re @@ -114,7 +114,7 @@ let make = ~minX=?, ~yMaxDiscreteDomainFactor=?, ~yMaxContinuousDomainFactor=?, - ~onHover: float => unit, + ~onHover: float => unit=_ => (), ~continuous=?, ~scale=?, ~showDistributionLines=false, diff --git a/src/components/editor/distribution.js b/src/components/editor/distribution.js index 02ef8c5c..c16c1fd5 100644 --- a/src/components/editor/distribution.js +++ b/src/components/editor/distribution.js @@ -82,9 +82,11 @@ class BaseDistributionBinned { let args_str = args.toString() + ")"; let substr = this.name + ".pdf(x, " + args_str; let compiled = math.compile(substr); + function pdf_func(x) { return compiled.evaluate({ x: x }); } + let mc_compiled = math.compile(this.name + ".sample(" + args_str); let kv_pairs = this.param_names.map((val, idx) => [val, args[idx]]); let params = Object.fromEntries(new Map(kv_pairs)); @@ -97,12 +99,14 @@ class NormalDistributionBinned extends BaseDistributionBinned { this.name = "normal"; this.param_names = ["mean", "std"]; } + get_bounds() { return [ this.params.mean - 4 * this.params.std, this.params.mean + 4 * this.params.std ]; } + bin() { return this._adabin(this.params.std); } @@ -114,9 +118,11 @@ class UniformDistributionBinned extends BaseDistributionBinned { this.param_names = ["start_point", "end_point"]; this.num_bins = 200; } + get_bounds() { return [this.params.start_point, this.params.end_point]; } + bin() { let divider_pts = evenly_spaced_grid( this.params.start_point, @@ -152,6 +158,7 @@ class LogNormalDistributionBinned extends BaseDistributionBinned { } return largest_buffer[n - 1]; } + get_bounds() { let samples = Array(this.n_bounds_samples) .fill(0) @@ -161,6 +168,7 @@ class LogNormalDistributionBinned extends BaseDistributionBinned { this._nth_largest(samples, this.n_largest_bound_sample) ]; } + bin() { return this._adabin(); } diff --git a/src/components/editor/index.js b/src/components/editor/index.js deleted file mode 100644 index 64de1ba4..00000000 --- a/src/components/editor/index.js +++ /dev/null @@ -1,31 +0,0 @@ -import "./styles.css"; -const embed = require("vega-embed").embed; -const get_pdf_from_user_input = require("./main.js").get_pdf_from_user_input; - -let [y, x] = get_pdf_from_user_input("normal(1, 1) / normal(10, 1)"); - -let pdf = x.map((val, idx) => ({ x: val, pdf: y[idx] })); - -let spec = { - data: { - values: pdf - }, - mark: { type: "area", line: true }, - encoding: { - x: { field: "x", type: "quantitative" }, - y: { - field: "pdf", - type: "quantitative", - scale: { domain: [0, 3 * Math.max(...y)] } - } - }, - width: 500 -}; - -embed("#viz", spec); - -console.log(y.reduce((a, b) => a + b)); - -document.getElementById("app").innerHTML = ` -
-`; diff --git a/src/components/editor/main.js b/src/components/editor/main.js index 3ff9b355..c44b314b 100644 --- a/src/components/editor/main.js +++ b/src/components/editor/main.js @@ -267,11 +267,13 @@ function get_grid_transform(distr_string) { arg_strings.push("x_" + i.toString()); } let compiled = math.compile(distr_string); + function grid_transform(x) { let kv_pairs = arg_strings.map((val, idx) => [val, x[idx]]); let args_obj = Object.fromEntries(new Map(kv_pairs)); return compiled.evaluate(args_obj); } + return grid_transform; }