ItemRoulette/ItemRoulette/ItemRoulette.php

102 lines
4.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
class ItemRoulette
{
private array $items;
/**
* Рассчёт верхнего значения диапазона, подаваемого на рандомизатор через
* множитель в зависимости от количества знаков после запятой у значения подаваемого на вход, умноженный на это значение.
* Если на вход идёт целое число, система возвратит 0;
* Если на вход идёт дробное число, система вернёт количество знаков;
* Если на вход идёт вообще не число, система всё равно вернёт 0;
*
* @param $num
* @return int множитель.
*/
private function randMax($num): int
{
if ((int)$num == $num || !is_numeric($num)) {
return 0;
}
list(, $a) = explode('.', strval($num));
return $num * pow(10, strlen($a));
}
/**
* Рассчёт выпадения определённого предмета.
* Система считает сумму подаваемых на вход процентов, высчитывает количесто знаков после запятой, высчитывает
* множитель, на который надо умножить полученное значение, чтобы получить целое число из дробного.
* После этого на полученный множитель умножается каждое процентное значение и гененируются диапазоны значений для
* каждого предмета. После этого берётся случайное число от 0 до максимального значения и сравнивается с
* диапазонами. В какой диапазон попадает, тот предмет и выпал.
*
* @return string имя выпавшего предмета.
*/
private function roll(): string
{
$sumOfPercents = 0;
foreach ($this->items as $itemsPercent) {
$sumOfPercents += $itemsPercent;
}
$rand = mt_rand(1, $this->randMax($sumOfPercents));
$rangeStart = 1;
foreach ($this->items as $itemKey => $itemsPercent) {
$rangeFinish = $rangeStart + ($itemsPercent * $multiplier);
if ($rand >= $rangeStart && $rand <= $rangeFinish) {
break;
}
$rangeStart = $rangeFinish + 1;
}
return $itemKey;
}
/**
* Функция, запускающая расчёт определённое количество раз и возвращающая массив выпавших предметов.
*
* @param $rolls
* @return array
*/
private function getMany($rolls): array
{
$result = [];
for ($i = 0; $i < $rolls; $i++) {
$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();
}
}