移転しました。

ガチャみたいに設定した確率で抽選を行うPHPライブラリを作った

くじ引きやガチャガチャのように、あるものはよく出る、あるものはあまり出ない、というように確率に差がある上で一つ抽出する、というプログラムをたまに書くことがあるので、その部分だけを行う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%」という確率になる。

同じような要件があって、まだコーディングしていなければ、是非使ってみてください。