Passed
Push — 1.x-dev ( cc1b76...09423a )
by Doug
02:10
created

PackedBoxList   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Test Coverage

Coverage 82.05%

Importance

Changes 0
Metric Value
dl 0
loc 125
ccs 32
cts 39
cp 0.8205
rs 10
c 0
b 0
f 0
wmc 17

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getWeightVariance() 0 10 2
A getVolumeUtilisation() 0 16 3
A reverseCompare() 0 11 3
A compare() 0 14 4
A getMeanWeight() 0 11 3
A insertFromArray() 0 4 2
1
<?php
2
/**
3
 * Box packing (3D bin packing, knapsack problem).
4
 *
5
 * @author Doug Wright
6
 */
7
8
namespace DVDoug\BoxPacker;
9
10
/**
11
 * List of possible packed box choices, ordered by utilisation (item count, volume).
12
 *
13
 * @author Doug Wright
14
 */
15
class PackedBoxList extends \SplMinHeap
16
{
17
    /**
18
     * Average (mean) weight of boxes.
19
     *
20
     * @var float
21
     */
22
    protected $meanWeight;
23
24
    /**
25
     * Compare elements in order to place them correctly in the heap while sifting up.
26
     *
27
     * @see \SplMinHeap::compare()
28
     *
29
     * @param PackedBox $boxA
30
     * @param PackedBox $boxB
31
     *
32
     * @return int
33
     */
34 7
    public function compare($boxA, $boxB)
35
    {
36 7
        $choice = $boxA->getItems()->count() - $boxB->getItems()->count();
37 7
        if ($choice == 0) {
38 6
            $choice = $boxA->getVolumeUtilisation() - $boxB->getVolumeUtilisation();
39
        }
40 7
        if ($choice == 0) {
41 6
            $choice = $boxA->getUsedVolume() - $boxB->getUsedVolume();
42
        }
43 7
        if ($choice == 0) {
44 6
            $choice = $boxA->getWeight() - $boxB->getWeight();
45
        }
46
47 7
        return $choice;
48
    }
49
50
    /**
51
     * Reversed version of compare.
52
     *
53
     * @deprecated
54
     *
55
     * @param PackedBox $boxA
56
     * @param PackedBox $boxB
57
     *
58
     * @return int
59
     */
60
    public function reverseCompare($boxA, $boxB)
61
    {
62
        $choice = $boxB->getItems()->count() - $boxA->getItems()->count();
63
        if ($choice === 0) {
64
            $choice = $boxA->getBox()->getInnerVolume() - $boxB->getBox()->getInnerVolume();
65
        }
66
        if ($choice === 0) {
67
            $choice = $boxB->getWeight() - $boxA->getWeight();
68
        }
69
70
        return $choice;
71
    }
72
73
    /**
74
     * Calculate the average (mean) weight of the boxes.
75
     *
76
     * @return float
77
     */
78 3
    public function getMeanWeight()
79
    {
80 3
        if (!is_null($this->meanWeight)) {
0 ignored issues
show
introduced by
The condition ! is_null($this->meanWeight) can never be false.
Loading history...
81 1
            return $this->meanWeight;
82
        }
83
84 3
        foreach (clone $this as $box) {
85 3
            $this->meanWeight += $box->getWeight();
86
        }
87
88 3
        return $this->meanWeight /= $this->count();
89
    }
90
91
    /**
92
     * Calculate the variance in weight between these boxes.
93
     *
94
     * @return float
95
     */
96 2
    public function getWeightVariance()
97
    {
98 2
        $mean = $this->getMeanWeight();
99
100 2
        $weightVariance = 0;
101 2
        foreach (clone $this as $box) {
102 2
            $weightVariance += pow($box->getWeight() - $mean, 2);
103
        }
104
105 2
        return round($weightVariance / $this->count(), 1);
106
    }
107
108
    /**
109
     * Get volume utilisation of the set of packed boxes.
110
     *
111
     * @return float
112
     */
113 1
    public function getVolumeUtilisation()
114
    {
115 1
        $itemVolume = 0;
116 1
        $boxVolume = 0;
117
118
        /** @var PackedBox $box */
119 1
        foreach (clone $this as $box) {
120 1
            $boxVolume += $box->getBox()->getInnerVolume();
121
122
            /** @var Item $item */
123 1
            foreach (clone $box->getItems() as $item) {
124 1
                $itemVolume += $item->getVolume();
125
            }
126
        }
127
128 1
        return round($itemVolume / $boxVolume * 100, 1);
129
    }
130
131
    /**
132
     * Do a bulk insert.
133
     *
134
     * @param array $boxes
135
     */
136 2
    public function insertFromArray(array $boxes)
137
    {
138 2
        foreach ($boxes as $box) {
139 2
            $this->insert($box);
140
        }
141 2
    }
142
}
143