Passed
Push — master ( e0ffe6...4f8f39 )
by David
01:56
created

Warehouse::createMatrix()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 39
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
nc 5
nop 0
dl 0
loc 39
rs 9.0111
c 0
b 0
f 0
1
<?php
2
3
namespace GGGGino\WarehousePath;
4
5
use GGGGino\WarehousePath\Calculator\CalculatorInterface;
6
use GGGGino\WarehousePath\Entity\Place;
7
use GGGGino\WarehousePath\Parser\JsonMatrixParser;
8
use GGGGino\WarehousePath\Parser\MatrixParser;
9
use GGGGino\WarehousePath\Parser\ParserInterface;
10
use GGGGino\WarehousePath\Parser\TreeParser;
11
12
class Warehouse
13
{
14
    /**
15
     * @var PlacesCollector
16
     */
17
    private $placesCollector;
18
19
    /**
20
     * @var Place[]
21
     */
22
    private $places = array();
23
24
    /**
25
     * @var CalculatorInterface
26
     */
27
    private $pathCalculator;
28
29
    /**
30
     * @var ParserInterface
31
     */
32
    private $parser;
33
34
    public function __construct(PlacesCollector $placesCollector, ParserInterface $parser)
35
    {
36
        $this->placesCollector = $placesCollector;
37
        $this->parser = $parser;
38
    }
39
40
    /***
41
     * @param string $path
42
     * @return Warehouse
43
     * @throws \Exception
44
     */
45
    public static function createFromJson($path)
46
    {
47
        if( !$path )
48
            throw new \Exception('Please select a path');
49
50
        $placesCollector = new PlacesCollector();
51
        $placesCollector->addBasePlaceTypes();
52
53
        $wm = new JsonMatrixParser($path, $placesCollector);
54
55
        $instance = new self($placesCollector, $wm);
56
        $instance->setPlaces($wm->parse());
57
58
        return $instance;
59
    }
60
61
    /**
62
     * @param $param
63
     * @return Warehouse
64
     * @throws \Exception
65
     */
66
    public static function createFromMatrix($param)
67
    {
68
        if( !is_array($param) )
69
            throw new \Exception('Matrix should be initialized with an array');
70
71
        $placesCollector = new PlacesCollector();
72
        $placesCollector->addBasePlaceTypes();
73
74
        $wm = new MatrixParser($param, $placesCollector);
75
76
        $instance = new self($placesCollector, $wm);
77
        $instance->setPlaces($wm->parse());
78
79
        return $instance;
80
    }
81
82
    /**
83
     * @param $param
84
     * @return Warehouse
85
     * @throws \Exception
86
     */
87
    public static function createFromTree($param)
88
    {
89
        if( !is_array($param) )
90
            throw new \Exception('Matrix should be initialized with an array');
91
92
        $placesCollector = new PlacesCollector();
93
        $placesCollector->addBasePlaceTypes();
94
95
        $wm = new TreeParser($param);
96
97
        $instance = new self($placesCollector, $wm);
98
        $instance->setPlaces($wm->parse());
99
100
        return $instance;
101
    }
102
103
    /**
104
     * Main algorithm to find the shortest path.
105
     *
106
     * @todo: nel futuro quando ci sarà un magazzino grande, spezzare il magazzino prendendo solo il quadrato contenente i vari punti
107
     *
108
     * @param Place $startPlace
109
     * @param Place $endPlace if not null do early exit
110
     */
111
    public function getPath(Place $startPlace, Place $endPlace = null)
0 ignored issues
show
Unused Code introduced by
The parameter $endPlace is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

111
    public function getPath(Place $startPlace, /** @scrutinizer ignore-unused */ Place $endPlace = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
112
    {
113
        $frontier = array();
114
        array_push($frontier, $startPlace);
115
116
        while (!empty($frontier)) {
117
            /** @var Place $current */
118
            $current = array_shift($frontier);
119
120
            /** @var Place $vicino */
121
            foreach ($current->getWalkableNeighbors() as $vicino) {
122
                $tempCost = $current->getCurrentWeight() + $vicino->getOriginalWeight();
123
124
                if ($vicino->isVisited() && $tempCost < $vicino->getCurrentWeight()) {
125
                    $vicino->setCurrentWeight($tempCost);
126
                    $vicino->setWalkingCameFrom($current);
127
                    array_push($frontier, $vicino);
128
                    continue;
129
                }
130
131
                if ($vicino->isVisited()) {
132
                    continue;
133
                }
134
135
                $vicino->setVisited(true);
136
137
                $vicino->increaseCurrentWeight($current->getCurrentWeight());
138
                $vicino->setWalkingCameFrom($current);
139
140
                array_push($frontier, $vicino);
141
            }
142
143
            $current->setVisited(true);
144
        }
145
    }
146
147
    /**
148
     * Reset all the node to permit another calculation
149
     */
150
    public function reset()
151
    {
152
        foreach ($this->places as $place) {
153
            $place->reset();
154
        }
155
    }
156
157
    /**
158
     * For every place i create the path
159
     *
160
     * @param Place[] $places
161
     * @return array
162
     */
163
    public function getMultiplePath(array $places)
164
    {
165
        $matrixDistances = array();
166
167
        /** @var Place $place */
168
        foreach ($places as $place) {
169
            $this->getPath($place);
170
            $tempPlaceDistance = array();
171
172
            /** @var Place $place */
173
            foreach ($places as $place1) {
174
                $tempPlaceDistance[] = $place1->getCurrentWeight();
175
            }
176
177
            $matrixDistances[] = $tempPlaceDistance;
178
            $this->reset();
179
        }
180
181
        return $matrixDistances;
182
    }
183
184
    /**
185
     * Create the matrix for development purpose.
186
     * If you want to print the whole wharehouse
187
     *
188
     * @return Entity\Place[][]
189
     * @throws \Exception
190
     */
191
    public function createMatrix()
192
    {
193
        /** @var Place[] $places */
194
        $places = $this->getPlaces();
195
196
        /** @var Place[][] $resultMatrix */
197
        $resultMatrix = array();
198
199
        if ( empty($places) )
200
            throw new \Exception('First add the places');
201
202
        /** @var Place $startingPlace */
203
        $startingPlace = reset($places);
204
205
        while ( $newPlace = $startingPlace->getTopRef() ) {
206
            $startingPlace = $newPlace;
207
        }
208
209
        while ( $newPlace = $startingPlace->getLeftRef() ) {
210
            $startingPlace = $newPlace;
211
        }
212
213
        /** @var Place $rowPlace */
214
        $rowPlace = $startingPlace;
215
216
        do {
217
            $tempRow = array();
218
219
            /** @var Place $columnPlace */
220
            $columnPlace = $rowPlace;
221
222
            do {
223
                $tempRow[] = $columnPlace;
224
            } while ($columnPlace = $columnPlace->getRightRef());
225
226
            $resultMatrix[] = $tempRow;
227
        } while ($rowPlace = $rowPlace->getBottomRef());
228
229
        return $resultMatrix;
230
    }
231
232
    /**
233
     * @param $arrayNodes
234
     * @param $matrix
235
     * @return Place[]
236
     */
237
    public function calculate($arrayNodes, $matrix)
238
    {
239
        return $this->pathCalculator->calculate($arrayNodes, $matrix);
240
    }
241
242
    /**
243
     * @return Place[]
244
     */
245
    public function getPlaces(): array
246
    {
247
        return $this->places;
248
    }
249
250
    /**
251
     * @param Entity\Place[] $places
252
     * @return Warehouse
253
     */
254
    public function setPlaces($places)
255
    {
256
        $this->places = $places;
257
        return $this;
258
    }
259
260
    /**
261
     * @param CalculatorInterface $pathCalculator
262
     * @return Warehouse
263
     */
264
    public function setPathCalculator($pathCalculator)
265
    {
266
        $this->pathCalculator = $pathCalculator;
267
        return $this;
268
    }
269
270
    /**
271
     * @param PlacesCollector $placesCollector
272
     * @return Warehouse
273
     */
274
    public function setPlacesCollector($placesCollector)
275
    {
276
        $this->placesCollector = $placesCollector;
277
        return $this;
278
    }
279
280
    /**
281
     * @return ParserInterface
282
     */
283
    public function getParser(): ParserInterface
284
    {
285
        return $this->parser;
286
    }
287
288
    /**
289
     * @return PlacesCollector
290
     */
291
    public function getPlacesCollector()
292
    {
293
        return $this->placesCollector;
294
    }
295
}