アイカツ！のマイページから情報を取得するやつを作る 番外編その2 - 取得したデータで遊んでみる

# はじめに

この記事は、[アイカツ！ Advent Calendar 2018](https://adventar.org/calendars/3700)の**15日目**の記事です。内容としては、現在大好評稼働中のアーケードゲーム、[データカードダス アイカツフレンズ！](http://www.aikatsu.com/friends/)のマイページから情報を取得するツールを作成中で、その内容と進捗の紹介になります。

前日の記事は[kakakaya](https://adventar.org/users/24462)による[アイカツ！のマイページから情報を取得するやつを作る その2 - Qiita](https://qiita.com/kakakaya/items/513bf6ac78bfff52068a)でした。

ちなみに、これまでアイカツ！ Advent Calendar 2018では以下のような技術系記事が投稿されています。


- [アイカツ！画像でLGTMできるChrome拡張機能をストアに公開しました - matのブログ](https://romiogaku.hateblo.jp/entry/2018/12/01/223906)
    - 2日目
- [Aikatsu Music Medoly - アトリエあざらし](http://blog.a-azarashi.jp/entry/2018/12/05/060344)
    - 5日目
- [アイカツ！のマイページから情報を取得するやつを作る その1 - Qiita](https://qiita.com/kakakaya/items/0371752db771d1cede4d)
    - 7日目
- [アイカツ！のマイページから情報を取得するやつを作る 番外編その1 - 各環境で実行可能なバイナリをgoreleaserでビルドしてGitHub Releasesでリリースする](https://qiita.com/kakakaya/items/509de4f246fc27f63e66)
    - 11日目
- [冴草きいちゃんがアイカツ!画像を探してくれるdiscord botを作った話 - nyakuroのブログ](http://cat-b.hatenadiary.jp/entry/2018/12/12/204912)
    - 12日目
- [アイカツ！のマイページから情報を取得するやつを作る その2 - Qiita](https://qiita.com/kakakaya/items/513bf6ac78bfff52068a)
    - 14日目


# aikatsu-dcd-parser
[kakakaya/aikatsu-dcd-parser: Fetch and parse Aikatsu! DCD mypage data.](https://github.com/kakakaya/aikatsu-dcd-parser)
取得及びパースをするライブラリ本体と、それを利用したCLIツールの2つが含まれており、いずれも `dcdkatsu` という名前でインポートや実行が可能です。詳細はこれまでの記事や[README](https://github.com/kakakaya/aikatsu-dcd-parser/blob/master/README.md)、[GoDoc](https://godoc.org/github.com/kakakaya/aikatsu-dcd-parser)などを参照してください。

# 遊ぶ
ある程度作ったところで誰か別の方が遊んでみる記事を出すかなと期待していたものの出なかったので自分で遊び方のサンプルを作ろうと思いました。

ステップバイステップで解説しているので、とにかく試してみたい！という方は下の方に[ワンライナーをまとめてある](https://qiita.com/kakakaya/items/e9dd7b56b9f666b28875#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB)のでそちらを参照してください。
## 準備
この記事でやってることを自分で試したい場合、以下のツールを導入しておく必要があります。

- `dcdkatsu` : この一連の記事で作っているデータカードダス アイカツフレンズ！からデータを取得するツール。この記事を書いている時点での最新版はv0.3.0です。
    - go 1.11.2位が入った環境で`go get -u -v github.com/kakakaya/aikatsu-dcd-parser/cmd/dcdkatsu`
    - または、[リリースページ](https://github.com/kakakaya/aikatsu-dcd-parser/releases)から自分のOSに対応する最新版をダウンロード
        - もし自分のOSやアーキテクチャに対応するものがない！という方は言ってくだされば対応します。
- `jq` : JSONをよしなにやるやつ
    - [stedolan/jq: Command-line JSON processor](https://github.com/stedolan/jq)
- `fzf` : fuzzy matching（曖昧検索）で絞り込むやつ
    - [junegunn/fzf: A command-line fuzzy finder](https://github.com/junegunn/fzf)
- `catimg` : ターミナルに画像を表示するやつ
    - [posva/catimg: Insanely fast image printing in your terminal](https://github.com/posva/catimg)


## 各弾の獲得済み・未獲得カード枚数を調べてみる
v0.2.0からデジタルバインダーやカードを取得する機能が追加され、各弾ごとのカード一覧や取得状況、各カードの詳細なデータを調べることが可能になりました。とはいえ、生の出力は以下のような感じなので、機械には読みやすい形式ですが人間の方は見にくいと感じるかもしれません。
（`owned:true` になっているものが獲得済み、`owned:false` になっているものが未獲得を表しています。カードの詳細がほとんど空になっているのは、通信回数を最小限にして不要なサーバへの通信を防ぐためで、詳細情報の取得については後半で取り扱います。）

```json:デジタルバインダーの出力例
{
  "series_id": 16,
  "series_name": "フレンズ5弾",
  "cards": [
    {
      "code": "F5-1", "name": "", "rarity": "BFR", "stars": "", "type": "", "category": "", "brand": "", "dress_appeal": "", "appeal_point": 0, "owner_id": "RX...3x", "owned": false, "series_id": 16,
      "url": "http://mypage.aikatsu.com/mypages/detail/NP10_H5_U_PR_Qt_001_T01/_00/16/RX...3x/",
      "image_url": "http://mypage.aikatsu.com/images/cardlist/card/458005/f5-1bfr_00.png"
    },
    {
      "code": "F5-2", "name": "", "rarity": "BFR", "stars": "", "type": "", "category": "", "brand": "", "dress_appeal": "", "appeal_point": 0, "owner_id": "RX...3x", "owned": false, "series_id": 16,
      "url": "http://mypage.aikatsu.com/mypages/detail/NP10_H5_U_PR_Qt_001_B01/_00/16/RX...3x/",
      "image_url": "http://mypage.aikatsu.com/images/cardlist/card/458005/f5-2bfr_00.png"
    },
    ...
  ],
  "owner_id": "RX...3x",
  "url": "http://mypage.aikatsu.com/mypages/digital_binders/RX...3x/16",
  "data_get_date": "2018-12-15T14:09:00+09:00"
}
```

これを、人間にも読みやすい形式にしてみようと思います。

1. 取得したいユーザーのIDを確認する
    - 例えば自分自身のデータを取得したい場合、[マイページ](http://mypage.aikatsu.com/)からログインして、最下部のSNS共有ボタンからURLを得られます。
        - http://mypage.aikatsu.com/mypages/index/RX...3x/ のような形式。
    - そのうちの`RX...3x`の部分をユーザーIDと呼称しています。
        - プライバシー保護の観点から一部を`...`にしていますが、実際には英数字のみが含まれるようです。
2. デジタルバインダーのデータを取得し、一旦ファイルに保存する
    - `dcdkatsu binder "RX...3x" 15 > digital_binder.json`
    - 15は4弾を表しています。16が5弾、12が1弾に相当しているようです。
3. カード以外の情報を見てみる
    - `cat digital_binder.json | jq 'del(.cards)'`
    
    ```json
{
    "series_id": 15,
    "series_name": "フレンズ4弾",
  "owner_id": "RX...3x",
  "url": "http://mypage.aikatsu.com/mypages/digital_binders/RX...3x/15",
  "data_get_date": "2018-12-15T13:36:00+09:00"
}
    ```
    - 良さげですね。 
4. カードが全部で何枚あるのか見てみる
    - `cat digital_binder.json | jq '.cards | length'`
    
    ```json
112
    ```
5. 取得済みカードが何枚あるのか見てみる
    - `cat digital_binder.json | jq '.cards | map(select(.owned == true)) | group_by(.) | length'`
    
    ```json
61
    ```
5. 未取得カードが何枚あるのか見てみる
    - `cat digital_binder.json | jq '.cards | map(select(.owned == false)) | group_by(.) | length'`
    
    ```json
51
    ```
    - ミュージアムをやり忘れてたのが敗因です。
6. BFRの取得率を確認する
    - v0.3.0からバインダー内の通し番号（`F5-1` みたいなやつ、以下コードと呼称）とレアリティも取得できるようになりました。これを利用して、BFRのカードだけで取得率を確認してみます。
    - まずBFRの枚数を確認してみます。
        - `cat digital_binder.json  | jq '.cards | map(select(.rarity == "BFR")) | length'`
        - => `24`
    - 所持済みのものに絞って枚数を確認する
        - `cat digital_binder.json  | jq '.cards | map(select(.rarity == "BFR")) | map(select(.owned == true)) | length'`
        - => `16`
    - というわけで、2/3を獲得できていたようです。
        - （group_byを活用してワンライナーでやろうとしていたものの思いつかず失敗）

## カードの詳細を表示してみる
カードについても見ていきましょう。上記バインダー関連のコマンドから得られるURLを指定することで、以下のようなデータが取得されます。

`dcdkatsu card http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_T02/_00/15/RX...3x/`

```json
{
  "code": "F4-24",
  "name": "ブリリアントソワレトップス",
  "rarity": "ベストフレンズレア",
  "stars": "★★★",
  "type": "クール",
  "category": "トップス",
  "brand": "ノーブランド",
  "dress_appeal": "ベストフレンズマーチ",
  "appeal_point": 950,
  "owner_id": "RX...3x",
  "owned": false,
  "series_id": 15,
  "url": "http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_T02/_00/15/RX...3x",
  "image_url": "http://mypage.aikatsu.com/images/cardlist/card/458004/f4-24bfr_00.png"
}
```

はい。先程のdigital_binderと組み合わせて、「所持していないカードの中から絞り込み検索で画像を確認する」みたいなことをやっていきましょう。
`cat digital_binder.json  | jq -c '.cards | map(select(.rarity == "BFR")) | map(select(.owned == false)) | .[] | "\(.code)  \(.url)"' | sed 's/"//g'`

```
F4-17  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_PR_Co_002_B01/_00/15/RX...3x/
F4-19  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_PR_Co_002_A01/_00/15/RX...3x/
F4-20  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_T01/_00/15/RX...3x/
F4-22  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_S01/_00/15/RX...3x/
F4-24  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_T02/_00/15/RX...3x/
F4-44  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_PR_Se_001_B01/_00/15/RX...3x/
F4-45  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_PR_Se_001_S01/_00/15/RX...3x/
F4-49  http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_PR_Se_002_S01/_00/15/RX...3x/
```
曖昧検索のツールである`fzf`を利用して上から絞り込んでみます。

`cat digital_binder.json  | jq -c '.cards | map(select(.rarity == "BFR")) | map(select(.owned == false)) | .[] | "\(.code)  \(.url)"' | sed 's/"//g' | fzf | cut -d ' ' -f 3`
そして、例えば"F-24"のカードを指定すると、以下のようにURLのみを得ることができます。
`http://mypage.aikatsu.com/mypages/detail/NP09_H4_U_R_Co_001_T02/_00/15/RX...3x/`


これを上記カード取得や画像表示と組み合わせてみましょう。

`image="$(cat digital_binder.json  | jq -c '.cards | map(select(.rarity == "BFR")) | map(select(.owned == false)) | .[] | "\(.code)  \(.url)"' | sed 's/"//g' | fzf | cut -d ' ' -f 3 | xargs -n 1 -I % dcdkatsu card % | jq '.image_url' | sed 's/"//g')"; wget $image && echo $image | awk -F '/' '{print $NF}' | xargs -n 1 -I % catimg %`

上記コマンドで画像をダウンロードしてcatimgでターミナルへ出力した例が以下のようになります。

![2018-12-15_15-13-38.png](https://qiita-image-store.s3.amazonaws.com/0/80036/000209de-2fdb-3b26-a86f-9e39851118ea.png)
一番下にプロンプトが表示されてるのが確認できるでしょうか。


# おわりに
本記事ではいくつかの遊び方を書きました。まとめてみましょう。

- 4弾の持ってないカードを数える
    -  `dcdkatsu binder "RX...3x" 15 | jq '.cards | map(select(.owned == false)) | group_by(.) | length'`
- 持っていない4弾のBFRカードを選択して画像を取得し、ターミナルに出力する
    - `image="$(dcdkatsu binder "RX...3x" 15  | jq -c '.cards | map(select(.rarity == "BFR")) | map(select(.owned == false)) | .[] | "\(.code)  \(.url)"' | sed 's/"//g' | fzf | cut -d ' ' -f 3 | xargs -n 1 -I % dcdkatsu card % | jq '.image_url' | sed 's/"//g')"; wget $image && echo $image | awk -F '/' '{print $NF}' | xargs -n 1 -I % catimg %`
    - `jq`の引数をいじると色々できます。

他にも次のような遊び方ができそうです。

- カードの取得日時を自動で記録する
- デジタルバインダーをオフライン用に出力する
- アピールポイントが高い順・低い順に並び替える
- などなど

今後も `aikatsu-dcd-parser`の機能追加を行っていく予定ですので、それによりより多くの遊び方ができるかもしれません。

なお、今後以下のような機能の実装を考えています。

- 取得間隔の制限（サーバへの負荷を防ぐため）
- 取得可能な機能の追加
  - ログインが必要な部分の取得
    - フレンズ
    - バッジ
    - ランキング実績
    - 大会実績
    - アーカイブ
      - アイカツスターズ！1弾〜5弾
      - アイカツスターズ！星のツバサ編
      - ↑色々違っていて面倒そうという気分
- 取得結果の保存、差分表示
- テストの作成、CI
    - やるだけ
    - ランキング周りが面倒そう
    - v0.2.0でアホなミスしたので早く入れたい
- リリース方法のいい感じ化
    - .debを配布したい
    - AURに置きたい

他にも欲しい機能やマサカリがあったら、この記事のコメントにお願いします。これは非公式なものであり、データカードダス アイカツフレンズ！公式や、バンダイナムコ、その他権利者の方に問い合わせないようお願いします。また、怒られたらすぐに消します。

明日は未定です。