ごごちと申します。
これまでジムバトルの最適パーティを
考えてきました。
攻撃側の最適化
【ポケモンGO】ジムバトルにおける最適パーティを最短経路問題で考えます【バトルチーム】
防衛側の最適化
最適ジム防衛パーティを最短経路問題で考察しました!【ポケモンGO】【ジム防衛】
攻撃側と防衛側がお互いに最適化を行うことで
どのような組合せに行き着くのかを
知りたいと思っています。
今回はポケマピ様のダメージ計算ツールから
攻撃側ポケモンと防衛側ポケモンを指定すると
撃破時間を自動取得するプログラムを作成
したので紹介したいと思います。
DB自動取得プログラム実行の様子
ポケマピ様のダメージ計算ツールに対して、
撃破時間を自動で取得する
Pythonプログラムを作成しました。
コードは後ほど記載します。
ダメージ計算ツールにポケモンの情報を入力し、
撃破時間を取得するプログラムになっています。
- 自分ポケモン入力
- 敵ポケモン入力
- 自分Lv入力
- 敵Lv入力
- 「計算する」ボタン押下
- 指定した技組合せの撃破時間を取得
実行後に生成される撃破時間DB
プログラム実行後には上の様なテーブルが生成され
.xlsx形式で保存されます。
各セルには
攻撃側のポケモン、
ノーマルアタック、
スペシャルアタック
に対応する防衛ポケモンへの
討伐時間が記載されています。
攻撃側候補ポケモンと
防衛側候補ポケモンを増やすと
さらに広大なテーブルデータになります。
DB自動取得プログラムの背景
これまで紹介したページでは、
攻撃側も防衛側も、
候補ポケモンの数や技の組合せが
限定されていました。
以下の2点がその理由です。
- 撃破時間DB作成が手作業で時間がかかる
- 組合せで計算量が爆発的に増えてしまう
今回は1.「撃破時間DB作成」を
自動化することにしました。
上の図の様に、
攻撃側と防衛側のポケモンの組合せの数だけ
撃破時間を取得する必要があります。
攻撃側候補が18匹、
防衛側候補が18匹とすると、
18×18 = 324 通り
の撃破時間が必要になります。
ポケマピ様のダメージ計算ツールで
1組当たり撃破時間を取得し、
excelなどに転記するのにかかる時間が
平均20秒とすると、
324通りの時間を入力するのに
108分=2時間弱かかります。
追加で候補ポケモンを増やしたい場合などには
後から作業が増えてしまいます。
さらに技の組合せなどを変えたも
一から作業をやり直す必要があります。
しかし、データ取得を自動化することで、
技の組合せが異なる場合でも
同様にデータ取得することができます。
まとめると、
DB自動取得プログラムを作成することで
以下の様なメリットがあります。
- DB作成の自動化(放置でDB作成)
- DB作成の効率化(手作業に比べ10倍以上の速度で取得可能)
- データの幅がひろがる(異なる技の組合せでも取得可能)
DB自動取得プログラム
import numpy as np
import pandas as pd
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver import ActionChains
#chromeでアクセス
options = webdriver.ChromeOptions()
################################################################################################################################################################
# chromedriver.exeの場所を指定
service = webdriver.chrome.service.Service(executable_path = 'C:\\Users\\xxxxxxxx\\Desktop\\PokemonGo_project\\20230607_scraping\\chromedriver.exe')
################################################################################################################################################################
driver = webdriver.Chrome(service=service, options=options)
driver.get('https://pokemongo-get.com/damagecal/')
time.sleep(10)
select_list_A = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[1]/div/div[3]/div[4]/select')
# Selectオブジェクトを作成
dropdownA = Select(select_list_A)
# 選択肢を選択
dropdownA.select_by_visible_text('50')
select_list_B = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[2]/div/div[3]/div[4]/select')
# Selectオブジェクトを作成
dropdownB = Select(select_list_B)
# 選択肢を選択
dropdownB.select_by_visible_text('50')
#シャドウポケモンON
#shadow_button = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[1]/div/table/tbody/tr/td[2]')
#shadow_button.click()
# 検索欄取得
search_box_A = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[1]/div/input')
search_box_B = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[2]/div/input')
# ポケモンを受け取ったら撃破時間を取得する関数
def get_defeat_time(attack_pokemon, defence_pokemon):
keyword_A=attack_pokemon[0]
keyword_B=defence_pokemon
search_box_A.clear()
search_box_B.clear()
search_box_A.send_keys(keyword_A)
search_box_B.send_keys(keyword_B)
result_button = driver.find_element(By.XPATH, '//*[@id="app"]/button[2]')
result_button.click()
time.sleep(2)
# result_tableの要素を取得
result_table = driver.find_element(By.XPATH, '//*[@id="app"]/div[3]/div[6]/table/tbody')
# result_tableから<tr>要素を取得
tr_elements = result_table.find_elements(By.TAG_NAME, 'tr')
# 取得した<tr>要素を処理する
for tr in tr_elements[1:]:
figures = tr.find_elements(By.XPATH, './/*[contains(@class,"text-center")]')
rank=figures[0].text
defeat_time = float(figures[1].text)
moves = tr.find_elements(By.XPATH, './/*[contains(@class,"flex-list-auto")]')
fast_move = moves[0].text
special_move = moves[1].text
if (attack_pokemon[1] in fast_move) and (attack_pokemon[2] in special_move):
print(keyword_A, ' vs ', keyword_B)
print(rank)
print(fast_move,special_move)
print(defeat_time)
return defeat_time
attack_pokemons = [
["カミツルギ","はっぱカッター","リーフブレード"],
["レシラム","ほのおのキバ","クロスフレイム"],
["カイオーガ","たきのぼり","こんげんのはどう"],
["デンジュモク","でんきショック","ほうでん"],
["マンムー","こなゆき","ゆきなだれ"],
["ルカリオ","カウンター","はどうだん"],
["ウツロイド","どくづき","ヘドロばくだん"],
["グラードン","マッドショット","だんがいのつるぎ"],
["ファイヤー","つばさでうつ","ゴッドバード"],
["ミュウツー","サイコカッター","サイコブレイク"],
["フェローチェ","むしくい","むしのさざめき"],
["ラムパルド","うちおとす","いわなだれ"],
["ゲンガー","したでなめる","シャドーボール"],
["パルキア","ドラゴンテール","りゅうせいぐん"],
["ダークライ","バークアウト","あくのはどう"],
["メタグロス","バレットパンチ","コメットパンチ"],
["サーナイト","あまえる","マジカルシャイン"],
["ポリゴンZ","ロックオン","はかいこうせん"],
]
defence_pokemons = ["ハピナス",
"ソーナンス",
"ラッキー",
"トゲキッス",
"メタグロス",
"カイリュー",
"ベトベトン",
"ベトベトン(アローラ)",
"ヤドキング(ガラル)",
"デスカーン",
"デスバーン",
"ミカルゲ",
"ヌメルゴン",
"ミロカロス",
"カビゴン",
"ラグラージ",
"パンプジン(とくだい)",
"サーフゴー",
]
# 動作確認&デモ用
attack_pokemons=attack_pokemons[:3]
defence_pokemons=defence_pokemons[:2]
df_time = pd.DataFrame(index=np.arange(len(attack_pokemons)),columns=["attack_pokemon","fast_move","special_move"])
for i,attack_pokemon in enumerate(attack_pokemons):
df_time.loc[i,"attack_pokemon"]=attack_pokemon[0]
df_time.loc[i,"fast_move"]=attack_pokemon[1]
df_time.loc[i,"special_move"]=attack_pokemon[2]
for j,defence_pokemon in enumerate(defence_pokemons):
defeat_time = get_defeat_time(attack_pokemon,defence_pokemon)
df_time.loc[i,defence_pokemon]=defeat_time
df_time.to_excel("check_demo.xlsx")
#いったん停止
time.sleep(2)
driver.quit()
chromedriverを使ってポケマピ様の
ダメージ計算ツールに対して
自動で検索&データ取得を行い
結果をexcelファイルに格納しています。
chromedriverを使った
スクレイピングについては、
こちらをご参照ください
DebankのPythonスクレイピングプログラムの環境構築!chromedriverまで解説!
今後について
ポケマピ様のダメージ計算ツールから効率的に
撃破時間テーブルを作成するプログラムを
紹介しました!
先ほども書いたように、
単なる効率化だけではなく、
データの幅が広がるのが魅力です。
例えば、
スペシャルアタック2に別タイプの技を設定し、
撃破時間が短くなる場合も
考えることができます。
これでデータ取得の効率化はできたので、
あとは最適化の計算量を減らす方法について
学びたいと思います!