Test Failed
Push — 2.x-dev ( 5e90af...eccc16 )
by Doug
03:16
created

ItemList::removePackedItems()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.2

Importance

Changes 0
Metric Value
cc 5
eloc 10
c 0
b 0
f 0
nc 7
nop 1
dl 0
loc 17
ccs 8
cts 10
cp 0.8
crap 5.2
rs 9.6111
1
<?php
2
/**
3
 * Box packing (3D bin packing, knapsack problem).
4
 *
5
 * @author Doug Wright
6
 */
7
namespace DVDoug\BoxPacker;
8
9
/**
10
 * List of items to be packed, ordered by volume.
11
 *
12
 * @author Doug Wright
13
 */
14
class ItemList extends \SplMaxHeap
15
{
16
    /**
17
     * Does this list contain constrained items?
18
     *
19
     * @var bool
20
     */
21
    private $hasConstrainedItems;
22
23
    /**
24
     * Compare elements in order to place them correctly in the heap while sifting up.
25
     *
26
     * @see \SplMaxHeap::compare()
27
     *
28
     * @param mixed $itemA
29
     * @param mixed $itemB
30
     *
31
     * @return int
32
     */
33 32
    public function compare($itemA, $itemB)
34
    {
35 32
        if ($itemA->getVolume() > $itemB->getVolume()) {
36 15
            return 1;
37 31
        } elseif ($itemA->getVolume() < $itemB->getVolume()) {
38 15
            return -1;
39 26
        } elseif ($itemA->getWeight() !== $itemB->getWeight()) {
40 3
            return $itemA->getWeight() - $itemB->getWeight();
41 26
        } elseif ($itemA->getDescription() < $itemB->getDescription()) {
42 7
            return 1;
43
        } else {
44 24
            return -1;
45
        }
46
    }
47
48
    /**
49
     * Do a bulk create.
50
     *
51
     * @param  Item[]   $items
52
     * @return ItemList
53
     */
54 28
    public static function fromArray(array $items)
55
    {
56 28
        $list = new static();
57 28
        foreach ($items as $item) {
58 26
            $list->insert($item);
59
        }
60 28
        return $list;
61
    }
62
63
    /**
64
     * Get copy of this list as a standard PHP array.
65
     *
66
     * @return Item[]
67
     */
68
    public function asArray()
69
    {
70
        $return = [];
71
        foreach (clone $this as $item) {
72
            $return[] = $item;
73
        }
74
75
        return $return;
76
    }
77
78
    /**
79
     * @internal
80
     *
81
     * @param  int      $n
82
     * @return ItemList
83
     */
84 18
    public function topN($n)
85
    {
86 18
        $workingList = clone $this;
87 18
        $topNList = new self();
88 18
        $i = 0;
89 18
        while(!$workingList->isEmpty() && $i < $n) {
90 18
            $topNList->insert($workingList->extract());
91 18
            $i++;
92
        }
93
94 18
        return $topNList;
95
    }
96
97
    /**
98
     * Remove item from list.
99
     *
100
     * @param Item $item
101
     */
102
    public function remove(Item $item)
103
    {
104
        $workingSet = [];
105
106
        foreach ($this as $that) {
107
            if ($that === $item) {
108
                $this->extract();
109
                break;
110
            } else {
111
                $workingSet[] = $that;
112
            }
113
        }
114
115
        foreach ($workingSet as $workingSetItem) {
116
            $this->insert($workingSetItem);
117
        }
118
    }
119
120
    /**
121
     * @param PackedItemList $packedItemList
122
     */
123 7
    public function removePackedItems(PackedItemList $packedItemList)
124
    {
125
        /** @var PackedItem $packedItem */
126 7
        foreach (clone $packedItemList as $packedItem) {
127 7
            $workingSet = [];
128
129 7
            foreach ($this as $that) {
130 7
                if ($that === $packedItem->getItem()) {
131 7
                    $this->extract();
132 7
                    break;
133
                } else {
134
                    $workingSet[] = $that;
135
                }
136
            }
137
138 7
            foreach ($workingSet as $workingSetItem) {
139
                $this->insert($workingSetItem);
140
            }
141
        }
142 7
    }
143
144
    /**
145
     * @param Item $item
146
     */
147 36
    public function insert($item)
148
    {
149 36
        $this->hasConstrainedItems = $this->hasConstrainedItems || $item instanceof ConstrainedPlacementItem;
150 36
        parent::insert($item);
151 36
    }
152
153
    /**
154
     * Does this list contain items with constrained placement criteria.
155
     */
156 28
    public function hasConstrainedItems()
157
    {
158 28
        if (!isset($this->hasConstrainedItems)) {
159
            $this->hasConstrainedItems = false;
160
            foreach (clone $this as $item) {
161
                if ($item instanceof ConstrainedPlacementItem) {
162
                    $this->hasConstrainedItems = true;
163
                    break;
164
                }
165
            }
166
        }
167
168 28
        return $this->hasConstrainedItems;
169
    }
170
}
171