かしのブログ

競技プログラミングとか

Elmを使った

GWにElmの勉強をしたのでそのまとめ

つくったもの

ポケモンの育成時のパラメータからバトルに使うステータスを計算するアプリケーション。

ポケモンの名前で検索して育成の数値を入力すると最終的なパラメータが計算される。

f:id:tnyo43:20190506124331p:plain

https://tnyo43.github.io/PokemonStatus/

動機

Elmをやってみたかった

冬に出る剣盾用に自分用のツールを作りたい

Elmの勉強

勉強にはこの本を使った。

www.amazon.co.jpAmazon CAPTCHA

あとYouTubeの動画も参考にした。この方は以前参加したElmのハンズオンをやってた方で、説明もとてもわかりやすい。

Elmのカウンターアプリを作りました - YouTube

あとは適当に作りながら調べた。特にCmdとかDecoderのところは書けるまでに結構苦戦した(後述)

開発

API

ポケモンのパラメータを取得するのに「PokéAPI」を用いた。 ポケモンの名前から必要なパラメータとタイプ、画像が得られる。

ただ、これだけだとポケモンの英語名か図鑑番号を入力する必要があったので、「GitHub - kotofurumiya/pokemon_data: 全ポケモンのJSONデータです。」のデータを使わせていただいた。

ページを開くとすべてのポケモンの日本語名から図鑑番号を調べるDictを作成して(Dict String Int)、検索するときに図鑑番号を調べられるようにしている。

Cmd

HttpGetとか乱数とか、副作用が生じうるものはCmdで扱うらしい

ページにアクセスするとHttpGetでポケモンの日本語名のデータを取ろうとするので、このときもCmdを使用する必要がある

init _ =
    ( Model "" Nothing Dict.empty
    , Http.get
        { url = urlJapanese
        , expect = Http.expectJson JapaneseData pokeJpsDecoder } )


-- updateの一部抜粋
        JapaneseData res ->
            case res of 
                Ok lst -> -- lstの型はList PokeJP
                    ( { model | data = getPokemonNameDict lst }, Cmd.none )
                Err e -> ( { model | data = Dict.empty }, Cmd.none )

type alias PokeJp =
    { no : Int
    , name : String
    }

一度自分で書くとなんてことはなく、これの他にポケモンのパラメータと画像のデータを取得するためにもHttpGetをしているが、そちらはすんなりと書けた

Model

Elmの一番シンプルだと思うのが、modelを更新するとviewも更新される仕組み

作っプログラムでは、

  • 初期状態ではなにも表示せず、検索すると出てくる → ポケモンの型はMaybe Pokemonにすればいい
  • 入力文字列を知る必要がある → Stringのinputが必要
  • 前述の名前と番号を調べる辞書が必要 -> Dict String Int

が必要で、あとはボタンとかHttpGetの結果でこれらを更新するだけなので、本当に手間が少ない

type alias Model =
    { inputName : String
    , pokemon : Maybe Pokemon
    , data : Dict String Int
    }

コンパイルエラー

全部コンパイルエラーが教えてくれるので実行時に悩まなくてよいのがありがたい

あとのエラーは全部JSONの扱いだった

テスト

規模が小さいので量は大したことがないが、実数値の計算はテストも作りながらしたので自信を持って使える

もっと見やすいテストを書けるようにしたい

振り返り

アプリ作るの苦手だったがわりとストレスなく楽しかった。自分も含めて初心者向きだと思う

CSSはほとんど気にしなかったのでこれからつくる

今後の改善

  • 数値の入力を直す(使いにくい)
  • CSSを使ってUIを改善
  • 任意のレベルで実数値を求める
  • メガ進化、フォームチェンジに対応
  • 持ち物に対応