Passed
Pull Request — master (#308)
by
unknown
05:50 queued 03:55
created

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