Passed
Push — 3.x ( c7e27c...0cdb4c )
by Doug
07:08
created

PackedBox::getItems()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 * Box packing (3D bin packing, knapsack problem).
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace DVDoug\BoxPacker;
10
11
use function iterator_to_array;
12
use JsonSerializable;
13
use function max;
14
use function round;
15
16
/**
17
 * A "box" with items.
18
 *
19
 * @author Doug Wright
20
 */
21
class PackedBox implements JsonSerializable
22
{
23
    /**
24
     * Box used.
25
     *
26
     * @var Box
27
     */
28
    protected $box;
29
30
    /**
31
     * Items in the box.
32
     *
33
     * @var PackedItemList
34
     */
35
    protected $items;
36
37
    /**
38
     * Total weight of items in the box.
39
     *
40
     * @var int
41
     */
42
    protected $itemWeight;
43
44
    /**
45
     * Volume used for items as % of box.
46
     *
47
     * @var float
48
     */
49
    protected $volumeUtilisation;
50
51
    /**
52
     * Get box used.
53
     */
54 25
    public function getBox(): Box
55
    {
56 25
        return $this->box;
57
    }
58
59
    /**
60
     * Get items packed.
61
     */
62 56
    public function getItems(): PackedItemList
63
    {
64 56
        return $this->items;
65
    }
66
67
    /**
68
     * Get packed weight.
69
     *
70
     * @return int weight in grams
71
     */
72 10
    public function getWeight(): int
73
    {
74 10
        return $this->box->getEmptyWeight() + $this->getItemWeight();
75
    }
76
77
    /**
78
     * Get packed weight of the items only.
79
     *
80
     * @return int weight in grams
81
     */
82 11
    public function getItemWeight(): int
83
    {
84 11
        if ($this->itemWeight !== null) {
85 10
            return $this->itemWeight;
86
        }
87
88 11
        $this->itemWeight = 0;
89
        /** @var PackedItem $item */
90 11
        foreach ($this->items as $item) {
91 11
            $this->itemWeight += $item->getItem()->getWeight();
92
        }
93
94 11
        return $this->itemWeight;
95
    }
96
97
    /**
98
     * Get remaining width inside box for another item.
99
     */
100 1
    public function getRemainingWidth(): int
101
    {
102 1
        return $this->box->getInnerWidth() - $this->getUsedWidth();
103
    }
104
105
    /**
106
     * Get remaining length inside box for another item.
107
     */
108 1
    public function getRemainingLength(): int
109
    {
110 1
        return $this->box->getInnerLength() - $this->getUsedLength();
111
    }
112
113
    /**
114
     * Get remaining depth inside box for another item.
115
     */
116 1
    public function getRemainingDepth(): int
117
    {
118 1
        return $this->box->getInnerDepth() - $this->getUsedDepth();
119
    }
120
121
    /**
122
     * Used width inside box for packing items.
123
     */
124 5
    public function getUsedWidth(): int
125
    {
126 5
        $maxWidth = 0;
127
128
        /** @var PackedItem $item */
129 5
        foreach ($this->items as $item) {
130 5
            $maxWidth = max($maxWidth, $item->getX() + $item->getWidth());
131
        }
132
133 5
        return $maxWidth;
134
    }
135
136
    /**
137
     * Used length inside box for packing items.
138
     */
139 5
    public function getUsedLength(): int
140
    {
141 5
        $maxLength = 0;
142
143
        /** @var PackedItem $item */
144 5
        foreach ($this->items as $item) {
145 5
            $maxLength = max($maxLength, $item->getY() + $item->getLength());
146
        }
147
148 5
        return $maxLength;
149
    }
150
151
    /**
152
     * Used depth inside box for packing items.
153
     */
154 5
    public function getUsedDepth(): int
155
    {
156 5
        $maxDepth = 0;
157
158
        /** @var PackedItem $item */
159 5
        foreach ($this->items as $item) {
160 5
            $maxDepth = max($maxDepth, $item->getZ() + $item->getDepth());
161
        }
162
163 5
        return $maxDepth;
164
    }
165
166
    /**
167
     * Get remaining weight inside box for another item.
168
     */
169 1
    public function getRemainingWeight(): int
170
    {
171 1
        return $this->box->getMaxWeight() - $this->getWeight();
172
    }
173
174 58
    public function getInnerVolume(): int
175
    {
176 58
        return $this->box->getInnerWidth() * $this->box->getInnerLength() * $this->box->getInnerDepth();
177
    }
178
179
    /**
180
     * Get used volume of the packed box.
181
     */
182 58
    public function getUsedVolume(): int
183
    {
184 58
        return $this->items->getVolume();
185
    }
186
187
    /**
188
     * Get unused volume of the packed box.
189
     */
190 1
    public function getUnusedVolume(): int
191
    {
192 1
        return $this->getInnerVolume() - $this->getUsedVolume();
193
    }
194
195
    /**
196
     * Get volume utilisation of the packed box.
197
     */
198 13
    public function getVolumeUtilisation(): float
199
    {
200 13
        return $this->volumeUtilisation;
201
    }
202
203
    /**
204
     * Constructor.
205
     */
206 58
    public function __construct(Box $box, PackedItemList $packedItemList)
207
    {
208 58
        $this->box = $box;
209 58
        $this->items = $packedItemList;
210
211 58
        $this->volumeUtilisation = round($this->getUsedVolume() / ($this->getInnerVolume() ?: 1) * 100, 1);
212 58
    }
213
214
    public function jsonSerialize(): array
215
    {
216
        return [
217
            'box' => [
218
                'reference' => $this->box->getReference(),
219
                'innerWidth' => $this->box->getInnerWidth(),
220
                'innerLength' => $this->box->getInnerLength(),
221
                'innerDepth' => $this->box->getInnerDepth(),
222
            ],
223
            'items' => iterator_to_array($this->items),
224
        ];
225
    }
226
}
227