Database.elm 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. module Database exposing (Database, decode, get, getAll)
  2. import Card exposing (CardData, CardDetails, CardPerformanceData, CardType(..), ManaColor(..), Power(..), parseManaCost)
  3. import Dict exposing (Dict)
  4. import Json.Decode as Decode exposing (Decoder, decodeString)
  5. import Json.Decode.Pipeline exposing (optional, required)
  6. import Tuple exposing (pair)
  7. type Database
  8. = Database (Dict String CardData)
  9. get : String -> Database -> Maybe CardData
  10. get name (Database db) =
  11. Dict.get name db
  12. getAll : Database -> List CardData
  13. getAll (Database db) =
  14. Dict.values db
  15. decode : String -> Result String ( String, Maybe Database )
  16. decode setData =
  17. let
  18. decoder : Decoder ( String, Maybe Database )
  19. decoder =
  20. Decode.map2 pair
  21. (Decode.field "code" Decode.string)
  22. (Decode.field "data"
  23. (Decode.nullable
  24. (Decode.map2 createDatabase
  25. (Decode.field "ratings" decodePerformanceData)
  26. (Decode.field "cards" decodeSetData)
  27. )
  28. )
  29. )
  30. in
  31. decodeString decoder setData |> Result.mapError Decode.errorToString
  32. createDatabase : Dict String CardPerformanceData -> Dict String CardDetails -> Database
  33. createDatabase performanceData detailsData =
  34. Dict.merge
  35. (\_ _ cardData -> cardData)
  36. (\name performance details -> Dict.insert name (CardData details performance))
  37. (\_ _ cardData -> cardData)
  38. performanceData
  39. detailsData
  40. Dict.empty
  41. |> Database
  42. decodePerformanceData : Decoder (Dict String CardPerformanceData)
  43. decodePerformanceData =
  44. Decode.list decodeCardPerformance
  45. |> Decode.map Dict.fromList
  46. |> Decode.map (Debug.log "perf")
  47. decodeSetData : Decoder (Dict String CardDetails)
  48. decodeSetData =
  49. Decode.list decodeCardDetails
  50. |> Decode.map Dict.fromList
  51. decodeCardPerformance : Decoder ( String, CardPerformanceData )
  52. decodeCardPerformance =
  53. Decode.map2 pair
  54. (Decode.field "Name" Decode.string)
  55. (Decode.succeed CardPerformanceData
  56. |> required "# Seen" decodeIntString
  57. |> required "# Picked" decodeIntString
  58. |> required "ATA" decodeMaybeFloatString
  59. |> required "ALSA" decodeMaybeFloatString
  60. |> required "GIH WR" decodeMaybePercentageString
  61. |> required "IWD" decodeImprovementWhenDrawn
  62. )
  63. decodeImprovementWhenDrawn : Decoder (Maybe Float)
  64. decodeImprovementWhenDrawn =
  65. Decode.string
  66. |> Decode.andThen
  67. (\s ->
  68. if s == "" then
  69. Decode.succeed Nothing
  70. else
  71. case String.toFloat (String.replace "pp" "" s) of
  72. Just i ->
  73. Decode.succeed (Just i)
  74. Nothing ->
  75. Decode.succeed Nothing
  76. )
  77. decodeIntString : Decoder Int
  78. decodeIntString =
  79. Decode.string
  80. |> Decode.andThen
  81. (\s ->
  82. case String.toInt s of
  83. Just i ->
  84. Decode.succeed i
  85. Nothing ->
  86. Decode.fail "Invalid integer"
  87. )
  88. decodeMaybeFloatString : Decoder (Maybe Float)
  89. decodeMaybeFloatString =
  90. Decode.string
  91. |> Decode.andThen
  92. (\s ->
  93. if s == "" then
  94. Decode.succeed Nothing
  95. else
  96. case String.toFloat s of
  97. Just i ->
  98. Decode.succeed (Just i)
  99. Nothing ->
  100. Decode.succeed Nothing
  101. )
  102. decodeMaybePercentageString : Decoder (Maybe Float)
  103. decodeMaybePercentageString =
  104. Decode.string
  105. |> Decode.andThen
  106. (\s ->
  107. if s == "" then
  108. Decode.succeed Nothing
  109. else
  110. case String.toFloat (String.replace "%" "" s) of
  111. Just i ->
  112. Decode.succeed (Just (i / 100))
  113. Nothing ->
  114. Decode.succeed Nothing
  115. )
  116. decodeCardDetails : Decoder ( String, CardDetails )
  117. decodeCardDetails =
  118. Decode.map2 pair
  119. (Decode.field "name" Decode.string)
  120. (Decode.succeed CardDetails
  121. |> required "name" Decode.string
  122. |> required "cmc" Decode.int
  123. |> required "type_line" decodeCardType
  124. |> required "type_line" Decode.string
  125. |> optional "oracle_text" (Decode.nullable Decode.string) Nothing
  126. |> optional "power" (Decode.nullable decodePower) Nothing
  127. |> optional "toughness" (Decode.nullable decodePower) Nothing
  128. |> required "colors" (Decode.list decodeManaColor)
  129. |> required "mana_cost"
  130. (Decode.string
  131. |> Decode.andThen
  132. (\s ->
  133. case parseManaCost s of
  134. Just m ->
  135. Decode.succeed (Just m)
  136. Nothing ->
  137. Decode.succeed Nothing
  138. )
  139. )
  140. |> required "image_uris" (Decode.field "large" Decode.string)
  141. )
  142. decodePower : Decoder Power
  143. decodePower =
  144. Decode.string
  145. |> Decode.andThen
  146. (\s ->
  147. if s == "*" then
  148. Decode.succeed VariablePower
  149. else
  150. case String.toInt s of
  151. Just i ->
  152. Decode.succeed (ConstantPower i)
  153. Nothing ->
  154. Decode.fail "Invalid integer"
  155. )
  156. decodeManaColor : Decoder ManaColor
  157. decodeManaColor =
  158. Decode.string
  159. |> Decode.andThen
  160. (\c ->
  161. case c of
  162. "R" ->
  163. Decode.succeed Red
  164. "U" ->
  165. Decode.succeed Blue
  166. "G" ->
  167. Decode.succeed Green
  168. "W" ->
  169. Decode.succeed White
  170. "B" ->
  171. Decode.succeed Black
  172. "C" ->
  173. Decode.succeed Colorless
  174. _ ->
  175. Decode.fail "Invalid mana color"
  176. )
  177. decodeCardType : Decoder CardType
  178. decodeCardType =
  179. Decode.string
  180. |> Decode.map
  181. (\c ->
  182. if String.contains "Creature" c then
  183. Creature
  184. else if String.contains "Instant" c then
  185. Instant
  186. else if String.contains "Sorcery" c then
  187. Sorcery
  188. else if String.contains "Enchantment" c then
  189. Enchantment
  190. else if String.contains "Artifact" c then
  191. Artifact
  192. else if String.contains "Planeswalker" c then
  193. Planeswalker
  194. else if String.contains "Land" c then
  195. Land
  196. else
  197. Other
  198. )