128 lines
No EOL
4.1 KiB
Forth
128 lines
No EOL
4.1 KiB
Forth
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 |