Completed
Push — master ( a9602e...8f132d )
by Hong
02:45
created

PriorityQueueTrait::insert()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 19
rs 9.4285
cc 1
eloc 7
nc 1
nop 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Shared
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Shared;
16
17
use Phossa2\Shared\Queue\PriorityQueueInterface;
18
19
/**
20
 * PriorityQueueTrait
21
 *
22
 * @package Phossa2\Shared
23
 * @author  Hong Zhang <[email protected]>
24
 * @see     PriorityQueueInterface
25
 * @version 2.0.20
26
 * @since   2.0.20 added
27
 */
28
trait PriorityQueueTrait
29
{
30
    /**
31
     * inner data storage
32
     *
33
     * @var    array
34
     * @access protected
35
     */
36
    protected $queue = [];
37
38
    /**
39
     * marker for sorted queue
40
     *
41
     * @var    bool
42
     * @access protected
43
     */
44
    protected $sorted = false;
45
46
    /**
47
     * priority counter, descreasing
48
     *
49
     * @var    int
50
     * @access protected
51
     */
52
    protected $counter = 10000000;
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    public function insert($data, /*# int */ $priority = 0)
58
    {
59
        // fix priority
60
        $pri = $this->fixPriority((int) $priority);
61
62
        // generate key to be used (int)
63
        $key = $this->generateKey($pri);
64
65
        // make sure not duplicated
66
        $this->remove($data);
67
68
        // added to the queue
69
        $this->queue[$key] = ['data' => $data, 'priority' => $pri];
70
71
        // mark as not sorted
72
        $this->sorted = false;
73
74
        return $this;
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    public function remove($data)
81
    {
82
        foreach ($this->queue as $key => $val) {
83
            if ($val['data'] === $data) {
84
                unset($this->queue[$key]);
85
                break;
86
            }
87
        }
88
        return $this;
89
    }
90
91
    /**
92
     * {@inheritdic}
93
     */
94
    public function flush()
95
    {
96
        $this->queue = [];
97
        return $this;
98
    }
99
100
    /**
101
     * {@inheritDoc}
102
     */
103
    public function combine(
104
        PriorityQueueInterface $queue
105
    )/*# : PriorityQueueInterface */ {
106
        // clone a new queue
107
        $nqueue = clone $this;
108
109
        // insert into new queue
110
        foreach ($queue as $data) {
111
            $nqueue->insert($data['data'], $data['priority']);
112
        }
113
114
        return $nqueue;
115
    }
116
117
    /**
118
     * {@inheritDoc}
119
     */
120
    public function count()
121
    {
122
        return count($this->queue);
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function getIterator()
129
    {
130
        // sort queue if not yet
131
        $this->sortQueue();
132
133
        // return iterator
134
        return new \ArrayIterator($this->queue);
135
    }
136
137
    /**
138
     * Make sure priority in the range of -100 - +100
139
     *
140
     * @param  int $priority
141
     * @return int
142
     * @access protected
143
     */
144
    protected function fixPriority(/*# int */ $priority)/*# : int */
145
    {
146
        return (int) ($priority > 100 ? 100 : ($priority < -100 ? -100 : $priority));
147
    }
148
149
    /**
150
     * Generate one int base on the priority
151
     *
152
     * @param  int $priority
153
     * @return int
154
     * @access protected
155
     */
156
    protected function generateKey(/*# int */ $priority)/*# : int */
157
    {
158
        return ($priority + 100) * 10000000 + --$this->counter;
159
    }
160
161
    /**
162
     * Sort the queue from higher to lower int $key
163
     *
164
     * @return $this
165
     * @access protected
166
     */
167
    protected function sortQueue()
168
    {
169
        if (!$this->sorted) {
170
            krsort($this->queue);
171
            $this->sorted = true;
172
        }
173
        return $this;
174
    }
175
}
176
177