0.25, 'prize2' => 0.06, 'prize3' => 0.1,] */ public array $items = []; /** * Рассчёт верхнего значения диапазона, подаваемого на рандомизатор через * множитель в зависимости от количества знаков после запятой у значения подаваемого на вход, умноженный на это значение. * Если на вход идёт целое число, система возвратит 0; * Если на вход идёт дробное число, система вернёт количество знаков; * Если на вход идёт вообще не число, система всё равно вернёт 0; * * @param $num * @return int множитель. */ private function randMax($num): int { if ((int)$num == $num || !is_numeric($num)) { return 0; } [, $a] = explode('.', strval($num)); return $num * pow(10, strlen($a)); } /** * Рассчёт выпадения определённого предмета. * Система считает сумму подаваемых на вход процентов, высчитывает количесто знаков после запятой, высчитывает * множитель, на который надо умножить полученное значение, чтобы получить целое число из дробного. * После этого на полученный множитель умножается каждое процентное значение и гененируются диапазоны значений для * каждого предмета. После этого берётся случайное число от 0 до максимального значения и сравнивается с * диапазонами. В какой диапазон попадает, тот предмет и выпал. * @return string|null имя выпавшего предмета. */ private function roll(): ?string { 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; if ($rand >= $rangeStart && $rand <= $rangeFinish) { break; } $rangeStart = $rangeFinish + 1; } return $itemKey; } /** * Функция, запускающая расчёт определённое количество раз и возвращающая массив выпавших предметов * либо NULL в случае ошибки. * * @param int $rolls сколько предметов надо получить на выходе. * * @return array|null */ 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; } }