Passed
Push — master ( ecaac2...a03751 )
by David
01:36
created

BreadthFirstBreadcrumb::setOnPreCreateBreadcumb()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GGGGino\WarehousePath\Breadcrumb;
4
5
use GGGGino\WarehousePath\Entity\Place;
6
use GGGGino\WarehousePath\PlacesCollector;
7
8
class BreadthFirstBreadcrumb implements BreadcrumbInterface
9
{
10
    /**
11
     * Callback useful if you want to modifiy temporarily some wharehouse configuration
12
     * es.
13
     * function(Place $startPlace, array $placesType) {};
14
     *
15
     * @var callable|null
16
     */
17
    private $onPreCreateBreadcumb = null;
18
19
    /**
20
     * Callback useful if you want to customize the mapping of this wharehouse.
21
     * Called in every loops
22
     * es.
23
     * function(Place $currentPlace) {};
24
     *
25
     * @var callable|null
26
     */
27
    private $onWalk = null;
28
29
    /**
30
     * @var PlacesCollector
31
     */
32
    protected $placeCollector;
33
34
    /**
35
     * BreadthFirstBreadcrumb constructor.
36
     * @param PlacesCollector $placeCollector
37
     */
38
    public function __construct(PlacesCollector $placeCollector)
39
    {
40
        $this->placeCollector = $placeCollector;
41
    }
42
43
    /**
44
     * Main algorithm to find the shortest path.
45
     *
46
     * @todo: nel futuro quando ci sarà un magazzino grande, spezzare il magazzino prendendo solo il quadrato contenente i vari punti
47
     *
48
     * @param Place $startPlace
49
     * @param Place $endPlace if not null do early exit
50
     */
51
    public function createBreadcrumb(Place $startPlace, Place $endPlace = null)
52
    {
53
        if ( is_callable( $this->onPreCreateBreadcumb ) ) {
54
            call_user_func($this->onPreCreateBreadcumb, $startPlace, $this->placeCollector->getPlacesType());
55
        }
56
57
        $frontier = array();
58
        array_push($frontier, $startPlace);
59
60
        while (!empty($frontier)) {
61
            /** @var Place $current */
62
            $current = array_shift($frontier);
63
64
            if ( is_callable( $this->onWalk ) ) {
65
                call_user_func($this->onWalk, $current);
66
            }
67
68
            /** @var Place $vicino */
69
            foreach ($current->getWalkableNeighbors() as $vicino) {
70
                $tempCost = $current->getCurrentWeight() + $vicino->getOriginalWeight();
71
72
                if ($vicino->isVisited() && $tempCost < $vicino->getCurrentWeight()) {
73
                    $vicino->setCurrentWeight($tempCost);
74
                    $vicino->setWalkingCameFrom($current);
75
                    array_push($frontier, $vicino);
76
                    continue;
77
                }
78
79
                if ($vicino->isVisited()) {
80
                    continue;
81
                }
82
83
                $vicino->setVisited(true);
84
85
                $vicino->increaseCurrentWeight($current->getCurrentWeight());
86
                $vicino->setWalkingCameFrom($current);
87
88
                array_push($frontier, $vicino);
89
            }
90
91
            $current->setVisited(true);
92
        }
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function createMultipleBreadcrumb(array $places)
99
    {
100
        $matrixDistances = array();
101
102
        /** @var Place $place */
103
        foreach ($places as $place) {
104
            $this->createBreadcrumb($place);
105
            $tempPlaceDistance = array();
106
107
            /** @var Place $place1 */
108
            foreach ($places as $place1) {
109
                $tempPlaceDistance[] = $place1->getCurrentWeight();
110
            }
111
112
            $matrixDistances[] = $tempPlaceDistance;
113
            $this->placeCollector->reset();
114
        }
115
116
        return $matrixDistances;
117
    }
118
119
    /**
120
     * @param callable|null $onPreCreateBreadcumb
121
     * @return BreadthFirstBreadcrumb
122
     */
123
    public function setOnPreCreateBreadcumb($onPreCreateBreadcumb)
124
    {
125
        $this->onPreCreateBreadcumb = $onPreCreateBreadcumb;
126
        return $this;
127
    }
128
129
    /**
130
     * @param callable|null $onWalk
131
     * @return BreadthFirstBreadcrumb
132
     */
133
    public function setOnWalk($onWalk)
134
    {
135
        $this->onWalk = $onWalk;
136
        return $this;
137
    }
138
}