Posted at
sue445Day 1

プリキュアのRuby実装「rubicure」

More than 1 year has passed since last update.


rubicureとは?

プリキュアのRuby実装です :heart:

maho_girls.gif

「sue445 = Rubyでプリキュアの人」と良くも悪くも印象づけた代表作です。


機能紹介


プリキュアの番組タイトルを出力

Precure に続けてタイトルを入力すると番組が取得できます。直感的!

> Precure.maho_girls.title

#=> "魔法つかいプリキュア!"

suffixに _precure がついていても反応します

> Precure.maho_girls_precure.title

#=> "魔法つかいプリキュア!"

#started_date で放送開始年月がとれます

> Precure.maho_girls.started_date

#=> Sun, 07 Feb 2016


番組に登場するプリキュアを取得

その番組に登場するプリキュアを取得したい場合には #girls でその番組に登場するプリキュアが取得できます 1

> Precure.maho_girls.girls.count

#=> 3

> Precure.maho_girls.girls.map(&:precure_name)
#=> ["キュアミラクル", "キュアマジカル", "キュアフェリーチェ"]


全てのプリキュアを取得

映画でおなじみの Precure.all_stars で取得できます

> Precure.all_stars.count

#=> 44

> Precure.all_stars.map(&:precure_name)
#=> ["キュアブラック", "キュアホワイト", "シャイニールミナス", "キュアブルーム", "キュアイーグレット", "キュアドリーム", "キュアルージュ", "キュアレモネード", "キュアミント", "キュアアクア", "ミルキィローズ", "キュアピーチ", "キュアベリー", "キュアパイン", "キュアパッション", "キュアブロッサム", "キュアマリン", "キュアサンシャイン", "キュアムーンライト", "キュアメロディ", "キュアリズム", "キュアビート", "キュアミューズ", "キュアハッピー", "キュアサニー", "キュアピース", "キュアマーチ", "キュアビューティ", "キュアハート", "キュアダイヤモンド", "キュアロゼッタ", "キュアソード", "キュアエース", "キュアラブリー", "キュアプリンセス", "キュアハニー", "キュアフォーチュン", "キュアフローラ", "キュアマーメイド", "キュアトゥインクル", "キュアスカーレット", "キュアミラクル", "キュアマジカル", "キュアフェリーチェ"]

#all_stars に日付を渡すとその時点での人数が取得できます

> Precure.all_stars(Date.parse("2016-01-01")).count

=> 41

#all_stars に映画を表すものを渡すとその時点での人数が取得できます。便利!

> Precure.all_stars(:dx).count

#=> 14

> Precure.all_stars(:dx2).count
#=> 17

Precure.all_stars(:dx3).count
#=> 21

> Precure.all_stars(:new_stage).count
#=> 29

> Precure.all_stars(:new_stage2).count
#=> 32

> Precure.all_stars(:new_stage3).count
#=> 37

> Precure.all_stars(:spring_carnival).count
#=> 40

> Precure.all_stars(:sing_together_miracle_magic).count
#=> 44

2

実際に使えるのは https://github.com/sue445/rubicure/blob/v0.4.9/config/movies.yml を見てください

特例として、キュアエコーは映画限定のプリキュアなので Precure.all_stars に対応した映画 3 を渡した時のみ取得できます。

> Precure.all_stars(:new_stage).include?(Cure.echo)

#=> true


個別にプリキュアを取得

Cure の後にプリキュアの名前を入力すると対応したプリキュアが取得できます

> Cure.miracle.precure_name

#=> "キュアミラクル"

> Cure.magical.precure_name
#=> "キュアマジカル"

> Cure.felice.precure_name
#=> "キュアフェリーチェ"

「キュア」で始まらないプリキュア(シャイニールミナスとミルキィローズ)は下記で取得できます

> Shiny.luminous.precure_name

#=> "シャイニールミナス"

> Milky.rose.precure_name
#=> "ミルキィローズ"


人間の時の名前を取得

> Cure.miracle.human_name

#=> "朝日奈みらい"


プリキュアに変身した後の名前を取得

> Cure.miracle.precure_name

#=> "キュアミラクル"


キャストの名前を取得

> Cure.miracle.cast_name

#=> "高橋李依"


プリキュアの色を取得

> Cure.miracle.color

#=> "pink"

存在するプリキュアの色を全部取得したい時には Rubicure::Girl.colors が使えます

> Rubicure::Girl.colors

#=> [:black, :blue, :green, :pink, :purple, :red, :white, :yellow]

特定の色のみ調べるワンライナー

> Precure.all_stars.select(&:pink?).map(&:precure_name)

#=> ["キュアブルーム", "キュアドリーム", "キュアピーチ", "キュアブロッサム", "キュアメロディ", "キュアハッピー", "キュアハート", "キュアラブリー", "キュアフローラ", "キュアミラクル"]

色ごとの人数を集計して多い順に取得するワンライナー

> Precure.all_stars.group_by{ |girl| girl.color }.map{ |color, girls| [color, girls.count] }.sort_by{ |color, girl_count| girl_count }.reverse

#=> [["pink", 10], ["yellow", 9], ["blue", 9], ["red", 5], ["purple", 4], ["white", 3], ["green", 3], ["black", 1]]


初登場した日付を取得

> Cure.miracle.created_date

#=> Sun, 07 Feb 2016

created_date は厳密には正式加入した日付です。これは Precure.all_stars で特定の日付や映画の時点でプリキュアオールスターズとして存在するかチェックするのに created_date を使っているためです。(ハピネスチャージプリキュア!で序盤から登場しているキュアフォーチュンの created_date が2014/6/29(22話)なのになっているのはそのため)


誕生日を取得

> Cure.miracle.birthday

#=> "6/12"

設定によっては誕生日が存在しないキャラもいますが、#has_birthday?#have_birthday? でチェックできます。

> Cure.miracle.has_birthday?

#=> true

> Cure.felice.has_birthday?
#=> false

#birthday? に日付を渡すと誕生日かどうか取得できます

# 引数省略時は Date.today

> Cure.miracle.birthday?
#=> false

> Cure.miracle.birthday?(Date.parse("2016-06-12"))
#=> true

現時点で誕生日の存在しているキャラを取得

> Precure.all_stars.select(&:have_birthday?).map(&:human_name)

#=> ["美墨なぎさ", "雪城ほのか", "九条ひかり", "日向咲", "美翔舞", "相田マナ", "菱川六花", "四葉ありす", "剣崎真琴", "春野はるか", "海藤みなみ", "天ノ川きらら", "紅城トワ", "朝日奈みらい", "十六夜リコ"]

> Precure.all_stars.select(&:have_birthday?).map(&:human_name).count
#=> 15

ちなみにrubicureで採用している誕生日はあくまでも 公式 設定のみです。

「映画Yes!プリキュア5GoGo! お菓子の国のハッピーバースディ♪」(映画公開日11/8)で夢原のぞみの誕生日を祝うシーンがあるので11/8が夢原のぞみの誕生日という説もありますが、公式設定というには微妙なのでrubicureでは採用していません。(rubicureでは採用しないってだけなので他の人が11/8にのぞみの誕生日を祝うことは否定していません。)


変身

プリキュアといえば変身!

rubicureでは変身を忠実に再現しています

初期状態では #name は人間の時の名前が返ります。

> yayoi = Cure.peace

> yayoi.name
#=> "黄瀬やよい"

#transform! で名乗りとともに変身します。

> yayoi.transform!

(レディ?)
プリキュア・スマイルチャージ!
(ゴー!ゴー!レッツ・ゴー!ピース!!)
ピカピカピカリンジャンケンポン! キュアピース!
5つの光が導く未来!
輝け!スマイルプリキュア!

変身は自分が変化する破壊的なメソッドなのでRubyの慣習に則ってメソッド名に ! がついています。

変身後はプリキュアの名前が返ります。

> yayoi.name

#=> "キュアピース"

変身後は #attack! で必殺技をうてます。

> yayoi.attack!

プリキュア!ピースサンダー!!

必殺技は敵を破壊する破壊的なメソッドなのでこれもRubyの慣習に則ってメソッド名に ! がついています。

2段階目以降の変身形態があれば順次変身します。(必殺技もそれに応じて変わります。)

> yayoi.transform!

> yayoi.name
#=> "プリンセスピース"

> yayoi.attack!

開け、ロイヤルクロック!
(みんなの力を1つにするクル!)
届け、希望の光!
はばたけ!光り輝く未来へ!
プリキュア!ロイヤルレインボーバースト!

> yayoi.transform!
> yayoi.name
#=> "ウルトラピース"

> yayoi.attack!

(みんなの力を1つにするクル!)
プリキュア!ミラクルレインボーバースト!
輝けー!!
スマイルプリキュア!!

humanize! で元の人間形態に戻ります。

> yayoi.humanize!

> yayoi.name
#=> "黄瀬やよい"

#transform! はシリーズ共通で使えるメソッドですが、シリーズ固有の変身の名乗りも全部対応しています

> Cure.black.dual_aurora_wave!

> Cure.luminous.luminous_shining_stream!
> Cure.bloom.dual_spilitual_power!
> Cure.dream.metamorphose!
> Milky.rose.sky_rose_translate!
> Cure.peach.change_precure_beatup!
> Cure.blossom.open_my_heart!
> Cure.melody.lets_play_precure_modulation!
> Cure.happy.smile_charge!
> Cure.heart.love_link!
> Cure.ace.dressup!
> Cure.lovely.kururin_mirror_change!
> Cure.fortune.kirarin_star_symphony!
> Cure.flora.princess_engage!


魔法つかいプリキュア!の変身

魔法つかいプリキュア!はリンクルストーンによって変身先が変わります。

ダイヤスタイルに変身

> mirai = Cure.miracle

> mirai.name
# => "朝日奈みらい"

> mirai.cure_up_rapapa! :diamond
キュアップ・ラパパ! ダイヤ!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

> mirai.name
#=> "キュアミラクル(ダイヤスタイル)"

> mirai.attack!
リンクルステッキ!
ダイヤ!永遠の輝きを私達の手に!
フルフルリンクル!
プリキュア!ダイヤモンドエターナル!

ルビースタイルに変身

> mirai.cure_up_rapapa! :ruby

キュアップ・ラパパ! ルビー!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

> mirai.attack!
リンクルステッキ!
ルビー!紅の情熱よ私達の手に!
フルフルリンクル!
プリキュア・ルビー・パッショナーレ!

サファイアスタイルに変身

> mirai.cure_up_rapapa! :sapphire

キュアップ・ラパパ! サファイア!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

> mirai.attack!
リンクルステッキ!
サファイア!青き知性よ私達の手に!
フルフルリンクル!
プリキュア・サファイア・スマーティッシュ!

トパーズスタイルに変身

> mirai.cure_up_rapapa! :topaz

キュアップ・ラパパ! トパーズ!
ミラクル・マジカル・ジュエリーレ!
ふたりの奇跡!キュアミラクル!
魔法つかいプリキュア!!

> mirai.attack!
リンクルステッキ!
トパーズ!金色の希望よ私達の手に!
フルフルリンクル!
プリキュア・トパーズ・エスペランサ!

はーちゃんこと花海ことははエメラルドで変身します。

> ha_chan = Cure.felice

> ha_chan = Cure.felice.name
#=> "花海ことは"

> ha_chan.cure_up_rapapa! :emerald
キュアップ・ラパパ!エメラルド!
フェリーチェ・ファンファン・フラワーレ!
あまねく生命に祝福を!キュアフェリーチェ!

> ha_chan.name
#=> "キュアフェリーチェ"

> ha_chan.attack!
フラワーエコーワンド!
エメラルド!
キュアー・アップ!
プリキュア!エメラルド・リンカネーション!


現在放映中のプリキュアの番組を取得

Precure.nowPrecure.current で取得できます

> Precure.now.title

#=> "魔法つかいプリキュア!"

> Precure.current.title
#=> "魔法つかいプリキュア!"


プリキュアの番組が放映中かどうか取得する

#on_air? を使うと、引数に渡した日付で放映されているかチェックできます

> Date.today

#=> Thu, 1 Dec 2016

> Precure.maho_girls.on_air?(Date.today)
#=> true

> Precure.go_princess.on_air?(Date.today)
#=> false

DateTime 以外にも日付っぽい文字列を渡してもいけます

> Precure.maho_girls.on_air?("2015-12-01")

#=> false

> Precure.go_princess.on_air?("2015-12-01")
#=> true


ピカリンジャンケン

キュアピースはピカリンジャンケンができます。

> Cure.peace.pikarin_janken

ピカピカピカリン
ジャンケンポン!
(パー)


eachを独自定時

Precure (実体は Rubicure::Core)はシリーズ順に取得できるように each を実装しています。

> Precure.each{ |series| puts series.title }

ふたりはプリキュア
ふたりはプリキュア Max Heart
ふたりはプリキュア SplashStar
Yes プリキュア5
Yes プリキュア5 Go Go
フレッシュプリキュア!
ハートキャッチプリキュア!
スイートプリキュア♪
スマイルプリキュア!
ドキドキ!プリキュア
ハピネスチャージプリキュア!
Go!プリンセスプリキュア
魔法つかいプリキュア!

Enumerable4include しているため map などのメソッドにも反応します。

> Precure.map(&:title)

#=> ["ふたりはプリキュア", "ふたりはプリキュア Max Heart", "ふたりはプリキュア Splash☆Star", "Yes! プリキュア5", "Yes! プリキュア5 Go Go!", "フレッシュプリキュア!", "ハートキャッチプリキュア!", "スイートプリキュア♪", "スマイルプリキュア!", "ドキドキ!プリキュア", "ハピネスチャージプリキュア!", "Go!プリンセスプリキュア", "魔法つかいプリキュア!"]


! 演算子

特定のキャラは否定の ! 演算子を実装しているので、使う度に正義と悪が入れ替わります

> passion = Cure.passion

> passion.name
#=> "東せつな"

> !passion

> passion.name
#=> "イース"

> beat = Cure.beat

> beat.name
#=> "黒川エレン"

> !beat

> beat.name
#=> "セイレーン"

> scarlet = Cure.scarlet

> scarlet.name
#=> "紅城トワ"

> !scarlet

> scarlet.name
#=> "トワイライト"

ちなみにこの機能はRubyKaigi 2014で ! 演算子をオーバーライドできるというのを聞いて思いつきました。

image

image


ワンライナー用の ubicure

ruby コマンドや irb コマンドで特定のgemを require した状態で起動する時は -r<gem名> のようになります。

rubicureの場合 ruby -rrubicure ですが、長いので代わりに ubicurerequire できます。

$ ruby -rubicure -e'puts Shiny.luminous.transform_message'


改善点


did_you_mean対応

全ての機能を method_missing で作りきってしまったため、typoしてもdid_you_meanで教えてくれないのが難点。

フルスタックキュアエンジニアなら全プリキュアの名前くらい知っているものなので不要だとは思うのですが、typoした時にdid_you_meanで教えてくれるのに慣れきってしまったので入れたい欲はあります。


その他関連プロダクト


rubicure API

Rubyがインストールされていない環境でもrubicureが使えるようにAPIサーバも提供しています。

$ curl -s https://rubicure.herokuapp.com/series/go_princess.json | jq .

{
"series_name": "go_princess",
"title": "Go!プリンセスプリキュア",
"started_date": "2015-02-01",
"girls": [
"cure_flora",
"cure_mermaid",
"cure_twinkle",
"cure_scarlet"
]
}

$ curl -s https://rubicure.herokuapp.com/girls/cure_twinkle.json | jq .
{
"girl_name": "cure_twinkle",
"human_name": "天ノ川きらら",
"precure_name": "キュアトゥインクル",
"cast_name": "山村響",
"color": "yellow",
"created_date": "2015-02-22",
"transform_message": "プリキュア!プリンセスエンゲージ!\nきらめく星のプリンセス!キュアトゥインクル!\n強く、やさしく、美しく!\nGo!プリンセスプリキュア!\n冷たい檻に閉ざされた夢、返していただきますわ!\nお覚悟はよろしくて?",
"extra_names": null,
"attack_messages": [
"エクスチェンジ!モードエレガント!\nキラキラ、星よ!プリキュア・トゥインクル・ハミング!\n(ドリーミング)\nごきげんよう\n"
],
"transform_calls": [
"princess_engage"
]
}

Tachikoma.io を使ってrubicureがアップデートされたら bundle update するPRを送るようにしているので雑に最新版に保ち続けています。


faker-precure

テストデータでプリキュアを使うためのライブラリです

https://github.com/sue445/faker-precure

使い方

require "faker/precure"

> Faker::Precure.human_name
#=> "黄瀬やよい"

> Faker::Precure.precure_name
#=> "キュアアクア"

> Faker::Precure.cast_name
#=> "豊口めぐみ"

> Faker::Precure.title
#=> "Yes! プリキュア5"

> Faker::Precure.transform_message
#=> "レッツプレイ!プリキュアモジュレーション!!\n爪弾くは女神の調べ! キュアミューズ!\n届け4人の組曲!スイートプリキュア!"

> Faker::Precure.user_name
#=> "cure_mint"

factory_girl を使っている場合こういうfactoryを作ればいい感じにランダムなテストデータを作れます。

FactoryGirl.define do

factory :user do
name { Faker::Precure.human_name }
end
end

一応注意点としてはプリキュアは44人しかいない 5ので、一意制約をつけているカラムに対して使わないでください。 44分の1の確率でテストが落ちます


cure-bots

https://github.com/sue445/cure-bots

プリキュアの誕生日の0:00にツイートするだけのボットです。

image

https://twitter.com/sue445/status/797091587029405698


他言語での実装について

プリキュアの各言語での実装まとめ - Qiita 参照


最後に

駆け足になりましたがrubicureとその周辺ツールの紹介をさせてもらいました。

レッツプリキュア!





  1. TODO: キュアモフルン取得 



  2. みんなで歌う奇跡の魔法の英名は「STMM製作委員会」から推測したものなので本当にsing together miracle magicかどうかは自信がないです 



  3. :new_stage, :new_stage3, :sing_together_miracle_magic 



  4. https://docs.ruby-lang.org/ja/latest/class/Enumerable.html 



  5. 2016年12月時点