123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- module RedCat.DrugsDataExtractor
- open System.Collections.Generic
- open Newtonsoft.Json.Linq
- open FuzzySharp
- open System.IO
- let drugsJson = File.ReadAllText(Path.Combine("/opt/redcatbot/", "drugs.json"))
- let comboJson = File.ReadAllText(Path.Combine("/opt/redcatbot/", "combos.json"))
- let DrugsJsonData = JObject.Parse(drugsJson)
- let ComboJsonData = JObject.Parse(drugsJson)
- let private tryExtractProps (propName: string) (jsonValue: JToken) =
- match jsonValue["properties"][propName] with
- | null -> None
- | token -> token.ToString() |> Some
-
- let private tryExtract (x: string) (jsonValue: JToken) =
- match jsonValue[x] with
- | null -> None
- | token -> token.ToString() |> Some
-
- let private tryExtractArray (fieldName: string) (jsonValue: JToken) =
- match jsonValue[fieldName] with
- | null -> None
- | categories ->
- categories.Values()
- |> Seq.cast<JToken>
- |> Seq.map(fun text -> text.ToString())
- |> Seq.toList |> Some
-
- let private DrugNamesWithAliases =
- DrugsJsonData.Properties()
- |> Seq.map(fun obj ->
- match obj.Value |> tryExtractArray "aliases" with
- | Some aliasesList -> aliasesList |> List.map(fun al -> (al, obj.Name))
- | None -> [(obj.Name, obj.Name)])
- |> Seq.concat
- |> Map.ofSeq
-
- let private DrugNames =
- DrugNamesWithAliases |> Map.values |> Set.ofSeq
- let private search (userInput: string) =
- let clearString (inStr: string) = inStr.Replace("-", "").Replace(",", "")
-
- let findCond (_in: KeyValuePair<string, string>) =
- match (_in.Key, _in.Value) with
- | _, drugName when drugName = userInput || clearString drugName = userInput ->
- drugName |> Some
- | someAlias, drugName when someAlias = userInput -> drugName |> Some
- | _ -> None
-
- let drugNameFound =
- DrugNamesWithAliases
- |> Seq.choose(findCond)
- |> Seq.tryHead
-
- drugNameFound
-
- type DrugRecord = {
- Name: string
- Summary: string option
- Categories: string list option
- OnSet: string option
- TotalDuration: string option
- Dose: string option
- }
- type ComboRecord = {
- DrugA: string
- DrugB: string
- Status: string option
- Note: string option
- }
- type SearchResult =
- | DrugRecord of DrugRecord
- | ResponseText of string
-
- let getComboRecord (userInputA: string) (userInputB: string) =
- let getRecord (jsonValue: JToken) = {
- DrugA = userInputA
- DrugB = userInputB
- Status = jsonValue |> tryExtract "status"
- Note = jsonValue |> tryExtract "note"
- }
- let tryGetCombo drugA drugB =
- match DrugsJsonData[drugA][drugB] with
- | null -> None
- | obj -> Some obj
-
- match (search userInputA, search userInputB) with
- | None, None -> Error $"Can't find both drugs {userInputA} and {userInputB}"
- | Some _, None -> Error $"Can't find second drug {userInputB}"
- | None, Some _ -> Error $"Can't find first drug {userInputA}"
- | Some drugA, Some drugB ->
- tryGetCombo drugA drugB
- |> Option.bind(fun jsonValue -> (getRecord jsonValue) |> Some)
- |> function
- | None -> Error $"Can't find combo from {userInputA} and {userInputB}"
- | Some combo -> combo |> Ok
-
- let getSearchResponse (userInput: string) =
- let matches =
- Process.ExtractTop(userInput, DrugNames)
- |> Seq.choose(fun e -> if e.Score > 62 then e.Value |> Some else None)
- |> String.concat "\n- "
-
- match matches with
- | "" -> Error $"Can't find drug name: {userInput}"
- | matches -> $"- {matches}" |> ResponseText |> Ok
-
- let getDrugRecord (userInput: string) =
- let getRecord (drugName: string) (jsonValue: JToken) = {
- Name = drugName
- Summary = jsonValue |> tryExtractProps "summary"
- Categories = jsonValue |> tryExtractArray "categories"
- OnSet = jsonValue |> tryExtractProps "onset"
- TotalDuration = jsonValue |> tryExtractProps "duration"
- Dose = jsonValue |> tryExtractProps "dose"
- }
- match search userInput with
- | Some drugName -> getRecord drugName DrugsJsonData[drugName] |> DrugRecord |> Ok
- | None -> getSearchResponse userInput
|