Passed
Pull Request — master (#335)
by
unknown
05:51 queued 04:02
created

PackedBox::getRemainingWidth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

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