DrugsDataExtractor.fs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. module RedCat.DrugsDataExtractor
  2. open System.Collections.Generic
  3. open Newtonsoft.Json.Linq
  4. open FuzzySharp
  5. open System.IO
  6. let drugsJson = File.ReadAllText(Path.Combine("/opt/redcatbot/", "drugs.json"))
  7. let comboJson = File.ReadAllText(Path.Combine("/opt/redcatbot/", "combos.json"))
  8. let DrugsJsonData = JObject.Parse(drugsJson)
  9. let ComboJsonData = JObject.Parse(drugsJson)
  10. let private tryExtractProps (propName: string) (jsonValue: JToken) =
  11. match jsonValue["properties"][propName] with
  12. | null -> None
  13. | token -> token.ToString() |> Some
  14. let private tryExtract (x: string) (jsonValue: JToken) =
  15. match jsonValue[x] with
  16. | null -> None
  17. | token -> token.ToString() |> Some
  18. let private tryExtractArray (fieldName: string) (jsonValue: JToken) =
  19. match jsonValue[fieldName] with
  20. | null -> None
  21. | categories ->
  22. categories.Values()
  23. |> Seq.cast<JToken>
  24. |> Seq.map(fun text -> text.ToString())
  25. |> Seq.toList |> Some
  26. let private DrugNamesWithAliases =
  27. DrugsJsonData.Properties()
  28. |> Seq.map(fun obj ->
  29. match obj.Value |> tryExtractArray "aliases" with
  30. | Some aliasesList -> aliasesList |> List.map(fun al -> (al, obj.Name))
  31. | None -> [(obj.Name, obj.Name)])
  32. |> Seq.concat
  33. |> Map.ofSeq
  34. let private DrugNames =
  35. DrugNamesWithAliases |> Map.values |> Set.ofSeq
  36. let private search (userInput: string) =
  37. let clearString (inStr: string) = inStr.Replace("-", "").Replace(",", "")
  38. let findCond (_in: KeyValuePair<string, string>) =
  39. match (_in.Key, _in.Value) with
  40. | _, drugName when drugName = userInput || clearString drugName = userInput ->
  41. drugName |> Some
  42. | someAlias, drugName when someAlias = userInput -> drugName |> Some
  43. | _ -> None
  44. let drugNameFound =
  45. DrugNamesWithAliases
  46. |> Seq.choose(findCond)
  47. |> Seq.tryHead
  48. drugNameFound
  49. type DrugRecord = {
  50. Name: string
  51. Summary: string option
  52. Categories: string list option
  53. OnSet: string option
  54. TotalDuration: string option
  55. Dose: string option
  56. }
  57. type ComboRecord = {
  58. DrugA: string
  59. DrugB: string
  60. Status: string option
  61. Note: string option
  62. }
  63. type SearchResult =
  64. | DrugRecord of DrugRecord
  65. | ResponseText of string
  66. let getComboRecord (userInputA: string) (userInputB: string) =
  67. let getRecord (jsonValue: JToken) = {
  68. DrugA = userInputA
  69. DrugB = userInputB
  70. Status = jsonValue |> tryExtract "status"
  71. Note = jsonValue |> tryExtract "note"
  72. }
  73. let tryGetCombo drugA drugB =
  74. match DrugsJsonData[drugA][drugB] with
  75. | null -> None
  76. | obj -> Some obj
  77. match (search userInputA, search userInputB) with
  78. | None, None -> Error $"Can't find both drugs {userInputA} and {userInputB}"
  79. | Some _, None -> Error $"Can't find second drug {userInputB}"
  80. | None, Some _ -> Error $"Can't find first drug {userInputA}"
  81. | Some drugA, Some drugB ->
  82. tryGetCombo drugA drugB
  83. |> Option.bind(fun jsonValue -> (getRecord jsonValue) |> Some)
  84. |> function
  85. | None -> Error $"Can't find combo from {userInputA} and {userInputB}"
  86. | Some combo -> combo |> Ok
  87. let getSearchResponse (userInput: string) =
  88. let matches =
  89. Process.ExtractTop(userInput, DrugNames)
  90. |> Seq.choose(fun e -> if e.Score > 62 then e.Value |> Some else None)
  91. |> String.concat "\n- "
  92. match matches with
  93. | "" -> Error $"Can't find drug name: {userInput}"
  94. | matches -> $"- {matches}" |> ResponseText |> Ok
  95. let getDrugRecord (userInput: string) =
  96. let getRecord (drugName: string) (jsonValue: JToken) = {
  97. Name = drugName
  98. Summary = jsonValue |> tryExtractProps "summary"
  99. Categories = jsonValue |> tryExtractArray "categories"
  100. OnSet = jsonValue |> tryExtractProps "onset"
  101. TotalDuration = jsonValue |> tryExtractProps "duration"
  102. Dose = jsonValue |> tryExtractProps "dose"
  103. }
  104. match search userInput with
  105. | Some drugName -> getRecord drugName DrugsJsonData[drugName] |> DrugRecord |> Ok
  106. | None -> getSearchResponse userInput