| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- module Database exposing (Database, decode, decoder, encode, fromCardData, get, getAll)
- import Card exposing (CardData, CardDetails, CardPerformanceData, CardType(..), ManaColor(..), Power(..), Rarity(..), parseManaCost, parsePower)
- import Dict exposing (Dict)
- import Json.Decode as Decode exposing (Decoder, decodeString)
- import Json.Decode.Pipeline exposing (custom, optional, required)
- import Json.Encode as Encode
- import Tuple exposing (pair)
- type Database
- = Database (Dict String CardData)
- fromCardData : List CardData -> Database
- fromCardData cards =
- List.map (\card -> ( card.details.name, card )) cards
- |> Dict.fromList
- |> Database
- get : String -> Database -> Maybe CardData
- get name (Database db) =
- Dict.get name db
- getAll : Database -> List CardData
- getAll (Database db) =
- Dict.values db
- decode : String -> Result String ( String, Maybe Database )
- decode setData =
- decodeString decoder setData |> Result.mapError Decode.errorToString
- decoder : Decoder ( String, Maybe Database )
- decoder =
- Decode.map2 pair
- (Decode.field "code" Decode.string)
- (Decode.field "data"
- (Decode.nullable
- (Decode.map2 createDatabase
- (Decode.field "ratings" decodePerformanceData)
- (Decode.field "cards" decodeSetData)
- )
- )
- )
- databaseToDict : Database -> Dict String CardData
- databaseToDict (Database db) =
- db
- encode : ( String, Database ) -> Encode.Value
- encode ( setCode, Database db ) =
- Encode.object
- [ ( "code", Encode.string setCode )
- , ( "data"
- , Encode.object
- [ ( "ratings", Encode.list encodeCardPerformance (Dict.values db) )
- , ( "cards", Encode.list encodeCardDetails (Dict.values db) )
- ]
- )
- ]
- createDatabase : Dict String CardPerformanceData -> Dict String CardDetails -> Database
- createDatabase performanceData detailsData =
- Dict.merge
- (\_ _ cardData -> cardData)
- (\name performance details -> Dict.insert name (CardData details performance))
- (\_ _ cardData -> cardData)
- performanceData
- detailsData
- Dict.empty
- |> Database
- decodePerformanceData : Decoder (Dict String CardPerformanceData)
- decodePerformanceData =
- Decode.list decodeCardPerformance
- |> Decode.map Dict.fromList
- decodeSetData : Decoder (Dict String CardDetails)
- decodeSetData =
- Decode.list decodeCardDetails
- |> Decode.map Dict.fromList
- encodeCardPerformance : CardData -> Encode.Value
- encodeCardPerformance d =
- Encode.object
- [ ( "Name", Encode.string d.details.name )
- , ( "# Seen", encodeIntString d.performance.totalTimesSeen )
- , ( "# Picked", encodeIntString d.performance.totalTimesPicked )
- , ( "ATA", encodeMaybeFloatString d.performance.averagePickPosition )
- , ( "ALSA", encodeMaybeFloatString d.performance.averageSeenPosition )
- , ( "GIH WR", encodeMaybePercentageString d.performance.gameInHandWinRate )
- , ( "IWD"
- , Encode.string
- (case d.performance.improvementWhenDrawn of
- Just i ->
- String.fromFloat i ++ "pp"
- Nothing ->
- ""
- )
- )
- ]
- decodeCardPerformance : Decoder ( String, CardPerformanceData )
- decodeCardPerformance =
- Decode.map2 pair
- (Decode.field "Name" Decode.string)
- (Decode.succeed CardPerformanceData
- |> required "# Seen" decodeIntString
- |> required "# Picked" decodeIntString
- |> required "ATA" decodeMaybeFloatString
- |> required "ALSA" decodeMaybeFloatString
- |> required "GIH WR" decodeMaybePercentageString
- -- The improvement when drawn changed to improvement in hand in newer set data
- -- from 17lands
- |> custom decodeIIHOrIWD
- )
- decodeIIHOrIWD : Decoder (Maybe Float)
- decodeIIHOrIWD =
- Decode.oneOf
- [ Decode.at [ "IIH" ] decodeImprovementWhenDrawn
- , Decode.at [ "IWD" ] decodeImprovementWhenDrawn
- ]
- decodeImprovementWhenDrawn : Decoder (Maybe Float)
- decodeImprovementWhenDrawn =
- Decode.string
- |> Decode.andThen
- (\s ->
- if s == "" then
- Decode.succeed Nothing
- else
- case String.toFloat (String.replace "pp" "" s) of
- Just i ->
- Decode.succeed (Just i)
- Nothing ->
- Decode.succeed Nothing
- )
- encodeIntString : Int -> Encode.Value
- encodeIntString i =
- Encode.string (String.fromInt i)
- decodeIntString : Decoder Int
- decodeIntString =
- Decode.string
- |> Decode.andThen
- (\s ->
- case String.toInt s of
- Just i ->
- Decode.succeed i
- Nothing ->
- Decode.fail "Invalid integer"
- )
- encodeMaybeFloatString : Maybe Float -> Encode.Value
- encodeMaybeFloatString m =
- case m of
- Just f ->
- Encode.string (String.fromFloat f)
- Nothing ->
- Encode.string ""
- decodeMaybeFloatString : Decoder (Maybe Float)
- decodeMaybeFloatString =
- Decode.string
- |> Decode.andThen
- (\s ->
- if s == "" then
- Decode.succeed Nothing
- else
- case String.toFloat s of
- Just i ->
- Decode.succeed (Just i)
- Nothing ->
- Decode.succeed Nothing
- )
- encodeMaybePercentageString : Maybe Float -> Encode.Value
- encodeMaybePercentageString m =
- case m of
- Just f ->
- Encode.string (String.fromFloat (f * 100) ++ "%")
- Nothing ->
- Encode.string ""
- decodeMaybePercentageString : Decoder (Maybe Float)
- decodeMaybePercentageString =
- Decode.string
- |> Decode.andThen
- (\s ->
- if s == "" then
- Decode.succeed Nothing
- else
- case String.toFloat (String.replace "%" "" s) of
- Just i ->
- Decode.succeed (Just (i / 100))
- Nothing ->
- Decode.succeed Nothing
- )
- encodeCardDetails : CardData -> Encode.Value
- encodeCardDetails card =
- Encode.object
- [ ( "name", Encode.string card.details.name )
- , ( "cmc", Encode.int card.details.cmc )
- , ( "type_line", Encode.string card.details.typeLine )
- , ( "oracle_text"
- , case card.details.oracleText of
- Just t ->
- Encode.string t
- Nothing ->
- Encode.null
- )
- , ( "power", encodePower card.details.power )
- , ( "toughness", encodePower card.details.toughness )
- , ( "colors", Encode.list encodeManaColor card.details.colors )
- , ( "mana_cost", Encode.string card.details.rawManaCost )
- , ( "image_uris", Encode.object [ ( "large", Encode.string card.details.imageUrl ) ] )
- , ( "rarity", encodeRarity card.details.rarity )
- ]
- encodeRarity : Rarity -> Encode.Value
- encodeRarity r =
- case r of
- Common ->
- Encode.string "common"
- Uncommon ->
- Encode.string "uncommon"
- Rare ->
- Encode.string "rare"
- Mythic ->
- Encode.string "mythic"
- NoRarity ->
- Encode.string ""
- decodeCardDetails : Decoder ( String, CardDetails )
- decodeCardDetails =
- Decode.map2 pair
- (Decode.field "name" Decode.string)
- (Decode.succeed CardDetails
- |> required "name" Decode.string
- |> required "cmc" Decode.int
- |> required "type_line" decodeCardType
- |> required "type_line" Decode.string
- |> optional "oracle_text" (Decode.nullable Decode.string) Nothing
- |> optional "power" (Decode.nullable decodePower) Nothing
- |> optional "toughness" (Decode.nullable decodePower) Nothing
- |> required "colors" (Decode.list decodeManaColor)
- |> required "mana_cost" Decode.string
- |> required "mana_cost"
- (Decode.string
- |> Decode.andThen
- (\s ->
- case parseManaCost s of
- Just m ->
- Decode.succeed (Just m)
- Nothing ->
- Decode.succeed Nothing
- )
- )
- |> required "image_uris" (Decode.field "large" Decode.string)
- |> optional "rarity" decodeRarity NoRarity
- )
- encodePower : Maybe Power -> Encode.Value
- encodePower p =
- case p of
- Just (ConstantPower i) ->
- Encode.string (String.fromInt i)
- Just (ConstantPlusVariablePower i) ->
- Encode.string (String.fromInt i ++ "+*")
- Just VariablePower ->
- Encode.string "*"
- Nothing ->
- Encode.null
- decodePower : Decoder Power
- decodePower =
- Decode.string
- |> Decode.andThen
- (\s ->
- case parsePower s of
- Just p ->
- Decode.succeed p
- Nothing ->
- Decode.fail ("Could not parse power: " ++ s)
- )
- encodeManaColor : ManaColor -> Encode.Value
- encodeManaColor c =
- case c of
- Red ->
- Encode.string "R"
- Blue ->
- Encode.string "U"
- Green ->
- Encode.string "G"
- White ->
- Encode.string "W"
- Black ->
- Encode.string "B"
- Colorless ->
- Encode.string "C"
- decodeManaColor : Decoder ManaColor
- decodeManaColor =
- Decode.string
- |> Decode.andThen
- (\c ->
- case c of
- "R" ->
- Decode.succeed Red
- "U" ->
- Decode.succeed Blue
- "G" ->
- Decode.succeed Green
- "W" ->
- Decode.succeed White
- "B" ->
- Decode.succeed Black
- "C" ->
- Decode.succeed Colorless
- _ ->
- Decode.fail "Invalid mana color"
- )
- decodeCardType : Decoder CardType
- decodeCardType =
- Decode.string
- |> Decode.map
- (\c ->
- if String.contains "Creature" c then
- Creature
- else if String.contains "Instant" c then
- Instant
- else if String.contains "Sorcery" c then
- Sorcery
- else if String.contains "Enchantment" c then
- Enchantment
- else if String.contains "Artifact" c then
- Artifact
- else if String.contains "Planeswalker" c then
- Planeswalker
- else if String.contains "Land" c then
- Land
- else
- Other
- )
- decodeRarity : Decoder Rarity
- decodeRarity =
- Decode.string
- |> Decode.map
- (\r ->
- if String.contains "mythic" r then
- Mythic
- else if String.contains "rare" r then
- Rare
- else if String.contains "uncommon" r then
- Uncommon
- else if String.contains "common" r then
- Common
- else
- NoRarity
- )
|