Completed
Push — master ( e72458...99f4f0 )
by Karthik
15:24
created

ItemOption   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 71
c 1
b 0
f 0
dl 0
loc 202
rs 10
wmc 26

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getSlots() 0 3 1
B generate() 0 39 9
A getCrafts() 0 3 1
A getCraftOptions() 0 3 1
A setCraftOption() 0 16 4
A __construct() 0 19 6
A getSlotOptions() 0 3 1
A setSlotOption() 0 10 3
1
<?php
2
3
namespace cyberinferno\Cabal\Helpers;
4
5
use cyberinferno\Cabal\Helpers\Exceptions\InvalidCraftLevelException;
6
use cyberinferno\Cabal\Helpers\Exceptions\InvalidOptionException;
7
use cyberinferno\Cabal\Helpers\Exceptions\MaxOptionException;
8
use cyberinferno\Cabal\Helpers\Exceptions\OptionLimitException;
9
10
/**
11
 * Class ItemOption
12
 *
13
 * Contains methods helpful to generate item option
14
 *
15
 * @package cyberinferno\Cabal\Helpers
16
 * @author Karthik P
17
 */
18
class ItemOption
19
{
20
    const MAX_OPTIONS = 4;
21
22
    const MIN_SLOTS = 1;
23
    const MAX_SLOTS = 4;
24
25
    const MIN_CRAFTS = 0;
26
    const MAX_CRAFTS = 3;
27
28
    const OUTPUT_FORMAT_INTEGER = 'int';
29
    const OUTPUT_FORMAT_HEXADECIMAL = 'hex';
30
31
    /**
32
     * @var int Max number of slots the generated item option will have
33
     */
34
    protected $_slots;
35
    /**
36
     * @var array
37
     */
38
    protected $_slotOptions = [];
39
    /**
40
     * @var int Max number of crafts the generated item option will have
41
     */
42
    protected $_crafts;
43
    /**
44
     * @var array
45
     */
46
    protected $_craftOptions = [];
47
    /**
48
     * @var array
49
     */
50
    protected $_availableCraftLevels = ['9', 'A', 'B', 'C', 'D', 'E', 'F'];
51
    /**
52
     * @var array
53
     */
54
    protected $_availableOptions = [
55
        '1', '2', '3', '4', '5',
56
        '6', '7', '8', '9', 'A',
57
        'B', 'C', 'D', 'E', 'F'
58
    ];
59
60
    /**
61
     * ItemOption constructor.
62
     * @param int $slots
63
     * @param int $crafts
64
     * @throws \Exception
65
     */
66
    public function __construct($slots, $crafts = 0)
67
    {
68
        if ($slots < self::MIN_SLOTS) {
69
            $slots = self::MIN_SLOTS;
70
        }
71
        if ($slots > self::MAX_SLOTS) {
72
            $slots = self::MAX_SLOTS;
73
        }
74
        if ($crafts < self::MIN_CRAFTS) {
75
            $crafts = self::MIN_CRAFTS;
76
        }
77
        if ($crafts > self::MAX_CRAFTS) {
78
            $crafts = self::MAX_CRAFTS;
79
        }
80
        if ($slots + $crafts > self::MAX_OPTIONS) {
81
            throw new MaxOptionException('Maximum number of options cannot exceed ' . self::MAX_OPTIONS);
82
        }
83
        $this->_slots = $slots;
84
        $this->_crafts = $crafts;
85
    }
86
87
    /**
88
     * Returns the number of slots in the option
89
     *
90
     * @return int
91
     */
92
    public function getSlots()
93
    {
94
        return $this->_slots;
95
    }
96
97
    /**
98
     * Returns the number of crafts in the option
99
     *
100
     * @return int
101
     */
102
    public function getCrafts()
103
    {
104
        return $this->_crafts;
105
    }
106
107
    /**
108
     * Returns slot options
109
     *
110
     * @return array
111
     */
112
    public function getSlotOptions()
113
    {
114
        return $this->_slotOptions;
115
    }
116
117
    /**
118
     * Sets a slot option
119
     *
120
     * @param string $option
121
     * @return ItemOption
122
     * @throws InvalidOptionException
123
     * @throws OptionLimitException
124
     */
125
    public function setSlotOption($option)
126
    {
127
        if (!in_array(strval($option), $this->_availableOptions)) {
128
            throw new InvalidOptionException();
129
        }
130
        if (count($this->_slotOptions) == $this->_slots) {
131
            throw new OptionLimitException('Slot option cannot exceed ' . $this->_slots);
132
        }
133
        $this->_slotOptions[] = ['option' => (string)$option];
134
        return $this;
135
    }
136
137
    /**
138
     * Returns craft options
139
     *
140
     * @return array
141
     */
142
    public function getCraftOptions()
143
    {
144
        return $this->_craftOptions;
145
    }
146
147
    /**
148
     * Sets a craft option
149
     *
150
     * @param string $craftLevel
151
     * @param string $option
152
     * @return ItemOption
153
     * @throws InvalidCraftLevelException
154
     * @throws InvalidOptionException
155
     * @throws OptionLimitException
156
     */
157
    public function setCraftOption($craftLevel, $option)
158
    {
159
        if (!in_array(strval($craftLevel), $this->_availableCraftLevels)) {
160
            throw new InvalidCraftLevelException();
161
        }
162
        if (!in_array(strval($option), $this->_availableOptions)) {
163
            throw new InvalidOptionException();
164
        }
165
        if (count($this->_craftOptions) == $this->_crafts) {
166
            throw new OptionLimitException('Craft option cannot exceed ' . $this->_crafts);
167
        }
168
        $this->_craftOptions[] = [
169
            'craftLevel' => (string)$craftLevel,
170
            'option' => (string)$option
171
        ];
172
        return $this;
173
    }
174
175
    /**
176
     * Returns the generated item option based upon the criteria set
177
     *
178
     * @param string $format
179
     * @return string|int
180
     */
181
    public function generate($format = self::OUTPUT_FORMAT_INTEGER)
182
    {
183
        $optionString = '';
184
        $slotsToFillArray = [];
185
        // Craft options should be at the end of the hex string hence we start prepending all craft options to output
186
        foreach ($this->_craftOptions as $craftOption) {
187
            $optionString = $craftOption['craftLevel'] . $craftOption['option'] . $optionString;
188
        }
189
        // We calculate slots to fill based upon slot options
190
        foreach ($this->_slotOptions as $slotOption) {
191
            if (isset($slotsToFillArray[$slotOption['option']])) {
192
                $slotsToFillArray[$slotOption['option']]++;
193
            } else {
194
                $slotsToFillArray[$slotOption['option']] = 1;
195
            }
196
        }
197
        // Sorting slots to fill array to make sure multiple slot options stay in the end
198
        arsort($slotsToFillArray, SORT_NUMERIC);
199
        // Build the output with slot options
200
        foreach ($slotsToFillArray as $option => $fill) {
201
            if (strlen($optionString) == 7) {
202
                // Means we prematurely reached the end due to wrong options being set hence go out of the loop
203
                break;
204
            }
205
            if (strlen($optionString) == 6) {
206
                // Ignore slots to fill value
207
                $optionString = $option . $optionString;
208
            } else {
209
                $optionString = $fill . $option . $optionString;
210
            }
211
        }
212
        if (strlen($optionString) < 7) {
213
            // Fill the output with 0s if there are empty slots
214
            $optionString = str_repeat('0', 7 - strlen($optionString)) . $optionString;
215
        }
216
        if ($format != self::OUTPUT_FORMAT_INTEGER) {
217
            return $this->_slots . $optionString;
218
        }
219
        return hexdec($this->_slots . $optionString);
220
    }
221
}