ポケモン名を入力すると様々なデータを返すbotを改変してみた(序章)

<h1>概要

こんなLINEbotあったら、ポケモンの対戦中、種族値や特性をカンニング出来て便利だな～と思って作成しようと思ったのがキッカケです。
(半年~1年近くポケモンには触れていませんが)

また、同志の方がqiitaで[導入手順](https://qiita.com/Takayoshi_Makabe/items/e16947fb6be836da6fe7)を公開して下さっておりましたので、今回は先人の知恵をお借りして、機能や仕様を少しだけ改変させてみました。<b>[[github]](https://github.com/rakisuto/linebot)</b>
(でも全然大した改変じゃないので悪しからず...)



<h2>改変内容

<b>1つの名前から関連するポケモンのデータを複数出力するようにしました。

ポケモンの中には、リージョンフォーム(亜種)を持っていたり、サイズごとに異なるパラメータを持っていたり、メガシンカと呼ばれる進化形態を持っていたりと、様々な種類が存在します。
たとえばバケッチャというポケモンは以下の4種類が存在します。

```
 no  |            name            |  type1   | type2 |  ability1  |  ability2  | hiddenability | hp | atk | def | spatk | spdef | speed | total
-----+----------------------------+----------+-------+------------+------------+---------------+----+-----+-----+-------+-------+-------+-------
 710 | バケッチャ(ふつうのサイズ) | ゴースト | くさ  | ものひろい | おみとおし | ふみん        | 49 |  66 |  70 |    44 |    55 |    51 |   335
 710 | バケッチャ(ちいさいサイズ) | ゴースト | くさ  | ものひろい | おみとおし | ふみん        | 44 |  66 |  70 |    44 |    55 |    56 |   335
 710 | バケッチャ(おおきいサイズ) | ゴースト | くさ  | ものひろい | おみとおし | ふみん        | 54 |  66 |  70 |    44 |    55 |    46 |   335
 710 | バケッチャ(とくだいサイズ) | ゴースト | くさ  | ものひろい | おみとおし | ふみん        | 59 |  66 |  70 |    44 |    55 |    41 |   335
(4 行)
```
これらのポケモンを調べるために、スマホで``バケッチャ(ふつうのサイズ)``
と文字を打つのは少し面倒です。
出来れば、バケッチャと入力したら4種類のバケッチャに関する情報がすべて列挙された方が便利かなと思いました。

そこで、main.pyでの既存の処理を修正しました。

【既存の処理】
:man_tone1:LINEユーザがポケモン名を入力
↓
:computer:main.pyの``handle_message``でメッセージを受け取り
``get_response_message``関数によってtableから該当のポケモン名を持つレコードを取得し、呼び出し元に返す。その後レコードの各カラムをユーザに返す。


【修正後の処理】
:man_tone1:LINEユーザがポケモン名を入力
↓
:computer:main.pyの``handle_message``でメッセージを受け取り
``get_response_name``関数によってtableから該当のポケモン名,または括弧付きのポケモン名,または語頭にメガと名の付くポケモン名を複数取得し、呼び出し元に返す。
その後、戻り値として受け取ったポケモン名を``get_response_message``関数に引数として渡す。``get_response_message``関数は渡されたポケモン名をwhere句に指定してtableからレコードの各カラムを取得し、呼び出し元に返す。...といった具合です。



<br>
メインとなる関数や処理は以下のコードです。
全量はgithubにて確認いただければと幸いです。

```python:main.py
def get_response_name(mes_from):
    with get_connection() as conn:
        with conn.cursor(cursor_factory=DictCursor) as cur:
            cur.execute("SELECT name FROM poke_stat \
                WHERE name = '{0}' or name LIKE '{0}(%' or name LIKE 'メガ{0}%'".format(mes_from))
            rows = cur.fetchall()
            return rows

def get_response_message(mes_from):
    with get_connection() as conn:
        with conn.cursor(cursor_factory=DictCursor) as cur:
            cur.execute("SELECT * FROM poke_stat WHERE name = '{}'".format(mes_from))
            rows = cur.fetchall()
            return rows

def handle_message(event):
    # グローバル変数の初期化
    reply_message = ""
    # 入力された名前に完全一致・部分一致するname要素を取得する。
    name_rows = get_response_name(event.message.text)
    # webhook検証対策
    if event.reply_token == "00000000000000000000000000000000":
        return
    # テキストチェック
    if len(name_rows) == 0:
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text="そのようなポケモンは存在しません")
    )
    else:
    # 取得したname要素の行を取得し、返す。
        for i in range(len(name_rows)):
            val_rows = get_response_message(*name_rows[i])
            r = val_rows[0]
            url_no = ('{0:04d}'.format(r[0]))
            reply_message += f'{r[1]}🔻\n\n'\
                             f'全国図鑑No.{r[0]}\n'\
                             f'タイプ1 {r[2]}\n'\
                             f'タイプ2 {r[3] if r[3] else "なし"}\n'\
                             f'特性1 {r[4]}\n'\
                             f'特性2 {r[5] if r[5] else "なし"}\n'\
                             f'隠れ特性 {r[6] if r[6] else "なし"}\n'\
                             f'H  {r[7]}\n'\
                             f'A  {r[8]}\n'\
                             f'B  {r[9]}\n'\
                             f'C  {r[10]}\n'\
                             f'D  {r[11]}\n'\
                             f'S  {r[12]}\n'\
                             f'T  {r[13]}\n\n'\

            if i == (len(name_rows)-1):
                reply_message += f'https://swsh.pokedb.tokyo/pokemon/show/{url_no}-00?season=15&rule=0'\

        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=reply_message)
        )

```




<h2>Input

PostgresSQLにポケモンのデータベースとなるcsvファイルをインポートします。
今回は[こちらのサイト](https://rikapoke.com/pokemon_data8gen/)で公開されている現時点で登場している全てのポケモンのデータを網羅したcsvファイルを利用させて頂きました。


<h2>機能

以下、実際に文字を打ち込んだ際の挙動です。
![Screenshot_2021-02-17-23-42-41-88.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558257/f58007a3-4551-d258-8fa9-477ce2a29f2d.jpeg)
名前を入力するとDBから対象のnameを参照して、全国図鑑,タイプ,その他各種パラメータを返します。

さきほど話題に上がっていたバケッチャも、
このように取得することが出来ました。
![Screenshot_2021-02-20-00-03-22-72.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558257/a4d34166-8928-e31d-e720-5f9230b24aac.jpeg)

![Screenshot_2021-02-20-00-03-33-42.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558257/377ebb83-4c40-96a6-c443-31888452d7b4.jpeg)

<h2>更なる改善

今後は、bs4によるwebスクレイピングを使って
そのポケモンの使用率や使用する技のランキングなどを出力できるようにしたいです。
既にスクレイピングのロジックは完成しているので
あとはUX/UIの部分を改善して、例えばLINEのカルーセルボタンなんかを使って
横にスライドしながら見れるようにしたり
日本語表記でも対応できるように改変するといったところです。

<h3>終わりに

今回はpythonというよりpostgresの操作がメインでした。
よかったらLINEに追加してみてください。
https://t.co/HYTztWPQYU?amp=1

<h3>参考にさせて頂いたサイト:bow:

https://qiita.com/Takayoshi_Makabe/items/e16947fb6be836da6fe7
https://rikapoke.com/pokemon_data8gen/