Added ability to add-remove dists
This commit is contained in:
parent
bdeb53a6c4
commit
f45b4b763a
|
@ -1,15 +1,4 @@
|
|||
type state = {
|
||||
log: bool,
|
||||
showStats: bool,
|
||||
showParams: bool,
|
||||
height: int,
|
||||
};
|
||||
|
||||
type action =
|
||||
| CHANGE_LOG
|
||||
| CHANGE_SHOW_STATS
|
||||
| CHANGE_SHOW_PARAMS
|
||||
| CHANGE_HEIGHT(int);
|
||||
open DistPlusPlotReducer;
|
||||
|
||||
let showAsForm = (distPlus: DistTypes.distPlus) => {
|
||||
<div>
|
||||
|
@ -146,7 +135,7 @@ let adjustBoth = discreteProbabilityMass => {
|
|||
|
||||
module DistPlusChart = {
|
||||
[@react.component]
|
||||
let make = (~distPlus: DistTypes.distPlus, ~state: state, ~onHover) => {
|
||||
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
|
||||
open Distributions.DistPlus;
|
||||
let discrete = distPlus |> T.toScaledDiscrete;
|
||||
let continuous =
|
||||
|
@ -166,27 +155,25 @@ module DistPlusChart = {
|
|||
distPlus |> Distributions.DistPlus.T.toDiscreteProbabilityMass;
|
||||
let (yMaxDiscreteDomainFactor, yMaxContinuousDomainFactor) =
|
||||
adjustBoth(toDiscreteProbabilityMass);
|
||||
<div className=Css.(style([minHeight(`px(state.height))]))>
|
||||
<DistributionPlot
|
||||
scale={state.log ? "log" : "linear"}
|
||||
minX
|
||||
maxX
|
||||
yMaxDiscreteDomainFactor
|
||||
yMaxContinuousDomainFactor
|
||||
height={state.height}
|
||||
?discrete
|
||||
?continuous
|
||||
color={`hex("5f6b7e")}
|
||||
onHover
|
||||
timeScale
|
||||
/>
|
||||
</div>;
|
||||
<DistributionPlot
|
||||
scale={config.log ? "log" : "linear"}
|
||||
height={DistPlusPlotReducer.heightToPix(config.height)}
|
||||
minX
|
||||
maxX
|
||||
yMaxDiscreteDomainFactor
|
||||
yMaxContinuousDomainFactor
|
||||
?discrete
|
||||
?continuous
|
||||
color={`hex("5f6b7e")}
|
||||
onHover
|
||||
timeScale
|
||||
/>;
|
||||
};
|
||||
};
|
||||
|
||||
module IntegralChart = {
|
||||
[@react.component]
|
||||
let make = (~distPlus: DistTypes.distPlus, ~onHover) => {
|
||||
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
|
||||
open Distributions.DistPlus;
|
||||
let integral =
|
||||
Distributions.DistPlus.T.toShape(distPlus)
|
||||
|
@ -204,9 +191,10 @@ module IntegralChart = {
|
|||
let maxX = integral |> Distributions.Continuous.T.maxX;
|
||||
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
|
||||
<DistributionPlot
|
||||
scale={config.log ? "log" : "linear"}
|
||||
height={DistPlusPlotReducer.heightToPix(config.height)}
|
||||
minX
|
||||
maxX
|
||||
height=80
|
||||
?continuous
|
||||
color={`hex("5f6b7e")}
|
||||
timeScale
|
||||
|
@ -215,64 +203,94 @@ module IntegralChart = {
|
|||
};
|
||||
};
|
||||
|
||||
module Chart = {
|
||||
[@react.component]
|
||||
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
|
||||
let chart =
|
||||
React.useMemo2(
|
||||
() => {
|
||||
config.isCumulative
|
||||
? <IntegralChart distPlus config onHover />
|
||||
: <DistPlusChart distPlus config onHover />
|
||||
},
|
||||
(distPlus, config),
|
||||
);
|
||||
<div
|
||||
className=Css.(
|
||||
style([
|
||||
minHeight(`px(DistPlusPlotReducer.heightToPix(config.height))),
|
||||
])
|
||||
)>
|
||||
chart
|
||||
</div>;
|
||||
};
|
||||
};
|
||||
|
||||
let button = "bg-gray-300 hover:bg-gray-500 text-grey-darkest text-xs px-4 py-1";
|
||||
|
||||
[@react.component]
|
||||
let make = (~distPlus: DistTypes.distPlus) => {
|
||||
let (x, setX) = React.useState(() => 0.);
|
||||
let (state, dispatch) =
|
||||
React.useReducer(
|
||||
(state: state, action: action) =>
|
||||
switch (action) {
|
||||
| CHANGE_LOG => {...state, log: !state.log}
|
||||
| CHANGE_HEIGHT(height) => {...state, height}
|
||||
| CHANGE_SHOW_STATS => {...state, showStats: !state.showStats}
|
||||
| CHANGE_SHOW_PARAMS => {...state, showParams: !state.showParams}
|
||||
},
|
||||
{log: false, height: 80, showStats: false, showParams: false},
|
||||
);
|
||||
let chart =
|
||||
React.useMemo2(
|
||||
() => {<DistPlusChart distPlus state onHover={r => {setX(_ => r)}} />},
|
||||
(distPlus, state),
|
||||
);
|
||||
let chart2 =
|
||||
React.useMemo1(
|
||||
() => {<IntegralChart distPlus onHover={r => {setX(_ => r)}} />},
|
||||
[|distPlus|],
|
||||
);
|
||||
React.useReducer(DistPlusPlotReducer.reducer, DistPlusPlotReducer.init);
|
||||
<div>
|
||||
chart
|
||||
chart2
|
||||
{state.distributions
|
||||
|> E.L.fmapi((index, config) =>
|
||||
<div className="flex">
|
||||
<div className="w-4/5">
|
||||
<Chart distPlus config onHover={r => {setX(_ => r)}} />
|
||||
</div>
|
||||
<div className="w-1/5">
|
||||
<div className="opacity-50 hover:opacity-100">
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(CHANGE_LOG(index))}>
|
||||
{(state.log ? "log" : "linear") |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ =>
|
||||
dispatch(
|
||||
CHANGE_IS_CUMULATIVE(index, !config.isCumulative),
|
||||
)
|
||||
}>
|
||||
{(config.isCumulative ? "cdf" : "pdf") |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(HEIGHT_INCREMENT(index))}>
|
||||
{"Expand" |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(HEIGHT_DECREMENT(index))}>
|
||||
{"Compress" |> ReasonReact.string}
|
||||
</button>
|
||||
{index != 0
|
||||
? <button
|
||||
className=button
|
||||
onClick={_ => dispatch(REMOVE_DIST(index))}>
|
||||
{"Remove" |> ReasonReact.string}
|
||||
</button>
|
||||
: ReasonReact.null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|> E.L.toArray
|
||||
|> ReasonReact.array}
|
||||
<div className="inline-flex opacity-50 hover:opacity-100">
|
||||
<button className=button onClick={_ => dispatch(CHANGE_LOG)}>
|
||||
{(state.log ? "x-Linear" : "x-Log") |> ReasonReact.string}
|
||||
</button>
|
||||
<button className=button onClick={_ => dispatch(CHANGE_SHOW_STATS)}>
|
||||
{"Stats" |> ReasonReact.string}
|
||||
</button>
|
||||
<button className=button onClick={_ => dispatch(CHANGE_SHOW_PARAMS)}>
|
||||
{"Params" |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ => dispatch(CHANGE_HEIGHT(state.height + 40))}>
|
||||
{"Expand" |> ReasonReact.string}
|
||||
</button>
|
||||
<button
|
||||
className=button
|
||||
onClick={_ =>
|
||||
dispatch(
|
||||
CHANGE_HEIGHT(
|
||||
state.height < 81 ? state.height : state.height - 40,
|
||||
),
|
||||
)
|
||||
}>
|
||||
{"Compress" |> ReasonReact.string}
|
||||
<button className=button onClick={_ => dispatch(ADD_DIST)}>
|
||||
{"Add" |> ReasonReact.string}
|
||||
</button>
|
||||
</div>
|
||||
{state.showParams ? showAsForm(distPlus) : ReasonReact.null}
|
||||
{state.showStats ? table(distPlus, x) : ReasonReact.null}
|
||||
</div>;
|
||||
// chart
|
||||
};
|
97
src/components/charts/DistPlusPlotReducer.re
Normal file
97
src/components/charts/DistPlusPlotReducer.re
Normal file
|
@ -0,0 +1,97 @@
|
|||
type chartConfig = {
|
||||
log: bool,
|
||||
isCumulative: bool,
|
||||
height: int,
|
||||
};
|
||||
|
||||
type state = {
|
||||
log: bool,
|
||||
showStats: bool,
|
||||
showParams: bool,
|
||||
distributions: list(chartConfig),
|
||||
};
|
||||
|
||||
type action =
|
||||
| CHANGE_SHOW_STATS
|
||||
| CHANGE_SHOW_PARAMS
|
||||
| REMOVE_DIST(int)
|
||||
| ADD_DIST
|
||||
| CHANGE_LOG(int)
|
||||
| CHANGE_IS_CUMULATIVE(int, bool)
|
||||
| HEIGHT_INCREMENT(int)
|
||||
| HEIGHT_DECREMENT(int);
|
||||
|
||||
let changeHeight = (currentHeight, foo: [ | `increment | `decrement]) =>
|
||||
switch (currentHeight, foo) {
|
||||
| (1, `decrement) => 1
|
||||
| (2, `decrement) => 1
|
||||
| (3, `decrement) => 2
|
||||
| (4, `decrement) => 3
|
||||
| (1, `increment) => 2
|
||||
| (2, `increment) => 3
|
||||
| (3, `increment) => 4
|
||||
| (4, `increment) => 4
|
||||
| _ => 1
|
||||
};
|
||||
|
||||
let heightToPix =
|
||||
fun
|
||||
| 1 => 80
|
||||
| 2 => 140
|
||||
| 3 => 240
|
||||
| 4 => 340
|
||||
| _ => 140;
|
||||
|
||||
let distributionReducer = (index, state: list(chartConfig), action) => {
|
||||
Js.log3(index, action, state);
|
||||
switch (action, E.L.get(state, index)) {
|
||||
| (HEIGHT_INCREMENT(_), Some(dist)) =>
|
||||
E.L.update(
|
||||
{...dist, height: changeHeight(dist.height, `increment)},
|
||||
index,
|
||||
state,
|
||||
)
|
||||
| (HEIGHT_DECREMENT(_), Some(dist)) =>
|
||||
E.L.update(
|
||||
{...dist, height: changeHeight(dist.height, `decrement)},
|
||||
index,
|
||||
state,
|
||||
)
|
||||
| (CHANGE_IS_CUMULATIVE(_, isCumulative), Some(dist)) =>
|
||||
E.L.update({...dist, isCumulative}, index, state)
|
||||
| (CHANGE_LOG(_), Some(dist)) =>
|
||||
E.L.update({...dist, log: !dist.log}, index, state)
|
||||
| (REMOVE_DIST(_), Some(_)) => E.L.remove(index, 1, state)
|
||||
| (ADD_DIST, Some(_)) =>
|
||||
E.L.append(state, [{log: false, isCumulative: false, height: 2}])
|
||||
| _ => state
|
||||
};
|
||||
};
|
||||
|
||||
let reducer = (state: state, action: action) =>
|
||||
switch (action) {
|
||||
| CHANGE_LOG(i)
|
||||
| CHANGE_IS_CUMULATIVE(i, _)
|
||||
| HEIGHT_DECREMENT(i)
|
||||
| REMOVE_DIST(i)
|
||||
| HEIGHT_INCREMENT(i) => {
|
||||
...state,
|
||||
distributions: distributionReducer(i, state.distributions, action),
|
||||
}
|
||||
| ADD_DIST => {
|
||||
...state,
|
||||
distributions: distributionReducer(0, state.distributions, action),
|
||||
}
|
||||
| CHANGE_SHOW_STATS => {...state, showStats: !state.showStats}
|
||||
| CHANGE_SHOW_PARAMS => {...state, showParams: !state.showParams}
|
||||
};
|
||||
|
||||
let init = {
|
||||
log: false,
|
||||
showStats: false,
|
||||
showParams: false,
|
||||
distributions: [
|
||||
{log: false, isCumulative: false, height: 2},
|
||||
{log: false, isCumulative: true, height: 1},
|
||||
],
|
||||
};
|
|
@ -177,10 +177,13 @@ module JsDate = {
|
|||
/* List */
|
||||
module L = {
|
||||
let fmap = List.map;
|
||||
let get = Belt.List.get;
|
||||
let toArray = Array.of_list;
|
||||
let fmapi = List.mapi;
|
||||
let concat = List.concat;
|
||||
let append = List.append;
|
||||
let drop = Rationale.RList.drop;
|
||||
let remove = Rationale.RList.remove;
|
||||
let find = List.find;
|
||||
let filter = List.filter;
|
||||
let for_all = List.for_all;
|
||||
|
@ -299,4 +302,4 @@ module JsArray = {
|
|||
};
|
||||
|
||||
let ste = React.string;
|
||||
let showIf = (cond, comp) => cond ? comp : ReasonReact.null;
|
||||
let showIf = (cond, comp) => cond ? comp : ReasonReact.null;
|
Loading…
Reference in New Issue
Block a user