Database.elm 6.8 KB

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