Issues (1369)

classes/Common/OutcomeManager.php (3 issues)

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
It seems like $strict can also be of type null; however, parameter $strict of array_search() does only seem to accept boolean, 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 ignore-type  annotation

80
    if (($index = array_search($outcome, $this->outcomes, /** @scrutinizer ignore-type */ $strict)) !== false) {
Loading history...
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
The variable $index seems to be defined by a foreach iteration on line 104. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
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 ignore-type  annotation

122
    return $this->getOutcome(mt_rand(1, /** @scrutinizer ignore-type */ $this->getMaxRange()));
Loading history...
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