Issues (18)

src/Tree.php (9 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace MartanLV\Koki;
6
7
/**
8
 * Augmented tree
9
 * Class StaticTree.
10
 *
11
 * @author yourname
12
 */
13
class Tree extends Node
14
{
15
    public $root;
16
17
    /**
18
     * undocumented function.
19
     *
20
     * @param $intervals array of Interval
21
     *
22
     * @return void
23
     */
24
    public function __construct(array $intervals = [], bool $preSorted = false)
25
    {
26
        !$preSorted && usort($intervals, function (IntervalInterface $i0, IntervalInterface $i) {
27
            return $i0->getStart() <=> $i->getStart();
28
        });
29
        $this->root = $this->toTree($intervals);
30
    }
31
32
    /**
33
     * An augmented tree can be built from a simple ordered tree,
34
     * for example a binary search tree or self-balancing binary search tree,
35
     * ordered by the 'low' values of the intervals.
36
     */
37
    public function toTree(array $intervals)
38
    {
39
        $max = 0;
40
        $len = count($intervals);
41
        $mid = (int) floor($len / 2);
42
43
        if (!$len) {
44
            return;
45
        }
46
47
        array_walk($intervals, function (IntervalInterface $el) use (&$max) {
48
            if ($max < $el->getEnd()) {
49
                $max = $el->getEnd();
50
            }
51
        });
52
        $l_intervals = array_splice($intervals, 0, $mid);
53
        $r_intervals = array_splice($intervals, -$mid);
54
        $interval = $intervals ? reset($intervals) : array_pop($l_intervals);
55
        $interval = $interval ?? array_pop($r_intervals);
56
57
        $node = new Node(
58
            $interval,
59
            $this->toTree($l_intervals),
60
            $this->toTree($r_intervals),
61
            $max
62
        );
63
64
        $node->root = &$this;
65
66
        return $node;
67
    }
68
69
    /**
70
     * returns intervals that exclusively fall within range given
71
     * to retrieve eather bound inclusevely, just modify parameters.
72
     *
73
     * @return void
74
     */
75
    public function select(int $low, int $high): array
76
    {
77
        return $this->root ? $this->root->select($low, $high) : [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->root ? $th...($low, $high) : array() returns the type array which is incompatible with the documented return type void.
Loading history...
78
    }
79
80
    public function selectNode(int $low, int $high): array
81
    {
82
        return $this->root ? $this->root->selectNode($low, $high) : [];
83
    }
84
85
    /**
86
     * rebalance messed up tree overall.
87
     */
88
    public function balance()
89
    {
90
        // todo
91
    }
92
93
    /**
94
     * understandable var dump.
95
     */
96
    public function __debugInfo()
97
    {
98
        $arr = $this->all();
99
100
        usort($arr, function (IntervalInterface $i0, IntervalInterface $i) {
101
            return $i0->getStart() <=> $i->getStart();
102
        });
103
104
        return $arr;
105
    }
106
107
    public function yieldInterSelect(int $low, int $high)
108
    {
109
        return $this->root ? $this->root->yieldInterSelect($low, $high) : [];
110
    }
111
112
    public function interSelectNode(int $low, int $high): array
113
    {
114
        return $this->root ? $this->root->interSelectNode($low, $high) : [];
115
    }
116
117
    public function interSelect(int $low, int $high): array
118
    {
119
        return $this->root ? $this->root->interSelect($low, $high) : [];
120
    }
121
122
    public function yieldSelect(int $low, int $high)
123
    {
124
        return $this->root ? $this->root->yieldSelect($low, $high) : [];
125
    }
126
127
    /**
128
     * @return void
129
     */
130
    public function all(): array
131
    {
132
        return $this->root ? $this->root->all() : [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->root ? $this->root->all() : array() returns the type array which is incompatible with the documented return type void.
Loading history...
133
    }
134
135
    /**
136
     * undocumented function.
137
     *
138
     * @return void
139
     */
140
    public function yieldAll()
141
    {
142
        return $this->root ? $this->root->yieldAll() : [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->root ? $th...t->yieldAll() : array() returns the type array which is incompatible with the documented return type void.
Loading history...
Are you sure the usage of $this->root->yieldAll() targeting MartanLV\Koki\Node::yieldAll() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
143
    }
144
145
    public function removeRegion(int $low, int $high)
146
    {
147
        if (!$this->root) {
148
            return [];
149
        }
150
        foreach ($this->interSelectNode($low, $high) as $node) {
151
            $this->remove($node);
152
        }
153
    }
154
155
    public function remove(IntervalInterface $i)
156
    {
157
        if (!$i->left && !$i->right) {
0 ignored issues
show
Accessing left on the interface MartanLV\Koki\IntervalInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
Accessing right on the interface MartanLV\Koki\IntervalInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
158
            if ($i->root) {
0 ignored issues
show
Accessing root on the interface MartanLV\Koki\IntervalInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
159
                $i->root = null;
160
            }
161
162
            return;
163
        }
164
165
        if ($i->left && $i->right) {
166
            // todo
167
            return;
168
        }
169
        if ($i->left) {
170
            $i->interval = &$i->left->interval;
0 ignored issues
show
Accessing interval on the interface MartanLV\Koki\IntervalInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
171
            $i->left = null;
172
        }
173
174
        if ($i->right) {
175
        }
176
177
        if ($this->max > $i->getEnd()) {
178
            if ($this->left) {
179
                $this->left->add($i);
180
            } else {
181
                $this->left = new Node($i);
182
            }
183
        } else {
184
            $this->max = $i->getEnd();
185
            if ($this->right) {
186
                $this->right->add($i);
187
            } else {
188
                $this->right = new Node($i);
189
            }
190
        }
191
192
        return;
193
        if (!$this->root) {
0 ignored issues
show
IfNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
194
            return [];
195
        }
196
        $this->root->remove($i);
197
    }
198
199
    public function add(IntervalInterface $i)
200
    {
201
        if (!$this->root) {
202
            $this->root = new Node($i);
203
204
            return;
205
        }
206
        $this->root->add($i);
207
    }
208
}
209