فهرست منبع

Parse card database

Cadel Watson 1 سال پیش
والد
کامیت
0369cdf6a4
3فایلهای تغییر یافته به همراه222 افزوده شده و 6 حذف شده
  1. 202 0
      src/Database.elm
  2. 7 2
      src/Draft.elm
  3. 13 4
      src/Main.elm

+ 202 - 0
src/Database.elm

@@ -0,0 +1,202 @@
+module Database exposing (Database, decode)
+
+import Dict exposing (Dict)
+import Json.Decode as Decode exposing (Decoder, decodeString)
+import Json.Decode.Pipeline exposing (optional, required)
+import Tuple exposing (pair)
+
+
+type Database
+    = Database (Dict String CardData)
+
+
+type ManaColor
+    = Red
+    | Blue
+    | Green
+    | White
+    | Black
+    | Colorless
+
+
+type CardType
+    = Creature
+    | Instant
+    | Sorcery
+    | Enchantment
+    | Artifact
+    | Planeswalker
+    | Land
+    | Other
+
+
+type Power
+    = ConstantPower Int
+    | VariablePower
+
+
+type alias CardData =
+    { details : CardDetails
+    , performance : CardPerformanceData
+    }
+
+
+type alias CardDetails =
+    { cmc : Int
+    , cardType : CardType
+    , typeLine : String
+    , oracleText : String
+    , power : Maybe Power
+    , toughness : Maybe Power
+    , colors : List ManaColor
+
+    --, manaCost : List ManaColor
+    }
+
+
+type alias CardPerformanceData =
+    { totalTimesSeen : Int
+    , totalTimesPicked : Int
+    , averagePickPosition : Maybe Float
+    , averageSeenPosition : Maybe Float
+    , gameInHandWinRate : Maybe Float
+    }
+
+
+decode : String -> String -> Result String Database
+decode setData draftData =
+    case ( decodeString decodeSetData setData, decodeString decodePerformanceData draftData ) of
+        ( Ok set, Ok draft ) ->
+            Ok (createDatabase draft set |> Database)
+
+        ( Err err, _ ) ->
+            Err <| Decode.errorToString err
+
+        ( _, Err err ) ->
+            Err <| Decode.errorToString err
+
+
+createDatabase : Dict String CardPerformanceData -> Dict String CardDetails -> Dict String CardData
+createDatabase performanceData detailsData =
+    Dict.merge
+        (\_ _ cardData -> cardData)
+        (\name performance details -> Dict.insert name (CardData details performance))
+        (\_ _ cardData -> cardData)
+        performanceData
+        detailsData
+        Dict.empty
+
+
+decodePerformanceData : Decoder (Dict String CardPerformanceData)
+decodePerformanceData =
+    Decode.field "card_performance_data"
+        (Decode.dict decodeCardPerformance)
+
+
+decodeSetData : Decoder (Dict String CardDetails)
+decodeSetData =
+    Decode.list decodeCardDetails
+        |> Decode.map Dict.fromList
+
+
+decodeCardPerformance : Decoder CardPerformanceData
+decodeCardPerformance =
+    Decode.succeed CardPerformanceData
+        |> required "total_times_seen" Decode.int
+        |> required "total_times_picked" Decode.int
+        |> required "avg_pick_position" (Decode.nullable Decode.float)
+        |> required "avg_seen_position" (Decode.nullable Decode.float)
+        |> required "game_in_hand_win_rate" (Decode.nullable Decode.float)
+
+
+decodeCardDetails : Decoder ( String, CardDetails )
+decodeCardDetails =
+    Decode.map2 pair
+        (Decode.field "name" Decode.string)
+        (Decode.succeed CardDetails
+            |> required "cmc" Decode.int
+            |> required "type_line" decodeCardType
+            |> required "type_line" Decode.string
+            |> required "oracle_text" Decode.string
+            |> optional "power" (Decode.nullable decodePower) Nothing
+            |> optional "toughness" (Decode.nullable decodePower) Nothing
+            |> required "colors" (Decode.list decodeManaColor)
+        )
+
+
+decodePower : Decoder Power
+decodePower =
+    Decode.string
+        |> Decode.andThen
+            (\s ->
+                if s == "*" then
+                    Decode.succeed VariablePower
+
+                else
+                    case String.toInt s of
+                        Just i ->
+                            Decode.succeed (ConstantPower i)
+
+                        Nothing ->
+                            Decode.fail "Invalid integer"
+            )
+
+
+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
+            )

+ 7 - 2
src/Draft.elm

@@ -22,8 +22,13 @@ type alias PickCard =
     }
 
 
-decode : Decoder Draft
-decode =
+decode : String -> Result String Draft
+decode x =
+    Decode.decodeString decodeDraft x |> Result.mapError Decode.errorToString
+
+
+decodeDraft : Decoder Draft
+decodeDraft =
     Decode.field "picks" (Decode.list decodePick)
         |> Decode.map Zipper.fromList
         |> Decode.andThen

+ 13 - 4
src/Main.elm

@@ -1,6 +1,7 @@
 module Main exposing (..)
 
 import Browser exposing (Document)
+import Database
 import Draft exposing (Draft)
 import Html exposing (Html, button, div, img, span, text)
 import Html.Attributes exposing (alt, attribute, class, classList, disabled, src)
@@ -26,6 +27,7 @@ type Model
 
 type alias ReadyModel =
     { draft : Draft
+    , database : Database.Database
     , highlighted : Maybe Draft.PickCard
     , flipHighlighted : Bool
     }
@@ -38,18 +40,25 @@ type alias ErrorModel =
 
 init : { setData : String, draftData : String } -> ( Model, Cmd Msg )
 init flags =
-    case decodeString Draft.decode flags.draftData of
-        Ok draftData ->
+    case ( Draft.decode flags.draftData, Database.decode flags.setData flags.draftData ) of
+        ( Ok draftData, Ok database ) ->
             ( Ready
                 { draft = draftData
+                , database = database
                 , highlighted = Nothing
                 , flipHighlighted = False
                 }
             , Cmd.none
             )
 
-        Err _ ->
-            ( Error { error = "Error decoding draft data" }, Cmd.none )
+        ( Err err, Ok _ ) ->
+            ( Error { error = "Error decoding draft data: " ++ err }, Cmd.none )
+
+        ( Ok _, Err err ) ->
+            ( Error { error = "Error decoding set data: " ++ err }, Cmd.none )
+
+        ( Err draftError, Err databaseError ) ->
+            ( Error { error = "Error decoding draft data: " ++ draftError ++ ", set data: " ++ databaseError }, Cmd.none )
 
 
 type Msg