Skip to content

Commit

Permalink
refact: moved unit functions to units
Browse files Browse the repository at this point in the history
  • Loading branch information
Casper Bollen authored and Casper Bollen committed Nov 30, 2023
1 parent 440fda1 commit 0322eb1
Show file tree
Hide file tree
Showing 2 changed files with 295 additions and 49 deletions.
247 changes: 246 additions & 1 deletion src/Informedica.GenForm.Lib/Scripts/Update.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -386,4 +386,249 @@ module Types =
Patient : Patient
DoseRule : DoseRule
SolutionRules : SolutionRule []
}
}


[<AutoOpen>]
module Utils =

open System
open System.IO
open System.Net.Http

open Informedica.Utils.Lib
open Informedica.Utils.Lib.BCL



module Web =


/// The url to the data sheet for Constraints
let [<Literal>] dataUrlIdConstraints = "1nny8rn9zWtP8TMawB3WeNWhl5d4ofbWKbGzGqKTd49g"


/// The url to the data sheet for GenPRES
/// https://docs.google.com/spreadsheets/d/1AEVYnqjAbVniu3VuczeoYvMu3RRBu930INhr3QzSDYQ/edit?usp=sharing
let [<Literal>] dataUrlIdGenPres = "1AEVYnqjAbVniu3VuczeoYvMu3RRBu930INhr3QzSDYQ"


/// <summary>
/// Get data from a web sheet
/// </summary>
/// <param name="urlId">The Url Id of the web sheet</param>
/// <param name="sheet">The specific sheet</param>
/// <returns>The data as a table of string array array</returns>
let getDataFromSheet urlId sheet =
fun () -> Web.GoogleSheets.getDataFromSheet urlId sheet
|> StopWatch.clockFunc $"loaded {sheet} from web sheet"



module BigRational =


/// <summary>
/// Parse an array of strings in float format to an array of BigRational
/// </summary>
/// <remarks>
/// Uses ; as separator. Filters out non parsable strings.
/// </remarks>
/// <example>
/// <code>
/// let brs = toBrs "1.0;2.0;3.0"
/// // returns [|1N; 2N; 3N|]
/// let brs = toBrs "1.0;2.0;3.0;abc"
/// // returns [|1N; 2N; 3N|]
/// </code>
/// </example>
let toBrs s =
s
|> String.splitAt ';'
|> Array.choose Double.tryParse
|> Array.choose BigRational.fromFloat


/// <summary>
/// Return 2 BigRational arrays as a tuple of optional first BigRational
/// of the first and second array. A None is returned for an empty array.
/// </summary>
/// <example>
/// <code>
/// let brs1 = [|1N|]
/// let brs2 = [|4N|]
/// tupleBrOpt brs1 brs2
/// // returns (Some 1N, Some 4N)
/// let brs1 = [|1N|]
/// let brs2 = [||]
/// tupleBrOpt brs1 brs2
/// // returns (Some 1N, None)
/// </code>
/// </example>
let tupleBrOpt brs1 brs2 =
brs1 |> Array.tryHead,
brs2 |> Array.tryHead




module Mapping =

open Informedica.Utils.Lib
open Informedica.Utils.Lib.BCL
open Informedica.GenUnits.Lib


/// Mapping of long Z-index route names to short names
let routeMapping =
Web.getDataFromSheet Web.dataUrlIdGenPres "Routes"
|> fun data ->
let getColumn =
data
|> Array.head
|> Csv.getStringColumn

data
|> Array.tail
|> Array.map (fun r ->
let get = getColumn r

{|
Long = get "ZIndex"
Short = get "ShortDutch"
|}
)


/// Mapping of long Z-index unit names to short names
let unitMapping =
Web.getDataFromSheet Web.dataUrlIdGenPres "Units"
|> fun data ->
let getColumn =
data
|> Array.head
|> Csv.getStringColumn

data
|> Array.tail
|> Array.map (fun r ->
let get = getColumn r

{|
Long = get "ZIndexUnitLong"
Short = get "Unit"
MV = get "MetaVisionUnit"
|}
)


/// Try to find mapping for a route
let mapRoute rte =
routeMapping
|> Array.tryFind (fun r ->
r.Long |> String.equalsCapInsens rte ||
r.Short |> String.equalsCapInsens rte

)
|> Option.map (fun r -> r.Short)


/// Try to map a unit to a short name
let mapUnit unt =
unitMapping
|> Array.tryFind (fun r ->
r.Long |> String.equalsCapInsens unt ||
r.Short |> String.equalsCapInsens unt
)
|> Option.map (fun r -> r.Short)


/// Get the array of RouteShape records
let mappingRouteShape =
Web.getDataFromSheet Web.dataUrlIdGenPres "ShapeRoute"
|> fun data ->
let inline getColumn get =
data
|> Array.head
|> get

data
|> Array.tail
|> Array.map (fun r ->
let getStr = getColumn Csv.getStringColumn r
let getFlt = getColumn Csv.getFloatOptionColumn r

{
Route = getStr "Route"
Shape = getStr "Shape"
Unit = getStr "Unit" |> Units.fromString |> Option.defaultValue NoUnit
DoseUnit = getStr "DoseUnit" |> Units.fromString |> Option.defaultValue NoUnit
MinDoseQty = None // getFlt "MinDoseQty"
MaxDoseQty = None //getFlt "MaxDoseQty"
Timed = getStr "Timed" |> String.equalsCapInsens "true"
Reconstitute = getStr "Reconstitute" |> String.equalsCapInsens "true"
IsSolution = getStr "IsSolution" |> String.equalsCapInsens "true"
}
|> fun rs ->
match rs.DoseUnit with
| NoUnit -> rs
| du ->
{ rs with
MinDoseQty =
getFlt "MinDoseQty"
|> Option.bind (fun v ->
v
|> BigRational.fromFloat
|> Option.map (ValueUnit.singleWithUnit du)
)
MaxDoseQty =
getFlt "MaxDoseQty"
|> Option.bind (fun v ->
v
|> BigRational.fromFloat
|> Option.map (ValueUnit.singleWithUnit du)
)
}
)


/// <summary>
/// Filter the mappingRouteShape array on route, shape and unit
/// </summary>
/// <param name="rte">The Route</param>
/// <param name="shape">The Shape</param>
/// <param name="unt">The Unit</param>
/// <returns>An array of RouteShape records</returns>
let filterRouteShapeUnit rte shape unt =
mappingRouteShape
|> Array.filter (fun xs ->
let eqsRte =
rte |> String.isNullOrWhiteSpace ||
rte |> String.trim |> String.equalsCapInsens xs.Route ||
xs.Route |> mapRoute |> Option.map (String.equalsCapInsens (rte |> String.trim)) |> Option.defaultValue false
let eqsShp = shape |> String.isNullOrWhiteSpace || shape |> String.trim |> String.equalsCapInsens xs.Shape
let eqsUnt =
unt = NoUnit ||
unt = xs.Unit
eqsRte && eqsShp && eqsUnt
)

(*
let private requires_ (rtes, unt, shape) =
rtes
|> Array.collect (fun rte ->
filterRouteShapeUnit rte shape unt
)
|> Array.map (fun xs -> xs.Reconstitute)
|> Array.exists id
/// Check if reconstitution is required for a route, shape and unit
let requiresReconstitution =
Memoization.memoize requires_
*)


Mapping.mappingRouteShape[9]
Loading

0 comments on commit 0322eb1

Please sign in to comment.