Completed
Push — master ( 48f643...20cea4 )
by Ventaquil
02:25
created

Dijkstra::distances()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
namespace Algorithms;
3
4
class Dijkstra
5
{
6
    protected $points;
7
    protected $relations;
8
9
    public function __construct($relations = null)
10
    {
11
        if (!empty($relations)) {
12
            $this->setRelations($relations);
13
        }
14
    }
15
16
    public function setRelations($relations)
17
    {
18
        if (self::validate($relations)) {
19
            $this->relations = $relations;
20
        } else {
21
            if (is_callable($relations) && ($relations instanceof \Closure)) {
22
                $creator = new GraphTools\Creator;
23
                call_user_func($relations, $creator);
24
25
                $this->relations = $creator->createConnections();
26
            }
27
        }
28
    }
29
30
    public function generate()
31
    {
32
        $result = []; # Prepare results array
33
34
        # Analyze all relations
35
            foreach ($this->relations as $point => $relation) {
36
                # Prepare $points array by isset source point
37
                    $this->points = [
38
                        $point => [
39
                            0,
40
                            '',
41
                        ],
42
                    ];
43
44
                $this->dist($point, $point);
45
                $result[$point] = $this->points; # Copy $points content to results array
46
            }
47
48
        return $result;
49
    }
50
51
    private function dist($source, $point, &$visited = [])
52
    {
53
        $visited[$point] = true; # Set current point as visited
54
55
        # Prepare help variables
56
            $min_ptr = -1;
57
            $min = 0;
58
59
        # Analyzes point neighborhood
60
            foreach ($this->relations[$point] as $relation) {
61
                if ($relation[0] != $source) { # If current point is different than source
62
                    if (empty($visited[$relation[0]])) { # If current point is not visited
63
                        if ($min_ptr == -1) { # When minimal point is not finded
64
                            $min_ptr = $relation[0];
65
                            $min = $relation[1];
66
                        } else {
67
                            if ($min > $relation[1]) {
68
                                $min_ptr = $relation[0];
69
                                $min = $relation[1];
70
                            }
71
                        }
72
                    }
73
74
                    # Change the shortest way to current point
75
                        if (isset($this->points[$point][0])) {
76
                            $first_field = $this->points[$point][0];
77
                        } else {
78
                            $first_field = 0;
79
                        }
80
81
                        if (empty($this->points[$relation[0]])) {
82
                            $this->points[$relation[0]] = [
83
                                $first_field + $relation[1],
84
                                ((empty($this->points[$point][1])) ? $point : $this->points[$point][1]) . ':' . $relation[0],
85
                            ];
86
                        } else {
87
                            if ($this->points[$relation[0]][0] > ($this->points[$point][0] + $relation[1])) {
88
                                $this->points[$relation[0]] = [
89
                                    (isset($this->points[$point][0]) ? $this->points[$point][0] : 0) + $relation[1],
90
                                    (empty($this->points[$point][1]) ? null : $this->points[$point][1] . ':') . $relation[0],
91
                                ];
92
                            }
93
                        }
94
                }
95
            }
96
97
        # If isset unvisited point with minimal way go for it
98
            if ($min_ptr != -1) {
99
                $this->dist($source, $min_ptr, $visited);
100
            }
101
    }
102
103
    public function distances($point)
104
    {
105
        $this->dist($point, $point);
106
        return $this->points;
107
    }
108
109 View Code Duplication
    private static function validate($relations_array)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
    {
111
        if (is_array($relations_array)) {
112
            $return = true;
113
            foreach ($relations_array as $relations) {
114
                $return = self::checkPointRelations($relations);
115
            }
116
117
            return $return;
118
        } else {
119
            return false;
120
        }
121
    }
122
123 View Code Duplication
    private static function checkPointRelations($relations)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
    {
125
        if (is_array($relations)) {
126
            $return = true;
127
128
            foreach ($relations as $relation) {
129
                $return = self::checkSingleRelation($relation);
130
            }
131
132
            return $return;
133
        } else {
134
            return false;
135
        }
136
    }
137
138
    private static function checkSingleRelation($relation)
139
    {
140
        return (is_array($relation) && (count($relation) == 2) && isset($relation[0]) && isset($relation[1]));
141
    }
142
}
143