Passed
Push — master ( 73ddcb...629397 )
by Doug
02:34
created

PackedBox   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 39
c 4
b 0
f 0
dl 0
loc 198
ccs 51
cts 51
cp 1
rs 10
wmc 23

16 Methods

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