Completed
Pull Request — master (#301)
by personal
02:13
created

SizeOfTree::getNumberOfChilds()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 37
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 17
c 0
b 0
f 0
nc 6
nop 2
dl 0
loc 37
rs 6.7272
1
<?php
2
3
/*
4
 * (c) Jean-François Lépine <https://twitter.com/Halleck45>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Hal\Component\Tree\Operator;
11
12
use Hal\Component\Tree\Graph;
13
use Hal\Component\Tree\Node;
14
15
class SizeOfTree
16
{
17
    /**
18
     * @var Graph
19
     */
20
    private $graph;
21
22
    /**
23
     * SizeOfTree constructor.
24
     * @param Graph $graph
25
     */
26
    public function __construct(Graph $graph)
27
    {
28
        if ((new CycleDetector())->isCyclic($graph)) {
29
            throw new \LogicException('Cannot get size informations of cyclic graph');
30
        }
31
32
        $this->graph = $graph;
33
    }
34
35
    /**
36
     * Get depth of node
37
     *
38
     * @param Node $node
39
     * @return int
40
     */
41
    public function getDepthOfNode(Node $node)
42
    {
43
44
        $edges = $node->getEdges();
45
46
        if (0 === sizeof($edges)) {
47
            return 0;
48
        }
49
50
        // our tree is not binary : interface can have more than one parent
51
        $max = 0;
52
        foreach ($edges as $edge) {
53
54
            if ($edge->getFrom() == $node) {
55
                continue;
56
            }
57
58
            $n = 1 + $this->getDepthOfNode($edge->getFrom());
59
            if ($n > $max) {
60
                $max = $n;
61
            }
62
        }
63
64
        return $max;
65
    }
66
67
    /**
68
     * Get depth of node
69
     *
70
     * @param Node $node
71
     * @return int
72
     */
73
    public function getNumberOfChilds(Node $node, $uniqs = false)
74
    {
75
76
        $edges = $node->getEdges();
77
78
        if (0 === sizeof($edges)) {
79
            return 0;
80
        }
81
82
        // our tree is not binary : interface can have more than one parent
83
        $max = 0;
84
        $n = 0;
85
86
        foreach ($edges as $edge) {
87
88
89
            if ($edge->getTo() == $node) {
90
                continue;
91
            }
92
93
            if (true == $uniqs && $edge->getTo()->visited) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
94
                continue;
95
            }
96
            $edge->getTo()->visited = true;
97
98
            $n += 1 + $this->getNumberOfChilds($edge->getTo(), $uniqs);
99
100
            $edge->getTo()->visited = false;
101
102
103
            if ($n > $max) {
104
                $max = $n;
105
            }
106
        }
107
108
        return $max;
109
    }
110
111
    /**
112
     * Get average height of graph
113
     *
114
     * @return float
115
     */
116
    public function getAverageHeightOfGraph()
117
    {
118
        $ns = [];
119
        foreach ($this->graph->getRootNodes() as $node) {
120
            array_push($ns, $this->getLongestBranch($node));
121
        }
122
        return round(array_sum($ns) / max(1, sizeof($ns)), 2);
123
    }
124
125
    /**
126
     * @param Node $node
127
     * @return int
128
     */
129
    public function getLongestBranch(Node $node)
130
    {
131
        $max = 1;
132
        foreach ($node->getEdges() as $edge) {
133
134
            if ($node == $edge->getTo()) {
135
                // only descendants
136
                continue;
137
            }
138
139
            $n = 1 + $this->getLongestBranch($edge->getTo());
140
141
            if ($n > $max) {
142
                $max = $n;
143
            }
144
        }
145
146
        return $max;
147
    }
148
}
149