Passed
Pull Request — master (#294)
by
unknown
18:38 queued 14:21
created

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