From 71e133dab11712640219e0278ebb1e8fd7089b43 Mon Sep 17 00:00:00 2001 From: Ivor Barhansky Date: Tue, 20 Sep 2022 17:21:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ItemRoulette/ItemRoulette.php | 72 +++++++++++++---------------------- ItemRoulette/index.php | 8 ++-- README.md | 6 ++- 3 files changed, 36 insertions(+), 50 deletions(-) diff --git a/ItemRoulette/ItemRoulette.php b/ItemRoulette/ItemRoulette.php index 0b1347b..a539c83 100644 --- a/ItemRoulette/ItemRoulette.php +++ b/ItemRoulette/ItemRoulette.php @@ -3,7 +3,12 @@ declare(strict_types=1); class ItemRoulette { - private array $items; + /** + * @var array Массив шанса выпадения предметов. Ключом выступает имя предмета, значением выступает шанс выпадения. + * Шанс задаётся в виде десятичной дроби (25% = 0.25). + * ['prize1' => 0.25, 'prize2' => 0.06, 'prize3' => 0.1,] + */ + public array $items = []; /** * Рассчёт верхнего значения диапазона, подаваемого на рандомизатор через @@ -20,7 +25,7 @@ class ItemRoulette if ((int)$num == $num || !is_numeric($num)) { return 0; } - list(, $a) = explode('.', strval($num)); + [, $a] = explode('.', strval($num)); return $num * pow(10, strlen($a)); } @@ -31,19 +36,19 @@ class ItemRoulette * После этого на полученный множитель умножается каждое процентное значение и гененируются диапазоны значений для * каждого предмета. После этого берётся случайное число от 0 до максимального значения и сравнивается с * диапазонами. В какой диапазон попадает, тот предмет и выпал. - * - * @return string имя выпавшего предмета. + * @return string|null имя выпавшего предмета. */ - private function roll(): string + private function roll(): ?string { - $sumOfPercents = 0; - foreach ($this->items as $itemsPercent) { - $sumOfPercents += $itemsPercent; + if (!is_array($this->items || empty($this->items))) { + return null; } + $itemKey = ''; + $sumOfPercents = array_sum($this->items); $rand = mt_rand(1, $this->randMax($sumOfPercents)); $rangeStart = 1; foreach ($this->items as $itemKey => $itemsPercent) { - $rangeFinish = $rangeStart + ($itemsPercent * $multiplier); + $rangeFinish = $rangeStart + $itemsPercent; if ($rand >= $rangeStart && $rand <= $rangeFinish) { break; } @@ -53,50 +58,25 @@ class ItemRoulette } /** - * Функция, запускающая расчёт определённое количество раз и возвращающая массив выпавших предметов. + * Функция, запускающая расчёт определённое количество раз и возвращающая массив выпавших предметов + * либо NULL в случае ошибки. * - * @param $rolls - * @return array + * @param int $rolls сколько предметов надо получить на выходе. + * + * @return array|null */ - private function getMany($rolls): array + public function loot(int $rolls = 1): ?array { + if ($rolls < 1) { + return null; + } $result = []; for ($i = 0; $i < $rolls; $i++) { + if (is_null($this->roll())) { + continue; + } $result[] = $this->roll(); } return $result; } - - /** - * Функция, запускающая расчёт один раз и возвращающая один предмет. - * - * @return string - */ - private function getOne(): string - { - return $this->roll(); - } - - /** - * Передача массива шанса выпадения предметов в класс. - * - * @param array $items - * @return void - */ - public function setItems(array $items) - { - $this->items = $items; - } - - /** - * Функция, запускающая расчёт определённое количество раз и, в зависимости от количества запусков - * возвращающая либо массив выпавших предметов либо одно строчное значение. - * - * @param int $rolls сколько предметов надо получить на выходе. - * @return array|string - */ - public function loot(int $rolls = 1) - { - return $rolls > 1 ? $this->getMany($rolls) : $this->getOne(); - } } \ No newline at end of file diff --git a/ItemRoulette/index.php b/ItemRoulette/index.php index 82455e2..1fc12a7 100644 --- a/ItemRoulette/index.php +++ b/ItemRoulette/index.php @@ -1,12 +1,14 @@ 0.25, 'item-2' => 0.5, 'item-3' => 5, 'item-4' => 4.25333]; -$prize->setItems($items); +$prize->items = ['item-1' => 0.25, 'item-2' => 0.5, 'item-3' => 5, 'item-4' => 4.25333]; var_dump($prize->loot()); var_dump($prize->loot(5)); -/*string(6) "item-4" +/*array(1) { + [0]=> + string(6) "item-4" +} array(5) { [0]=> string(6) "item-3" diff --git a/README.md b/README.md index 692a774..8099b79 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Генерация списка случайного дропа по заданным параметрам. Функция на вход получает массив состоящий из служебных названий предметов и процент выпадения. + ```php [ 'item-1' => '0.25', // 25% @@ -10,7 +11,10 @@ 'item-3' => '0.5', // 50% ] ``` -На выходе функция вернёт или одно название выпавшего предмета `item-3`, или массив названий `['item-3', 'item-3', 'item-1']` в зависимости от того, с какими параметрами запущена функция. + +На выходе функция вернёт массив названий `['item-3', 'item-3', 'item-1']` в зависимости от выбора количества призовых +предметов. ## Требования + `PHP 7.4`. По запросу можно переписать под версии вплоть до `PHP 5.3`. \ No newline at end of file