Passed
Push — master ( 26f6ea...ecaac2 )
by David
01:28
created

BreadthFirstBreadcrumb::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
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
     * @param callable|null $onPreCreateBreadcumb
97
     * @return BreadthFirstBreadcrumb
98
     */
99
    public function setOnPreCreateBreadcumb($onPreCreateBreadcumb)
100
    {
101
        $this->onPreCreateBreadcumb = $onPreCreateBreadcumb;
102
        return $this;
103
    }
104
105
    /**
106
     * @param callable|null $onWalk
107
     * @return BreadthFirstBreadcrumb
108
     */
109
    public function setOnWalk($onWalk)
110
    {
111
        $this->onWalk = $onWalk;
112
        return $this;
113
    }
114
}