Passed
Push — 1.x ( 457fa0...308477 )
by Doug
03:11
created

ItemList::hasConstrainedItems()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 7.9062

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 13
ccs 3
cts 8
cp 0.375
crap 7.9062
rs 10
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 47
    public function compare($itemA, $itemB)
34
    {
35 47
        if ($itemA->getVolume() > $itemB->getVolume()) {
36 21
            return 1;
37 46
        } elseif ($itemA->getVolume() < $itemB->getVolume()) {
38 18
            return -1;
39 41
        } elseif ($itemA->getWeight() !== $itemB->getWeight()) {
40 3
            return $itemA->getWeight() - $itemB->getWeight();
41 41
        } elseif ($itemA->getDescription() < $itemB->getDescription()) {
42 9
            return 1;
43
        } else {
44 39
            return -1;
45
        }
46
    }
47
48
    /**
49
     * Do a bulk create.
50
     *
51
     * @param  Item[]   $items
52
     * @return ItemList
53
     */
54 42
    public static function fromArray(array $items)
55
    {
56 42
        $list = new static();
57 42
        foreach ($items as $item) {
58 41
            $list->insert($item);
59
        }
60 42
        return $list;
61
    }
62
63
    /**
64
     * Get copy of this list as a standard PHP array.
65
     *
66
     * @return Item[]
67
     */
68 5
    public function asArray()
69
    {
70 5
        $return = [];
71 5
        foreach (clone $this as $item) {
72 5
            $return[] = $item;
73
        }
74
75 5
        return $return;
76
    }
77
78
    /**
79
     * @internal
80
     *
81
     * @param  int      $n
82
     * @return ItemList
83
     */
84 33
    public function topN($n)
85
    {
86 33
        $workingList = clone $this;
87 33
        $topNList = new self();
88 33
        $i = 0;
89 33
        while(!$workingList->isEmpty() && $i < $n) {
90 33
            $topNList->insert($workingList->extract());
91 33
            $i++;
92
        }
93
94 33
        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 37
    public function removePackedItems(PackedItemList $packedItemList)
124
    {
125
        /** @var PackedItem $packedItem */
126 37
        foreach (clone $packedItemList as $packedItem) {
127 32
            $workingSet = [];
128
129 32
            foreach ($this as $that) {
130 32
                if ($that === $packedItem->getItem()) {
131 32
                    $this->extract();
132 32
                    break;
133
                } else {
134 4
                    $workingSet[] = $that;
135
                }
136
            }
137
138 32
            foreach ($workingSet as $workingSetItem) {
139 4
                $this->insert($workingSetItem);
140
            }
141
        }
142 37
    }
143
144
    /**
145
     * @param Item $item
146
     */
147 50
    public function insert($item)
148
    {
149 50
        $this->hasConstrainedItems = $this->hasConstrainedItems || $item instanceof ConstrainedPlacementItem;
150 50
        parent::insert($item);
151 50
    }
152
153
    /**
154
     * Does this list contain items with constrained placement criteria.
155
     */
156 42
    public function hasConstrainedItems()
157
    {
158 42
        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 42
        return $this->hasConstrainedItems;
169
    }
170
}
171