1 | <?php |
||||
2 | /** |
||||
3 | * Created by Gorlum 17.02.2018 23:55 |
||||
4 | */ |
||||
5 | |||||
6 | namespace Common; |
||||
7 | |||||
8 | /** |
||||
9 | * Class OutcomeManager |
||||
10 | * |
||||
11 | * Manage outcomes for a bunch of random cases |
||||
12 | * |
||||
13 | * @package Common |
||||
14 | */ |
||||
15 | class OutcomeManager implements \Countable { |
||||
16 | |||||
17 | /** |
||||
18 | * Possible outcomes |
||||
19 | * |
||||
20 | * @var array $outcomes |
||||
21 | */ |
||||
22 | protected $outcomes = []; |
||||
23 | |||||
24 | /** |
||||
25 | * Chances for outcome to roll |
||||
26 | * |
||||
27 | * @var int[] $chances |
||||
28 | */ |
||||
29 | protected $chances = []; |
||||
30 | |||||
31 | |||||
32 | public function __construct() { |
||||
33 | } |
||||
34 | |||||
35 | /** |
||||
36 | * Roll element from predefined array |
||||
37 | * |
||||
38 | * @param iterable|array $iterable - [P_CHANCE => (int), ...(payload)] |
||||
39 | * |
||||
40 | * @return mixed|null |
||||
41 | */ |
||||
42 | public static function rollArray($iterable) { |
||||
43 | if (!is_iterable($iterable) || empty($iterable)) { |
||||
44 | return null; |
||||
45 | } |
||||
46 | |||||
47 | $manager = new static(); |
||||
48 | |||||
49 | foreach ($iterable as $element) { |
||||
50 | if (!is_array($element) || empty($element[P_CHANCE])) { |
||||
51 | continue; |
||||
52 | } |
||||
53 | $manager->add($element, $element[P_CHANCE]); |
||||
54 | } |
||||
55 | |||||
56 | $result = $manager->rollOutcome(); |
||||
57 | unset($manager); |
||||
58 | |||||
59 | return $result; |
||||
60 | } |
||||
61 | |||||
62 | /** |
||||
63 | * Adds outcome to internal array |
||||
64 | * |
||||
65 | * @param mixed $outcome - Outcome which can be selected |
||||
66 | * @param int $chance - Chance of this particular outcome. Should be integer. Sum of all chances can be above mt_getrandmax() |
||||
67 | */ |
||||
68 | public function add($outcome, $chance) { |
||||
69 | $this->outcomes[] = $outcome; |
||||
70 | $this->chances[] = $chance; |
||||
71 | } |
||||
72 | |||||
73 | /** |
||||
74 | * Removed outcome from list |
||||
75 | * |
||||
76 | * @param mixed $outcome - Outcome to be removed |
||||
77 | * @param bool|null $strict - Strict search flag |
||||
78 | */ |
||||
79 | public function remove($outcome, $strict = null) { |
||||
80 | if (($index = array_search($outcome, $this->outcomes, $strict)) !== false) { |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
81 | unset($this->outcomes[$index]); |
||||
82 | unset($this->chances[$index]); |
||||
83 | } |
||||
84 | } |
||||
85 | |||||
86 | |||||
87 | /** |
||||
88 | * Get max range of all current outcomes to use as maximum in mt_rand() |
||||
89 | * |
||||
90 | * @return float|int |
||||
91 | */ |
||||
92 | public function getMaxRange() { |
||||
93 | return array_sum($this->chances); |
||||
94 | } |
||||
95 | |||||
96 | /** |
||||
97 | * Get outcome by rolled chance |
||||
98 | * |
||||
99 | * @param int $rolled - Rolled chance |
||||
100 | * |
||||
101 | * @return mixed|null - (null) if no outcomes |
||||
102 | */ |
||||
103 | public function getOutcome($rolled) { |
||||
104 | foreach ($this->chances as $index => $chance) { |
||||
105 | if ($rolled <= $chance) { |
||||
106 | break; |
||||
107 | } |
||||
108 | $rolled -= $chance; |
||||
109 | } |
||||
110 | |||||
111 | return array_key_exists($index, $this->outcomes) ? $this->outcomes[$index] : null; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
112 | } |
||||
113 | |||||
114 | /** |
||||
115 | * All-in-one function |
||||
116 | * |
||||
117 | * Code can use this function if it don't want to know what number was rolled |
||||
118 | * |
||||
119 | * @return mixed|null |
||||
120 | */ |
||||
121 | public function rollOutcome() { |
||||
122 | return $this->getOutcome(mt_rand(1, $this->getMaxRange())); |
||||
0 ignored issues
–
show
It seems like
$this->getMaxRange() can also be of type double ; however, parameter $max of mt_rand() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
123 | } |
||||
124 | |||||
125 | /** |
||||
126 | * Count elements of an object |
||||
127 | * @link http://php.net/manual/en/countable.count.php |
||||
128 | * @return int The custom count as an integer. |
||||
129 | * </p> |
||||
130 | * <p> |
||||
131 | * The return value is cast to an integer. |
||||
132 | * @since 5.1.0 |
||||
133 | */ |
||||
134 | public function count() { |
||||
135 | return count($this->outcomes); |
||||
136 | } |
||||
137 | |||||
138 | } |
||||
139 |