From 1d6a28cd432c2a049a41cc4b8f9e125e1f3d0a9e Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 9 Feb 2020 15:25:04 +0000 Subject: [PATCH] First attempt at Prop file --- src/Model2.re | 64 +++++++++++++++++++++ src/Prop.re | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 src/Model2.re create mode 100644 src/Prop.re diff --git a/src/Model2.re b/src/Model2.re new file mode 100644 index 00000000..2aee33b7 --- /dev/null +++ b/src/Model2.re @@ -0,0 +1,64 @@ +type model = { + name: string, + author: string, + assumptions: list(Input.parameter), + inputs: list(Input.parameter), + outputs: list(Output.parameter), + outputConfig: Output.outputConfig, +}; + +let gatherInputs = (m: model, a: list(InputTypes.withName)) => { + let getItem = (p: Input.parameter) => InputTypes.getName(a, p.id); + [ + m.assumptions |> List.map(getItem), + m.inputs |> List.map(getItem), + [InputTypes.getName(a, "output")], + ] + |> List.flatten; +}; + +module MS = Belt.Map.String; + +type modelMaps = { + assumptions: MS.t((Input.parameter, option(InputTypes.t))), + inputs: MS.t((Input.parameter, option(InputTypes.t))), + output: (Output.parameter, option(InputTypes.t)), +}; + +let toMaps = (m: model): modelMaps => { + assumptions: + MS.fromArray( + m.assumptions + |> List.map((r: Input.parameter) => + (r.id, (r, Input.toInput(r.parameterType))) + ) + |> Array.of_list, + ), + inputs: + MS.fromArray( + m.inputs + |> List.map((r: Input.parameter) => + (r.id, (r, Input.toInput(r.parameterType))) + ) + |> Array.of_list, + ), + output: (Output.make(~name="Payouts", ~parameterType=FloatCdf, ()), None), +}; + +type modelParams = { + assumptions: list(option(InputTypes.t)), + inputs: list(option(InputTypes.t)), + output: option(InputTypes.t), +}; + +let response = (m: model, a: list(InputTypes.withName)) => { + let getItem = (p: Input.parameter) => + InputTypes.getName(a, p.id)->Belt.Option.map(InputTypes.withoutName); + { + assumptions: m.assumptions |> List.map(getItem), + inputs: m.inputs |> List.map(getItem), + output: + InputTypes.getName(a, "output") + ->Belt.Option.map(InputTypes.withoutName), + }; +}; \ No newline at end of file diff --git a/src/Prop.re b/src/Prop.re new file mode 100644 index 00000000..87083e36 --- /dev/null +++ b/src/Prop.re @@ -0,0 +1,150 @@ +module Value = { + type t = + | SelectSingle(string) + | FloatPoint(float) + | FloatCdf(string); + + let to_string = (t: t) => { + switch (t) { + | SelectSingle(r) => r + | FloatCdf(r) => r + | FloatPoint(r) => r |> Js.Float.toFixed + }; + }; +}; + +module Type = { + type selectOption = { + id: string, + name: string, + }; + + type selectSingle = { + options: list(selectOption), + default: option(string), + }; + + type floatPoint = {validatations: list(float => bool)}; + + type withDefaultMinMax('a) = { + default: option('a), + min: option('a), + max: option('a), + }; + + type t = + | SelectSingle(selectSingle) + | FloatPoint(withDefaultMinMax(float)) + | Year(withDefaultMinMax(float)) + | FloatCdf; + + let default = (t: t) => + switch (t) { + | Year(r) => r.default->Belt.Option.map(p => Value.FloatPoint(p)) + | SelectSingle(r) => + r.default->Belt.Option.map(p => Value.SelectSingle(p)) + | FloatPoint(r) => r.default->Belt.Option.map(p => Value.FloatPoint(p)) + | FloatCdf => None + }; +}; + +module TypeWithMetadata = { + // TODO: Figure out a better name for assumptionType + type assumptionType = + | INPUT + | ASSUMPTION; + + type t = { + id: string, + name: string, + description: option(string), + type_: Type.t, + assumptionType, + }; + + // TODO: Change default here + let currentYear = { + id: "currentyear", + name: "Current Year", + description: None, + type_: FloatPoint({default: None, min: None, max: None}), + assumptionType: ASSUMPTION, + }; + + let make = + (~name, ~type_, ~id=name, ~description=None, ~assumptionType=INPUT, ()) => { + id, + name, + type_, + description, + assumptionType, + }; +}; + +module ValueMap = { + module MS = Belt.Map.String; + module Combination = { + type t = { + typeWithMetadata: TypeWithMetadata.t, + value: option(Value.t), + }; + let make = (typeWithMetadata, value) => {typeWithMetadata, value}; + let makeWithDefaults = typeWithMetadata => { + typeWithMetadata, + value: Type.default(typeWithMetadata.type_), + }; + }; + type t = MS.t(Combination.t); + let get = MS.get; + let keys = MS.keysToArray; + let map = MS.map; + let fromArray = MS.fromArray; + let values = t => + t |> MS.valuesToArray |> Array.map((r: Combination.t) => r.value); + let types = t => + t + |> MS.valuesToArray + |> Array.map((r: Combination.t) => r.typeWithMetadata); + + let fromTypesWithMetadata = (c: array(TypeWithMetadata.t)) => + c->Belt.Array.map((b: TypeWithMetadata.t) => + (b.name, Combination.makeWithDefaults(b)) + ) + |> fromArray; + + let getValue = (t: t, key: MS.key) => + t->MS.get(key)->Belt.Option.flatMap(r => r.value); + + let getType = (t: t, key: MS.key) => + t->MS.get(key)->Belt.Option.map(r => r.typeWithMetadata); +}; + +module Model = { + type t = { + name: string, + author: string, + inputTypes: list(TypeWithMetadata.t), + ouputTypes: list(TypeWithMetadata.t), + }; + type inputValues = { + inputs: ValueMap.t, + outputSelection: string, + }; + type outputValues = ValueMap.t; + + let toInputDefaults = (t: t): inputValues => { + inputs: t.inputTypes |> Array.of_list |> ValueMap.fromTypesWithMetadata, + outputSelection: "", + }; + + let run = (inputs: inputValues, f) => f(inputs); +}; + +module InputValues = { + type t = Model.inputValues; + let update = (t, str, newValue) => t |> +}; + +module OutputValues = { + type t = ValueMap.t; +}; \ No newline at end of file