くじ引きやガチャガチャのように、あるものはよく出る、あるものはあまり出ない、というように確率に差がある上で一つ抽出する、というプログラムをたまに書くことがあるので、その部分だけを行うPHPライブラリを作った。
インストール
Composerを使う場合は、composer.jsonのrequireに
"cloned/luckybox": "$VERSION"
を追加。$VERSIONに入れられるバージョンはPackagistを参照。今のところは 0.9.* としておくと良いでしょう。
Composer推奨だけど、Composerを使わない場合はGitHubからソースコードをダウンロードしてrequire_onceしてもOK。
使い方
コインは60%、キノコは35%、スターは5%、という設定で1回くじを引いてみる例はこんな感じ。
<?php use LuckyBox\LuckyBox; use LuckyBox\Card\IdCard; // Items $items = array( 1 => array('name' => 'Coin', 'rate' => 60), // 60% 2 => array('name' => 'Mushroom', 'rate' => 35), // 35% 3 => array('name' => 'Star', 'rate' => 5), // 5% ); // Setup $luckyBox = new LuckyBox(); foreach ($items as $id => $item) { $card = new IdCard(); $card->setId($id) ->setRate($item['rate']); $luckyBox->add($card); } // Draw $card = $luckyBox->draw(); $item = $items[$card->getId()]; echo "You got {$item['name']}" . PHP_EOL;
LuckyBoxに確率(rate)を設定したCardを詰めて、LuckyBox#draw()するとその確率に応じた割合で一つ取得できる。
バンドルされているIdCardクラスは、rate以外にidのみ保持できるクラスで、より複雑なCardを作りたい場合は、Cardインタフェースを実装したものであれば自作しても利用可能。
デフォルトでは無限に LuckyBox#draw() できるけれど、LuckyBox#setConsumable(true) するとadd()したCardの分しか引けなくなる。こんな感じで利用できる。
<?php $luckyBox = new LuckyBox(); // Add some cards. $luckyBox->setConsumable(true); while (!$luckyBox->isEmpty()) { $card = $luckyBox->draw(); // Do something. }
0.5% みたいなより精度の高い確率を設定したい場合は、より大きな数をrateに設定すると可能。
<?php $card1 = new IdCard(); $card2 = new IdCard(); $card1->setRate(1023); // 10.23% $card2->setRate(8977); // 89.77%
ここでは説明しやすいように合計を100とか10000にしているけれど、実際には全てのrateの合計に対する比率になっているので、「1:1:3」みたいな指定も可能。「1:1:3」とすると「20%:20%:60%」という確率になる。
同じような要件があって、まだコーディングしていなければ、是非使ってみてください。