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

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