These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Box packing (3D bin packing, knapsack problem) |
||
4 | * @package BoxPacker |
||
5 | * @author Doug Wright |
||
6 | */ |
||
7 | declare(strict_types=1); |
||
8 | namespace DVDoug\BoxPacker; |
||
9 | |||
10 | /** |
||
11 | * A "box" with items |
||
12 | * @author Doug Wright |
||
13 | * @package BoxPacker |
||
14 | */ |
||
15 | class PackedBox |
||
16 | { |
||
17 | |||
18 | /** |
||
19 | * Box used |
||
20 | * @var Box |
||
21 | */ |
||
22 | protected $box; |
||
23 | |||
24 | /** |
||
25 | * Items in the box |
||
26 | * @var PackedItemList |
||
27 | */ |
||
28 | protected $items; |
||
29 | |||
30 | /** |
||
31 | * Total weight of box |
||
32 | * @var int |
||
33 | */ |
||
34 | protected $weight; |
||
35 | |||
36 | /** |
||
37 | * Get box used |
||
38 | * @return Box |
||
39 | */ |
||
40 | 4 | public function getBox(): Box |
|
41 | { |
||
42 | 4 | return $this->box; |
|
43 | } |
||
44 | |||
45 | /** |
||
46 | * Get items packed |
||
47 | * @return PackedItemList |
||
48 | */ |
||
49 | 35 | public function getItems(): PackedItemList |
|
50 | { |
||
51 | 35 | return $this->items; |
|
52 | } |
||
53 | |||
54 | /** |
||
55 | * Get packed weight |
||
56 | * @return int weight in grams |
||
57 | */ |
||
58 | 10 | public function getWeight(): int |
|
59 | { |
||
60 | 10 | if (!is_null($this->weight)) { |
|
61 | 7 | return $this->weight; |
|
62 | } |
||
63 | |||
64 | 10 | $this->weight = $this->box->getEmptyWeight(); |
|
65 | 10 | $items = clone $this->items; |
|
66 | /** @var PackedItem $item */ |
||
67 | 10 | foreach ($items as $item) { |
|
68 | 10 | $this->weight += $item->getItem()->getWeight(); |
|
69 | } |
||
70 | 10 | return $this->weight; |
|
71 | } |
||
72 | |||
73 | /** |
||
74 | * Get remaining width inside box for another item |
||
75 | * @return int |
||
76 | */ |
||
77 | 2 | public function getRemainingWidth(): int |
|
78 | { |
||
79 | 2 | return $this->box->getInnerWidth() - $this->getUsedWidth(); |
|
80 | } |
||
81 | |||
82 | /** |
||
83 | * Get remaining length inside box for another item |
||
84 | * @return int |
||
85 | */ |
||
86 | 2 | public function getRemainingLength(): int |
|
87 | { |
||
88 | 2 | return $this->box->getInnerLength() - $this->getUsedLength(); |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * Get remaining depth inside box for another item |
||
93 | * @return int |
||
94 | */ |
||
95 | 2 | public function getRemainingDepth(): int |
|
96 | { |
||
97 | 2 | return $this->box->getInnerDepth() - $this->getUsedDepth(); |
|
98 | } |
||
99 | |||
100 | /** |
||
101 | * Used width inside box for packing items |
||
102 | * @return int |
||
103 | */ |
||
104 | 6 | public function getUsedWidth(): int |
|
105 | { |
||
106 | 6 | $maxWidth = 0; |
|
107 | |||
108 | /** @var PackedItem $item */ |
||
109 | 6 | foreach (clone $this->items as $item) { |
|
110 | 6 | $maxWidth = max($maxWidth, $item->getX() + $item->getWidth()); |
|
111 | } |
||
112 | |||
113 | 6 | return $maxWidth; |
|
114 | } |
||
115 | |||
116 | /** |
||
117 | * Used length inside box for packing items |
||
118 | * @return int |
||
119 | */ |
||
120 | 6 | public function getUsedLength(): int |
|
121 | { |
||
122 | 6 | $maxLength = 0; |
|
123 | |||
124 | /** @var PackedItem $item */ |
||
125 | 6 | foreach (clone $this->items as $item) { |
|
126 | 6 | $maxLength = max($maxLength, $item->getY() + $item->getLength()); |
|
127 | } |
||
128 | |||
129 | 6 | return $maxLength; |
|
130 | } |
||
131 | |||
132 | /** |
||
133 | * Used depth inside box for packing items |
||
134 | * @return int |
||
135 | */ |
||
136 | 6 | public function getUsedDepth(): int |
|
137 | { |
||
138 | 6 | $maxDepth = 0; |
|
139 | |||
140 | /** @var PackedItem $item */ |
||
141 | 6 | foreach (clone $this->items as $item) { |
|
142 | 6 | $maxDepth = max($maxDepth, $item->getZ() + $item->getDepth()); |
|
143 | } |
||
144 | |||
145 | 6 | return $maxDepth; |
|
146 | } |
||
147 | |||
148 | /** |
||
149 | * Get remaining weight inside box for another item |
||
150 | * @return int |
||
151 | */ |
||
152 | 1 | public function getRemainingWeight(): int |
|
153 | { |
||
154 | 1 | return $this->box->getMaxWeight() - $this->getWeight(); |
|
155 | } |
||
156 | |||
157 | /** |
||
158 | * @return int |
||
159 | */ |
||
160 | 7 | public function getInnerVolume(): int |
|
161 | { |
||
162 | 7 | return $this->box->getInnerWidth() * $this->box->getInnerLength() * $this->box->getInnerDepth(); |
|
163 | } |
||
164 | |||
165 | /** |
||
166 | * Get volume utilisation of the packed box |
||
167 | * @return float |
||
168 | */ |
||
169 | 1 | public function getVolumeUtilisation(): float |
|
170 | { |
||
171 | 1 | $itemVolume = 0; |
|
172 | |||
173 | /** @var PackedItem $item */ |
||
174 | 1 | View Code Duplication | foreach (clone $this->items as $item) { |
0 ignored issues
–
show
|
|||
175 | 1 | $itemVolume += ($item->getItem()->getWidth() * $item->getItem()->getLength() * $item->getItem()->getDepth()); |
|
176 | } |
||
177 | |||
178 | 1 | return round($itemVolume / $this->getInnerVolume() * 100, 1); |
|
179 | } |
||
180 | |||
181 | |||
182 | /** |
||
183 | * Constructor |
||
184 | * |
||
185 | * @param Box $box |
||
186 | * @param PackedItemList $itemList |
||
187 | */ |
||
188 | 38 | public function __construct(Box $box, PackedItemList $itemList) |
|
189 | { |
||
190 | 38 | $this->box = $box; |
|
191 | 38 | $this->items = $itemList; |
|
192 | } |
||
193 | } |
||
194 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.