Browse Source

Add CMC chart

Cadel Watson 1 năm trước cách đây
mục cha
commit
76630ebabe
3 tập tin đã thay đổi với 145 bổ sung13 xóa
  1. 12 2
      elm.json
  2. 43 0
      src/Deck.elm
  3. 90 11
      src/Main.elm

+ 12 - 2
elm.json

@@ -11,12 +11,22 @@
             "elm/core": "1.0.5",
             "elm/html": "1.0.0",
             "elm/json": "1.1.3",
-            "myrho/elm-round": "1.0.5"
+            "elm-community/list-extra": "8.7.0",
+            "myrho/elm-round": "1.0.5",
+            "terezka/elm-charts": "4.0.0"
         },
         "indirect": {
+            "K-Adam/elm-dom": "1.0.0",
+            "danhandrea/elm-time-extra": "1.1.0",
+            "elm/parser": "1.1.0",
+            "elm/svg": "1.0.1",
             "elm/time": "1.0.0",
             "elm/url": "1.0.0",
-            "elm/virtual-dom": "1.0.2"
+            "elm/virtual-dom": "1.0.2",
+            "justinmimbs/date": "4.1.0",
+            "justinmimbs/time-extra": "1.2.0",
+            "ryan-haskell/date-format": "1.0.0",
+            "terezka/intervals": "2.0.2"
         }
     },
     "test-dependencies": {

+ 43 - 0
src/Deck.elm

@@ -0,0 +1,43 @@
+module Deck exposing (Deck, cmcCurve, fromDraft)
+
+import Card exposing (CardData)
+import Database exposing (Database)
+import Draft exposing (Draft)
+import List.Extra as List exposing (group)
+import Zipper
+
+
+type alias Deck =
+    { cards : List CardData }
+
+
+fromDraft : Bool -> Database -> Draft -> Deck
+fromDraft includeWholeDeck db draft =
+    let
+        picks =
+            if includeWholeDeck then
+                Zipper.toList draft |> List.map .chosen
+
+            else
+                (Zipper.focus draft :: Zipper.left draft) |> List.map .chosen
+
+        cards =
+            List.filterMap (\pick -> Database.get pick.name db) picks
+    in
+    { cards = cards }
+
+
+cmcCurve : Deck -> List ( Int, Int )
+cmcCurve deck =
+    let
+        maxBucket =
+            7
+
+        cmcs =
+            deck.cards
+                |> List.map (.details >> .cmc)
+    in
+    (List.range 0 maxBucket
+        |> List.map (\cmc -> ( cmc, List.count (\x -> x == cmc) cmcs ))
+    )
+        ++ [ ( maxBucket, List.count (\x -> x >= maxBucket) cmcs ) ]

+ 90 - 11
src/Main.elm

@@ -2,13 +2,18 @@ module Main exposing (..)
 
 import Browser exposing (Document)
 import Card exposing (CardData)
+import Chart as C
+import Chart.Attributes as CA
 import Database
+import Deck
 import Draft exposing (Draft)
 import Html exposing (Html, button, div, img, span, text)
 import Html.Attributes exposing (alt, class, classList, disabled, src)
 import Html.Events as Events exposing (onClick)
 import Html.Keyed as Keyed
+import List.Extra as List
 import Round
+import Tuple exposing (second)
 import Zipper
 
 
@@ -26,6 +31,11 @@ type Model
     | Error ErrorModel
 
 
+type DeckProgress
+    = EntireDeck
+    | DeckUpToPick
+
+
 type FocusStat
     = FocusALSA
     | FocusALPA
@@ -39,6 +49,7 @@ type alias ReadyModel =
     , highlighted : Maybe Draft.PickCard
     , flipHighlighted : Bool
     , focusStat : FocusStat
+    , deckProgress : DeckProgress
     }
 
 
@@ -57,6 +68,7 @@ init flags =
                 , highlighted = Nothing
                 , flipHighlighted = False
                 , focusStat = FocusPickRate
+                , deckProgress = DeckUpToPick
                 }
             , Cmd.none
             )
@@ -77,6 +89,7 @@ type Msg
     | Highlight Draft.PickCard
     | FlipHighlightedCard
     | SetFocusStat FocusStat
+    | SetDeckProgress DeckProgress
 
 
 update : Msg -> Model -> ( Model, Cmd Msg )
@@ -105,6 +118,9 @@ update msg model =
                 SetFocusStat stat ->
                     ( Ready { mdl | focusStat = stat }, Cmd.none )
 
+                SetDeckProgress progress ->
+                    ( Ready { mdl | deckProgress = progress }, Cmd.none )
+
         Error mdl ->
             ( Error mdl, Cmd.none )
 
@@ -135,19 +151,82 @@ viewReady model =
 viewSidebar : ReadyModel -> Html Msg
 viewSidebar model =
     div [ class "col-span-2 p-6 bg-slate-600" ]
-        [ button
-            [ onClick Decrement
-            , disabled (not (Zipper.hasLeft model.draft))
-            , class "bg-slate-900 rounded text-white p-2 shadow disabled:opacity-50"
+        [ div []
+            [ button
+                [ onClick Decrement
+                , disabled (not (Zipper.hasLeft model.draft))
+                , class "bg-slate-900 rounded text-white p-2 shadow disabled:opacity-50"
+                ]
+                [ text "Previous" ]
+            , span [ class "text-white px-3 font-medium" ] [ text ("Pick " ++ String.fromInt (Zipper.position model.draft)) ]
+            , button
+                [ onClick Increment
+                , class "bg-slate-900 rounded text-white p-2 shadow disabled:opacity-50"
+                , disabled (not (Zipper.hasRight model.draft))
+                ]
+                [ text "Next" ]
+            ]
+        , viewDeck model
+        ]
+
+
+viewDeck : ReadyModel -> Html Msg
+viewDeck model =
+    div [ class "mt-6" ]
+        [ div [ class "w-full flex" ]
+            [ button
+                [ onClick (SetDeckProgress DeckUpToPick)
+                , disabled (model.deckProgress == DeckUpToPick)
+                , classList
+                    [ ( "grow border-b-2 text-white pb-2", True )
+                    , ( "border-slate-300 font-medium"
+                      , model.deckProgress == DeckUpToPick
+                      )
+                    , ( "border-slate-900"
+                      , model.deckProgress /= DeckUpToPick
+                      )
+                    ]
+                ]
+                [ text "Up to current pick" ]
+            , button
+                [ onClick (SetDeckProgress EntireDeck)
+                , disabled (model.deckProgress == EntireDeck)
+                , classList
+                    [ ( "grow border-b-2 text-white pb-2", True )
+                    , ( "border-slate-300 font-medium"
+                      , model.deckProgress == EntireDeck
+                      )
+                    , ( "border-slate-900"
+                      , model.deckProgress /= EntireDeck
+                      )
+                    ]
+                ]
+                [ text "Entire deck" ]
+            ]
+        , viewCmcChart model
+        ]
+
+
+viewCmcChart : ReadyModel -> Html Msg
+viewCmcChart model =
+    let
+        deck =
+            Deck.fromDraft (model.deckProgress == EntireDeck) model.database model.draft
+
+        cmcs =
+            Deck.cmcCurve deck
+
+        bars =
+            C.bars [] [ C.bar (second >> toFloat) [] ] cmcs
+    in
+    div [ class "m-4" ]
+        [ C.chart
+            [ CA.height 300
             ]
-            [ text "Previous" ]
-        , span [ class "text-white px-3 font-medium" ] [ text ("Pick " ++ String.fromInt (Zipper.position model.draft)) ]
-        , button
-            [ onClick Increment
-            , class "bg-slate-900 rounded text-white p-2 shadow disabled:opacity-50"
-            , disabled (not (Zipper.hasRight model.draft))
+            [ C.xLabels []
+            , C.yLabels [ CA.withGrid ]
+            , bars
             ]
-            [ text "Next" ]
         ]