Browse Source

Updates for EOE

Cadel Watson 4 months ago
parent
commit
fcb0557ada
8 changed files with 110 additions and 26 deletions
  1. 2 1
      .idea/drafter-elm.iml
  2. 31 8
      README.md
  3. 1 1
      data/generate_card_ratings.py
  4. 1 1
      js/app.js
  5. 32 1
      src/Card.elm
  6. 21 12
      src/Database.elm
  7. 20 1
      tests/TestCard.elm
  8. 2 1
      tests/TestDatabase.elm

+ 2 - 1
.idea/drafter-elm.iml

@@ -2,9 +2,10 @@
 <module type="PYTHON_MODULE" version="4">
 <module type="PYTHON_MODULE" version="4">
   <component name="NewModuleRootManager">
   <component name="NewModuleRootManager">
     <content url="file://$MODULE_DIR$">
     <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.venv" />
       <excludeFolder url="file://$MODULE_DIR$/venv" />
       <excludeFolder url="file://$MODULE_DIR$/venv" />
     </content>
     </content>
-    <orderEntry type="jdk" jdkName="Python 3.11 (drafter-elm)" jdkType="Python SDK" />
+    <orderEntry type="jdk" jdkName="Python 3.12 (drafter)" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
   </component>
 </module>
 </module>

+ 31 - 8
README.md

@@ -1,15 +1,38 @@
-# Parcel, Tailwind CSS and Elm boilerplate
+# Drafter
 
 
-The corresponding blog post can be found [on my blog: Using Parcel JS with Tailwind CSS, Elm Lang and Elm Spa](https://vincent.jousse.org/blog/en/2021-09-21-parcel-tailwind-css-elm-lang-elm-spa).
+# UI
 
 
-## Installing
+Install with `npm install`.
 
 
-    npm install
+Run with `npm run start`.
 
 
-## Running DEV env
+Build with `npm run build`.
 
 
-    npm run start
+## Backend
 
 
-## Building
+## Adding a new set
 
 
-    npm run build
+0. Create a new folder in data/sets
+
+Named after the set code, e.g. `data/sets/eoe`.
+
+1. Download card ratings
+
+Log in to 17lands, go to card data, select the set, premier draft format, and top users, then switch to table view.
+
+Click export and download the CSV file.
+
+Save to `data/sets/<CODE>/card-ratings-all.csv`
+
+2. Download updated card data from Scryfall
+
+Go to https://scryfall.com/docs/api/bulk-data and download the Oracle Cards JSON file.
+
+Move it to `data/cards/oracle-cards.json`.
+
+3. Generate the set data
+
+```bash
+cd data
+python generate_card_ratings.py
+```

+ 1 - 1
data/generate_card_ratings.py

@@ -32,7 +32,7 @@ def find_card_with_dual_faces(all_card_data, name):
 
 
 
 
 def main():
 def main():
-    with open("oracle-cards-20250222221022.json") as f:
+    with open("cards/oracle-cards.json") as f:
         all_card_data = json.load(f)
         all_card_data = json.load(f)
 
 
     for set in discover_sets():
     for set in discover_sets():

+ 1 - 1
js/app.js

@@ -1,4 +1,4 @@
-import draftData from "../data/draft_dft.json";
+import draftData from "../data/drafts/draft_tdm_bad.json";
 
 
 import {Elm} from '../src/Main.elm';
 import {Elm} from '../src/Main.elm';
 
 

+ 32 - 1
src/Card.elm

@@ -14,10 +14,11 @@ module Card exposing
     , iwd
     , iwd
     , manaCostToSymbol
     , manaCostToSymbol
     , parseManaCost
     , parseManaCost
+    , parsePower
     , pickRate
     , pickRate
     )
     )
 
 
-import Parser as P exposing ((|.), Parser, Trailing(..))
+import Parser as P exposing ((|.), (|=), Parser, Trailing(..))
 import Stats exposing (NormalDistribution)
 import Stats exposing (NormalDistribution)
 
 
 
 
@@ -43,6 +44,7 @@ type CardType
 
 
 type Power
 type Power
     = ConstantPower Int
     = ConstantPower Int
+    | ConstantPlusVariablePower Int
     | VariablePower
     | VariablePower
 
 
 
 
@@ -368,3 +370,32 @@ manaCostToSymbol c =
 
 
         _ ->
         _ ->
             ""
             ""
+
+
+parsePower : String -> Maybe Power
+parsePower str =
+    case P.run powerP str of
+        Ok result ->
+            Just result
+
+        Err _ ->
+            Nothing
+
+
+powerP : Parser Power
+powerP =
+    let
+        variablePowerP =
+            P.succeed VariablePower |. P.backtrackable (P.keyword "*")
+
+        constantPlusVariablePowerP =
+            P.succeed ConstantPlusVariablePower |= P.backtrackable P.int |. P.backtrackable (P.keyword "+*")
+
+        constantPowerP =
+            P.succeed ConstantPower |= P.int
+    in
+    P.oneOf
+        [ variablePowerP
+        , constantPlusVariablePowerP
+        , constantPowerP
+        ]

+ 21 - 12
src/Database.elm

@@ -1,9 +1,9 @@
 module Database exposing (Database, decode, decoder, encode, fromCardData, get, getAll)
 module Database exposing (Database, decode, decoder, encode, fromCardData, get, getAll)
 
 
-import Card exposing (CardData, CardDetails, CardPerformanceData, CardType(..), ManaColor(..), Power(..), parseManaCost)
+import Card exposing (CardData, CardDetails, CardPerformanceData, CardType(..), ManaColor(..), Power(..), parseManaCost, parsePower)
 import Dict exposing (Dict)
 import Dict exposing (Dict)
 import Json.Decode as Decode exposing (Decoder, decodeString)
 import Json.Decode as Decode exposing (Decoder, decodeString)
-import Json.Decode.Pipeline exposing (optional, required)
+import Json.Decode.Pipeline exposing (custom, optional, required)
 import Json.Encode as Encode
 import Json.Encode as Encode
 import Tuple exposing (pair)
 import Tuple exposing (pair)
 
 
@@ -122,10 +122,20 @@ decodeCardPerformance =
             |> required "ATA" decodeMaybeFloatString
             |> required "ATA" decodeMaybeFloatString
             |> required "ALSA" decodeMaybeFloatString
             |> required "ALSA" decodeMaybeFloatString
             |> required "GIH WR" decodeMaybePercentageString
             |> required "GIH WR" decodeMaybePercentageString
-            |> required "IWD" decodeImprovementWhenDrawn
+            -- 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 : Decoder (Maybe Float)
 decodeImprovementWhenDrawn =
 decodeImprovementWhenDrawn =
     Decode.string
     Decode.string
@@ -277,6 +287,9 @@ encodePower p =
         Just (ConstantPower i) ->
         Just (ConstantPower i) ->
             Encode.string (String.fromInt i)
             Encode.string (String.fromInt i)
 
 
+        Just (ConstantPlusVariablePower i) ->
+            Encode.string (String.fromInt i ++ "+*")
+
         Just VariablePower ->
         Just VariablePower ->
             Encode.string "*"
             Encode.string "*"
 
 
@@ -289,16 +302,12 @@ decodePower =
     Decode.string
     Decode.string
         |> Decode.andThen
         |> Decode.andThen
             (\s ->
             (\s ->
-                if s == "*" then
-                    Decode.succeed VariablePower
+                case parsePower s of
+                    Just p ->
+                        Decode.succeed p
 
 
-                else
-                    case String.toInt s of
-                        Just i ->
-                            Decode.succeed (ConstantPower i)
-
-                        Nothing ->
-                            Decode.fail "Invalid integer"
+                    Nothing ->
+                        Decode.fail ("Could not parse power: " ++ s)
             )
             )
 
 
 
 

+ 20 - 1
tests/TestCard.elm

@@ -1,6 +1,6 @@
 module TestCard exposing (..)
 module TestCard exposing (..)
 
 
-import Card exposing (ManaCost(..))
+import Card exposing (ManaCost(..), ManaColor(..))
 import Expect exposing (Expectation)
 import Expect exposing (Expectation)
 import Fuzz exposing (Fuzzer, int, list, string)
 import Fuzz exposing (Fuzzer, int, list, string)
 import Signals
 import Signals
@@ -19,4 +19,23 @@ suite =
         , test "parseManaCost ('{X}{Y}')" <|
         , test "parseManaCost ('{X}{Y}')" <|
             \_ ->
             \_ ->
                 Expect.equal (Card.parseManaCost "{X}{Y}") (Just [ X, Y ])
                 Expect.equal (Card.parseManaCost "{X}{Y}") (Just [ X, Y ])
+
+        , test "parseManaCost ('{2/G}{2/U}{2/R}')" <|
+            \_ ->
+                Expect.equal (Card.parseManaCost "{2/G}{2/U}{2/R}") (Just [ TwoOrColor Green, TwoOrColor Blue, TwoOrColor Red ])
+        , test "parsePower ('')" <|
+            \_ ->
+                Expect.equal (Card.parsePower "") Nothing
+        , test "parsePower ('1')" <|
+            \_ ->
+                Expect.equal (Card.parsePower "1") (Just (Card.ConstantPower 1))
+        , test "parsePower ('0')" <|
+            \_ ->
+                Expect.equal (Card.parsePower "0") (Just (Card.ConstantPower 0))
+        , test "parsePower ('*')" <|
+            \_ ->
+                Expect.equal (Card.parsePower "*") (Just (Card.VariablePower))
+        , test "parsePower ('1+*')" <|
+            \_ ->
+                Expect.equal (Card.parsePower "1+*") (Just (Card.ConstantPlusVariablePower 1))
         ]
         ]

+ 2 - 1
tests/TestDatabase.elm

@@ -75,7 +75,8 @@ fuzzPower : Fuzzer Power
 fuzzPower =
 fuzzPower =
     Fuzz.oneOf
     Fuzz.oneOf
         [ Fuzz.constant VariablePower
         [ Fuzz.constant VariablePower
-        , Fuzz.int |> Fuzz.map ConstantPower
+        , Fuzz.intAtLeast 0 |> Fuzz.map ConstantPower
+        , Fuzz.intAtLeast 0 |> Fuzz.map ConstantPlusVariablePower
         ]
         ]