Cadel Watson 1 год назад
Родитель
Сommit
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.field "picks" (Decode.list decodePick)
         |> Decode.map Zipper.fromList
         |> Decode.map Zipper.fromList
         |> Decode.andThen
         |> Decode.andThen

+ 13 - 4
src/Main.elm

@@ -1,6 +1,7 @@
 module Main exposing (..)
 module Main exposing (..)
 
 
 import Browser exposing (Document)
 import Browser exposing (Document)
+import Database
 import Draft exposing (Draft)
 import Draft exposing (Draft)
 import Html exposing (Html, button, div, img, span, text)
 import Html exposing (Html, button, div, img, span, text)
 import Html.Attributes exposing (alt, attribute, class, classList, disabled, src)
 import Html.Attributes exposing (alt, attribute, class, classList, disabled, src)
@@ -26,6 +27,7 @@ type Model
 
 
 type alias ReadyModel =
 type alias ReadyModel =
     { draft : Draft
     { draft : Draft
+    , database : Database.Database
     , highlighted : Maybe Draft.PickCard
     , highlighted : Maybe Draft.PickCard
     , flipHighlighted : Bool
     , flipHighlighted : Bool
     }
     }
@@ -38,18 +40,25 @@ type alias ErrorModel =
 
 
 init : { setData : String, draftData : String } -> ( Model, Cmd Msg )
 init : { setData : String, draftData : String } -> ( Model, Cmd Msg )
 init flags =
 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
             ( Ready
                 { draft = draftData
                 { draft = draftData
+                , database = database
                 , highlighted = Nothing
                 , highlighted = Nothing
                 , flipHighlighted = False
                 , flipHighlighted = False
                 }
                 }
             , Cmd.none
             , 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
 type Msg