Reorganization of files
This commit is contained in:
parent
e84cfd4c92
commit
990f01b8d6
|
@ -15,7 +15,7 @@ let timeDist =
|
||||||
);
|
);
|
||||||
|
|
||||||
let setup = dist =>
|
let setup = dist =>
|
||||||
RenderTypes.DistPlus.make(~distPlusIngredients=dist,())
|
RenderTypes.DistPlusRenderer.make(~distPlusIngredients=dist,())
|
||||||
|> DistPlusIngredients.toDistPlus
|
|> DistPlusIngredients.toDistPlus
|
||||||
|> E.O.React.fmapOrNull(distPlus => <DistPlusPlot distPlus />);
|
|> E.O.React.fmapOrNull(distPlus => <DistPlusPlot distPlus />);
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ module Styles = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type inputs = {
|
type inputs = {
|
||||||
samplingInputs: RenderTypes.Sampling.inputs,
|
samplingInputs: RenderTypes.ShapeRenderer.Sampling.inputs,
|
||||||
guesstimatorString: string,
|
guesstimatorString: string,
|
||||||
length: int,
|
length: int,
|
||||||
shouldTruncateSampledDistribution: int,
|
shouldTruncateSampledDistribution: int,
|
||||||
|
@ -134,7 +134,7 @@ module DemoDist = {
|
||||||
(),
|
(),
|
||||||
);
|
);
|
||||||
let inputs =
|
let inputs =
|
||||||
RenderTypes.DistPlus.make(
|
RenderTypes.DistPlusRenderer.make(
|
||||||
~samplingInputs={
|
~samplingInputs={
|
||||||
sampleCount: Some(options.sampleCount),
|
sampleCount: Some(options.sampleCount),
|
||||||
outputXYPoints: Some(options.outputXYPoints),
|
outputXYPoints: Some(options.outputXYPoints),
|
||||||
|
|
|
@ -40,6 +40,8 @@ let buildSimple = (~continuous: option(DistTypes.continuousShape), ~discrete): o
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Delete, only being used in tests
|
||||||
let build = (~continuous, ~discrete, ~assumptions) =>
|
let build = (~continuous, ~discrete, ~assumptions) =>
|
||||||
switch (assumptions) {
|
switch (assumptions) {
|
||||||
| {
|
| {
|
39
src/distPlus/renderers/DistPlusIngredients.re
Normal file
39
src/distPlus/renderers/DistPlusIngredients.re
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
open DistTypes;
|
||||||
|
|
||||||
|
let make =
|
||||||
|
(~guesstimatorString, ~domain=Complete, ~unit=UnspecifiedDistribution, ())
|
||||||
|
: distPlusIngredients => {
|
||||||
|
guesstimatorString,
|
||||||
|
domain,
|
||||||
|
unit,
|
||||||
|
};
|
||||||
|
|
||||||
|
let truncateIfShould = (inputs: RenderTypes.DistPlusRenderer.inputs, dist) => {
|
||||||
|
inputs.shouldTruncate
|
||||||
|
? dist
|
||||||
|
: dist |> Distributions.DistPlus.T.truncate(inputs.recommendedLength);
|
||||||
|
};
|
||||||
|
|
||||||
|
let toDistPlus = (inputs: RenderTypes.DistPlusRenderer.inputs): option(distPlus) => {
|
||||||
|
let toDist = shape =>
|
||||||
|
Distributions.DistPlus.make(
|
||||||
|
~shape,
|
||||||
|
~domain=inputs.distPlusIngredients.domain,
|
||||||
|
~unit=inputs.distPlusIngredients.unit,
|
||||||
|
~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString),
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
|> Distributions.DistPlus.T.scaleToIntegralSum(~intendedSum=1.0);
|
||||||
|
let shape =
|
||||||
|
GuesstimatorToShape.run({
|
||||||
|
samplingInputs: inputs.samplingInputs,
|
||||||
|
guesstimatorString: inputs.distPlusIngredients.guesstimatorString,
|
||||||
|
symbolicInputs: {
|
||||||
|
length: inputs.recommendedLength,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|> GuesstimatorToShape.getShape;
|
||||||
|
let dist =
|
||||||
|
shape |> E.O.fmap(toDist) |> E.O.fmap(truncateIfShould(inputs));
|
||||||
|
dist;
|
||||||
|
};
|
31
src/distPlus/renderers/GuesstimatorToShape.re
Normal file
31
src/distPlus/renderers/GuesstimatorToShape.re
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
let runSymbolic =
|
||||||
|
(guesstimatorString, length) =>{
|
||||||
|
let graph = MathJsParser.fromString(guesstimatorString);
|
||||||
|
graph |> E.R.fmap(g => RenderTypes.ShapeRenderer.Symbolic.make(g, SymbolicDist.toShape(length,g)))
|
||||||
|
}
|
||||||
|
|
||||||
|
let getShape = (r: RenderTypes.ShapeRenderer.Combined.outputs) =>
|
||||||
|
switch (r.symbolic, r.sampling) {
|
||||||
|
| (Some(Ok({shape})), _) => Some(shape)
|
||||||
|
| (_, Some({shape})) => shape
|
||||||
|
| _ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
let run =
|
||||||
|
(
|
||||||
|
inputs: RenderTypes.ShapeRenderer.Combined.inputs
|
||||||
|
)
|
||||||
|
: RenderTypes.ShapeRenderer.Combined.outputs => {
|
||||||
|
let symbolic = runSymbolic(inputs.guesstimatorString, inputs.symbolicInputs.length);
|
||||||
|
let sampling =
|
||||||
|
switch (symbolic) {
|
||||||
|
| Ok(r) => None
|
||||||
|
| Error(r) =>
|
||||||
|
Samples.T.fromGuesstimatorString(
|
||||||
|
~guesstimatorString=inputs.guesstimatorString,
|
||||||
|
~samplingInputs=inputs.samplingInputs,
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
{symbolic: Some(symbolic), sampling};
|
||||||
|
};
|
88
src/distPlus/renderers/RenderTypes.re
Normal file
88
src/distPlus/renderers/RenderTypes.re
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
module ShapeRenderer = {
|
||||||
|
module Sampling = {
|
||||||
|
type inputs = {
|
||||||
|
sampleCount: option(int),
|
||||||
|
outputXYPoints: option(int),
|
||||||
|
kernelWidth: option(float),
|
||||||
|
};
|
||||||
|
type samplingStats = {
|
||||||
|
sampleCount: int,
|
||||||
|
outputXYPoints: int,
|
||||||
|
bandwidthXSuggested: float,
|
||||||
|
bandwidthUnitSuggested: float,
|
||||||
|
bandwidthXImplemented: float,
|
||||||
|
bandwidthUnitImplemented: float,
|
||||||
|
};
|
||||||
|
type outputs = {
|
||||||
|
continuousParseParams: option(samplingStats),
|
||||||
|
shape: option(DistTypes.shape),
|
||||||
|
};
|
||||||
|
module Inputs = {
|
||||||
|
let defaultSampleCount = 5000;
|
||||||
|
let defaultOutputXYPoints = 10000;
|
||||||
|
let empty = {
|
||||||
|
sampleCount: None,
|
||||||
|
outputXYPoints: None,
|
||||||
|
kernelWidth: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
type fInputs = {
|
||||||
|
sampleCount: int,
|
||||||
|
outputXYPoints: int,
|
||||||
|
kernelWidth: option(float),
|
||||||
|
};
|
||||||
|
let toF = (i: inputs): fInputs => {
|
||||||
|
sampleCount: i.sampleCount |> E.O.default(defaultSampleCount),
|
||||||
|
outputXYPoints:
|
||||||
|
i.outputXYPoints |> E.O.default(defaultOutputXYPoints),
|
||||||
|
kernelWidth: i.kernelWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module Symbolic = {
|
||||||
|
type inputs = {length: int};
|
||||||
|
type outputs = {
|
||||||
|
graph: SymbolicDist.bigDist,
|
||||||
|
shape: DistTypes.shape,
|
||||||
|
};
|
||||||
|
let make = (graph, shape) => {graph, shape};
|
||||||
|
};
|
||||||
|
|
||||||
|
module Combined = {
|
||||||
|
type inputs = {
|
||||||
|
samplingInputs: Sampling.inputs,
|
||||||
|
symbolicInputs: Symbolic.inputs,
|
||||||
|
guesstimatorString: string,
|
||||||
|
};
|
||||||
|
type outputs = {
|
||||||
|
symbolic: option(Belt.Result.t(Symbolic.outputs, string)),
|
||||||
|
sampling: option(Sampling.outputs),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module DistPlusRenderer = {
|
||||||
|
let defaultRecommendedLength = 10000;
|
||||||
|
let defaultShouldTruncate = true;
|
||||||
|
type inputs = {
|
||||||
|
distPlusIngredients: DistTypes.distPlusIngredients,
|
||||||
|
samplingInputs: ShapeRenderer.Sampling.inputs,
|
||||||
|
recommendedLength: int,
|
||||||
|
shouldTruncate: bool,
|
||||||
|
};
|
||||||
|
let make =
|
||||||
|
(
|
||||||
|
~samplingInputs=ShapeRenderer.Sampling.Inputs.empty,
|
||||||
|
~recommendedLength=defaultRecommendedLength,
|
||||||
|
~shouldTruncate=defaultShouldTruncate,
|
||||||
|
~distPlusIngredients,
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
: inputs => {
|
||||||
|
distPlusIngredients,
|
||||||
|
samplingInputs,
|
||||||
|
recommendedLength,
|
||||||
|
shouldTruncate,
|
||||||
|
};
|
||||||
|
};
|
|
@ -10,7 +10,7 @@ module JS = {
|
||||||
ys: ysGet(d),
|
ys: ysGet(d),
|
||||||
};
|
};
|
||||||
|
|
||||||
[@bs.module "./utility/KdeLibrary.js"]
|
[@bs.module "./KdeLibrary.js"]
|
||||||
external samplesToContinuousPdf: (array(float), int, int) => distJs =
|
external samplesToContinuousPdf: (array(float), int, int) => distJs =
|
||||||
"samplesToContinuousPdf";
|
"samplesToContinuousPdf";
|
||||||
};
|
};
|
||||||
|
@ -106,9 +106,8 @@ module T = {
|
||||||
KDE.normalSampling(samples, outputXYPoints, width);
|
KDE.normalSampling(samples, outputXYPoints, width);
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: Figure out some way of doing this without having to integrate so many times.
|
|
||||||
let toShape =
|
let toShape =
|
||||||
(~samples: t, ~samplingInputs: RenderTypes.Sampling.Inputs.fInputs, ()) => {
|
(~samples: t, ~samplingInputs: RenderTypes.ShapeRenderer.Sampling.Inputs.fInputs, ()) => {
|
||||||
Array.fast_sort(compare, samples);
|
Array.fast_sort(compare, samples);
|
||||||
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples);
|
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples);
|
||||||
let length = samples |> E.A.length |> float_of_int;
|
let length = samples |> E.A.length |> float_of_int;
|
||||||
|
@ -132,7 +131,7 @@ module T = {
|
||||||
samplingInputs.outputXYPoints,
|
samplingInputs.outputXYPoints,
|
||||||
usedWidth,
|
usedWidth,
|
||||||
);
|
);
|
||||||
let foo: RenderTypes.Sampling.samplingStats = {
|
let foo: RenderTypes.ShapeRenderer.Sampling.samplingStats = {
|
||||||
sampleCount: samplingInputs.sampleCount,
|
sampleCount: samplingInputs.sampleCount,
|
||||||
outputXYPoints: samplingInputs.outputXYPoints,
|
outputXYPoints: samplingInputs.outputXYPoints,
|
||||||
bandwidthXSuggested: _suggestedXWidth,
|
bandwidthXSuggested: _suggestedXWidth,
|
||||||
|
@ -155,7 +154,7 @@ module T = {
|
||||||
~continuous=pdf |> E.O.fmap(fst),
|
~continuous=pdf |> E.O.fmap(fst),
|
||||||
~discrete,
|
~discrete,
|
||||||
);
|
);
|
||||||
let samplesParse: RenderTypes.Sampling.outputs = {
|
let samplesParse: RenderTypes.ShapeRenderer.Sampling.outputs = {
|
||||||
continuousParseParams: pdf |> E.O.fmap(snd),
|
continuousParseParams: pdf |> E.O.fmap(snd),
|
||||||
shape,
|
shape,
|
||||||
};
|
};
|
||||||
|
@ -165,12 +164,12 @@ module T = {
|
||||||
let fromGuesstimatorString =
|
let fromGuesstimatorString =
|
||||||
(
|
(
|
||||||
~guesstimatorString,
|
~guesstimatorString,
|
||||||
~samplingInputs=RenderTypes.Sampling.Inputs.empty,
|
~samplingInputs=RenderTypes.ShapeRenderer.Sampling.Inputs.empty,
|
||||||
(),
|
(),
|
||||||
) => {
|
) => {
|
||||||
let hasValidSamples =
|
let hasValidSamples =
|
||||||
Guesstimator.stringToSamples(guesstimatorString, 10) |> E.A.length > 0;
|
Guesstimator.stringToSamples(guesstimatorString, 10) |> E.A.length > 0;
|
||||||
let samplingInputs = RenderTypes.Sampling.Inputs.toF(samplingInputs);
|
let samplingInputs = RenderTypes.ShapeRenderer.Sampling.Inputs.toF(samplingInputs);
|
||||||
switch (hasValidSamples) {
|
switch (hasValidSamples) {
|
||||||
| false => None
|
| false => None
|
||||||
| true =>
|
| true =>
|
|
@ -1,3 +1,5 @@
|
||||||
|
// todo: rename to SymbolicParser
|
||||||
|
|
||||||
module MathJsonToMathJsAdt = {
|
module MathJsonToMathJsAdt = {
|
||||||
type arg =
|
type arg =
|
||||||
| Symbol(string)
|
| Symbol(string)
|
|
@ -1,48 +0,0 @@
|
||||||
open DistTypes;
|
|
||||||
|
|
||||||
let make =
|
|
||||||
(~guesstimatorString, ~domain=Complete, ~unit=UnspecifiedDistribution, ())
|
|
||||||
: distPlusIngredients => {
|
|
||||||
guesstimatorString,
|
|
||||||
domain,
|
|
||||||
unit,
|
|
||||||
};
|
|
||||||
|
|
||||||
let applyTruncation = (truncateTo, distPlus) =>
|
|
||||||
switch (truncateTo, distPlus) {
|
|
||||||
| (Some(t), Some(d)) => Some(d |> Distributions.DistPlus.T.truncate(t))
|
|
||||||
| (None, Some(d)) => Some(d)
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
|
|
||||||
// ~samplingInputs=RenderTypes.Sampling.Inputs.empty,
|
|
||||||
// ~truncateTo: option(int),
|
|
||||||
// t: distPlusIngredients,
|
|
||||||
//Make truncation optional
|
|
||||||
let toDistPlus =
|
|
||||||
(
|
|
||||||
inputs:RenderTypes.DistPlus.inputs
|
|
||||||
)
|
|
||||||
: option(distPlus) => {
|
|
||||||
let toDist = shape =>
|
|
||||||
Distributions.DistPlus.make(
|
|
||||||
~shape,
|
|
||||||
~domain=inputs.distPlusIngredients.domain,
|
|
||||||
~unit=inputs.distPlusIngredients.unit,
|
|
||||||
~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString),
|
|
||||||
(),
|
|
||||||
)
|
|
||||||
|> Distributions.DistPlus.T.scaleToIntegralSum(~intendedSum=1.0);
|
|
||||||
let shape =
|
|
||||||
GuesstimatorToShape.run(
|
|
||||||
~renderingInputs={
|
|
||||||
guesstimatorString: inputs.distPlusIngredients.guesstimatorString,
|
|
||||||
shapeLength: inputs.recommendedLength,
|
|
||||||
},
|
|
||||||
~samplingInputs=inputs.samplingInputs,
|
|
||||||
)
|
|
||||||
|> GuesstimatorToShape.getShape;
|
|
||||||
//TODO: Apply truncation
|
|
||||||
let foo = shape |> E.O.fmap(toDist);
|
|
||||||
foo;
|
|
||||||
};
|
|
|
@ -1,32 +0,0 @@
|
||||||
let runSymbolic =
|
|
||||||
(renderingInputs: RenderTypes.primaryInputs) =>{
|
|
||||||
let graph = MathJsParser.fromString(renderingInputs.guesstimatorString);
|
|
||||||
graph |> E.R.fmap(g => RenderTypes.Symbolic.make(g, SymbolicDist.toShape(renderingInputs.shapeLength,g)))
|
|
||||||
}
|
|
||||||
|
|
||||||
let getShape = (r: RenderTypes.Combined.outputs) =>
|
|
||||||
switch (r.symbolic, r.sampling) {
|
|
||||||
| (Some(Ok({shape})), _) => Some(shape)
|
|
||||||
| (_, Some({shape})) => shape
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
|
|
||||||
let run =
|
|
||||||
(
|
|
||||||
~renderingInputs: RenderTypes.primaryInputs,
|
|
||||||
~samplingInputs: RenderTypes.Sampling.inputs,
|
|
||||||
)
|
|
||||||
: RenderTypes.Combined.outputs => {
|
|
||||||
let symbolic = runSymbolic(renderingInputs);
|
|
||||||
let sampling =
|
|
||||||
switch (symbolic) {
|
|
||||||
| Ok(r) => None
|
|
||||||
| Error(r) =>
|
|
||||||
Samples.T.fromGuesstimatorString(
|
|
||||||
~guesstimatorString=renderingInputs.guesstimatorString,
|
|
||||||
~samplingInputs,
|
|
||||||
(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
{symbolic: Some(symbolic), sampling};
|
|
||||||
};
|
|
|
@ -1,86 +0,0 @@
|
||||||
type primaryInputs = {
|
|
||||||
guesstimatorString: string,
|
|
||||||
shapeLength: int,
|
|
||||||
};
|
|
||||||
|
|
||||||
module Sampling = {
|
|
||||||
type inputs = {
|
|
||||||
sampleCount: option(int),
|
|
||||||
outputXYPoints: option(int),
|
|
||||||
kernelWidth: option(float),
|
|
||||||
};
|
|
||||||
type samplingStats = {
|
|
||||||
sampleCount: int,
|
|
||||||
outputXYPoints: int,
|
|
||||||
bandwidthXSuggested: float,
|
|
||||||
bandwidthUnitSuggested: float,
|
|
||||||
bandwidthXImplemented: float,
|
|
||||||
bandwidthUnitImplemented: float,
|
|
||||||
};
|
|
||||||
type outputs = {
|
|
||||||
continuousParseParams: option(samplingStats),
|
|
||||||
shape: option(ProbExample.DistTypes.shape),
|
|
||||||
};
|
|
||||||
module Inputs = {
|
|
||||||
let defaultSampleCount = 5000;
|
|
||||||
let defaultOutputXYPoints = 10000;
|
|
||||||
let empty = {sampleCount: None, outputXYPoints: None, kernelWidth: None};
|
|
||||||
|
|
||||||
type fInputs = {
|
|
||||||
sampleCount: int,
|
|
||||||
outputXYPoints: int,
|
|
||||||
kernelWidth: option(float),
|
|
||||||
};
|
|
||||||
let toF = (i: inputs): fInputs => {
|
|
||||||
sampleCount: i.sampleCount |> E.O.default(defaultSampleCount),
|
|
||||||
outputXYPoints: i.outputXYPoints |> E.O.default(defaultOutputXYPoints),
|
|
||||||
kernelWidth: i.kernelWidth,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module Symbolic = {
|
|
||||||
type inputs = {length: int};
|
|
||||||
type outputs = {
|
|
||||||
graph: ProbExample.SymbolicDist.bigDist,
|
|
||||||
shape: ProbExample.DistTypes.shape,
|
|
||||||
};
|
|
||||||
let make = (graph, shape) => {graph, shape};
|
|
||||||
};
|
|
||||||
|
|
||||||
module Combined = {
|
|
||||||
type inputs = {
|
|
||||||
samplingInputs: Sampling.inputs,
|
|
||||||
symbolicInputs: Symbolic.inputs,
|
|
||||||
guesstimatorString: string,
|
|
||||||
};
|
|
||||||
type outputs = {
|
|
||||||
symbolic: option(Belt.Result.t(Symbolic.outputs, string)),
|
|
||||||
sampling: option(Sampling.outputs),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module DistPlus = {
|
|
||||||
let defaultRecommendedLength = 10000;
|
|
||||||
let defaultShouldTruncate = true;
|
|
||||||
type inputs = {
|
|
||||||
distPlusIngredients: DistTypes.distPlusIngredients,
|
|
||||||
samplingInputs: Sampling.inputs,
|
|
||||||
recommendedLength: int,
|
|
||||||
shouldTruncate: bool,
|
|
||||||
};
|
|
||||||
let make =
|
|
||||||
(
|
|
||||||
~samplingInputs=Sampling.Inputs.empty,
|
|
||||||
~recommendedLength=defaultRecommendedLength,
|
|
||||||
~shouldTruncate=defaultShouldTruncate,
|
|
||||||
~distPlusIngredients,
|
|
||||||
()
|
|
||||||
)
|
|
||||||
: inputs => {
|
|
||||||
distPlusIngredients,
|
|
||||||
samplingInputs,
|
|
||||||
recommendedLength,
|
|
||||||
shouldTruncate,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -19,7 +19,7 @@ let propValue = (t: Prop.Value.t) => {
|
||||||
| ConditionalArray(r) => "Array" |> ReasonReact.string
|
| ConditionalArray(r) => "Array" |> ReasonReact.string
|
||||||
| DistPlusIngredients((r: DistTypes.distPlusIngredients)) =>
|
| DistPlusIngredients((r: DistTypes.distPlusIngredients)) =>
|
||||||
let newDistribution =
|
let newDistribution =
|
||||||
RenderTypes.DistPlus.make(~distPlusIngredients=r, ~recommendedLength=1000, ~shouldTruncate=true,())
|
RenderTypes.DistPlusRenderer.make(~distPlusIngredients=r, ~recommendedLength=1000, ~shouldTruncate=true,())
|
||||||
|> DistPlusIngredients.toDistPlus
|
|> DistPlusIngredients.toDistPlus
|
||||||
switch (newDistribution) {
|
switch (newDistribution) {
|
||||||
| Some(distribution) =>
|
| Some(distribution) =>
|
||||||
|
|
|
@ -110,7 +110,7 @@ module Model = {
|
||||||
// TODO: Fixe number that integral is calculated for
|
// TODO: Fixe number that integral is calculated for
|
||||||
let getGlobalCatastropheChance = dateTime => {
|
let getGlobalCatastropheChance = dateTime => {
|
||||||
GlobalCatastrophe.makeI(MomentRe.momentNow())
|
GlobalCatastrophe.makeI(MomentRe.momentNow())
|
||||||
|> RenderTypes.DistPlus.make(~distPlusIngredients=_, ())
|
|> RenderTypes.DistPlusRenderer.make(~distPlusIngredients=_, ())
|
||||||
|> DistPlusIngredients.toDistPlus
|
|> DistPlusIngredients.toDistPlus
|
||||||
|> E.O.bind(_, Distributions.DistPlusTime.Integral.xToY(Time(dateTime)));
|
|> E.O.bind(_, Distributions.DistPlusTime.Integral.xToY(Time(dateTime)));
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user