ポケモンの種族値を秒速で確認するCLIツールを作ってみる
ポケモンの種族値なんて全部暗記できない!
よほどのポケモンガチ勢でもない限り、約600種類のポケモンの種族値を丸暗記することはかなり難しいでしょう。
「せめてメジャーなポケモンの素早さだけでも」と思っても、ポケモン対戦では一手のミスが命取りです。もし覚え間違えてたら?それが敗因となることもあるでしょう。
もちろん既存のアプリケーションもあるでしょうが、対戦時間は非常にシビアなので速さも重要になってきます。
そこで、ファジーファインダー的にポケモンの名前を入力して種族値をサッと確認できるツールを作ってみました(実際には昔作って忘れてたのを、記事を書く練習がてらネタにしています)。
sqlite3で種族値テーブルを作ろう
種族値テーブルをテキストで作ってpecoで絞り込むみたいな方法でも簡易に作れますが、折角なので「HCDの合計が一番高いポケモンは?」なども疑問にもサッと答えられるように、データベースを作っておくと、後で別のツールを作る夢も広がります。
テーブルはこんな感じにしてみました。ポケモン名のローマ字で検索できるように、ローマ字名をprimary keyに、種族値合計も利用頻度が高くSQLを書くのがめんどくさいので、あらかじめ計算して入れておくと便利です。hとかaとかの意味は分かりますよね?
create table status_list(
jpromaji VARCHAR(255) primary key,
jpname VARCHAR(255) not null,
no integer not null,
h integer not null,
a integer not null,
b integer not null,
c integer not null,
d integer not null,
s integer not null,
sum integer not null
);
データソースは伝統のポケ徹(yakkun.com)を使います。
https://yakkun.com/swsh/stats_list.htm をスクレイピングして、SQLに変換する pokemon.rb
を書いてみます。
スクレイピングにはnokogiriを使ってみました。またローマ字を扱うのでromajiも便利でした。
こうやって curl https://yakkun.com/swsh/stats_list.htm | ruby pokemon.rb | sqlite3 pokemon
としていつでも作り直せるようにしておくと、あとあと便利です。(アプデでポケモンが増えたりするので……。)
#! /usr/bin/env ruby
# curl https://yakkun.com/swsh/stats_list.htm | ruby pokemon.rb | sqlite3 pokemon
require 'nokogiri'
require 'romaji'
Encoding.default_external='euc-jp'
html = $stdin.read
doc = Nokogiri::HTML(html)
doc.css('.stupidtable > tbody > tr > td').each_slice(9) do |line|
no, jpname, h, a, b, c, d, s, sum = line.map { |td| td.children.first.text }
jpromaji = Romaji.kana2romaji(jpname)
values = [
no.to_i,
"\"#{jpname}\"",
"\"#{jpromaji}\"",
h.to_i,
a.to_i,
b.to_i,
c.to_i,
d.to_i,
s.to_i,
sum.to_i,
]
puts "insert into status_list (no, jpname, jpromaji, h, a, b, c, d, s, sum) values (#{values.join(',')}) on conflict(jpromaji) do nothing;"
end
CLIツールを作ろう
データベースだけでも結構便利ですが、元々の目的だったCLIツールを作ってみましょう。
キーボード一打ごとに動作してほしいのでio/console
を使います。
また、sqlite3のコマンドを叩くのでopen3
も使っています。sqlite3に対してLIKE検索するだけです。
ANSIエスケープシーケンスは覚えるのが面倒なのでclassを作ってます。
ちなみにANSIエスケープシーケンスについては、こちらの記事がわかりやすくてありがたかったです。
スクリプトはいくらでも凝れそうですが、表示の仕方を変えれるオプションを付けるぐらいにとどめています。
#! /usr/bin/env ruby
require 'io/console'
require 'open3'
sqlite_argument = ARGV[0] || '-list'
class Cursor
def move_top
print "\e[0H"
end
def line_on(i)
print "\e[#{i}G"
end
def clear_line
line_on(0)
print "\e[2K"
end
def clear_after
print "\e[0J"
end
def clear_all
print "\e[2J"
end
end
cursor = Cursor.new
columns = "jpname,jpromaji,h,a,b,c,d,s"
query_template = "select #{columns} from status_list where jpromaji LIKE \"%%%s%%\" limit 10"
cursor.clear_all
buff = []
$stdin.raw do |stdin|
while true
cursor.move_top
cursor.clear_line
print "> #{buff.join}"
case c = stdin.getc
when "\r", "\n"
buff.clear
cursor.clear_after
next
when "\u007F"
# backspace
buff.pop
when "\u0003", "\u0004"
# CTRL+C or CTRL+D
exit 0
else
buff << c
end
puts
query = sprintf(query_template, buff.join)
## debug
# cursor.clear_line
# puts query
cursor.clear_line
puts columns
out, _status = Open3.capture2e("sqlite3 #{sqlite_argument} pokemon", stdin_data: query)
out.each_line do |line|
cursor.clear_line
puts line
end
cursor.clear_after
end
end
いいわけ
いい感じのgifアニメを貼れればよかったけど、ttygifなどではいい感じの操作イメージが作れなかった……。
Discussion