Passed
Push — master ( 1d376a...450b13 )
by Denis
03:25
created

Generator::getRandomAddresses()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Ngtfkx\Laradeck\AddressGenerator;
4
5
6
use Illuminate\Support\Collection;
7
use Ngtfkx\Laradeck\AddressGenerator\Exceptions\CityNotFound;
8
9
class Generator
10
{
11
    /**
12
     * @var Collection Список городов для которых будем генерировать адреса
13
     */
14
    protected $cities;
15
16
    /**
17
     * @var Collection Список доступных для поиска имен городов городов
18
     */
19
    protected $searchableCityNames;
20
21
    /**
22
     * @var Collection Список достпупных гордов
23
     */
24
    protected $availableCities;
25
26
    /**
27
     * @var Collection Список достпупных адресов
28
     */
29
    protected $availableAddresses;
30
31
    /**
32
     * Generator constructor.
33
     */
34
    public function __construct()
35
    {
36
        $this->cities = new Collection();
37
38
        $this->makeCities();
39
40
        $this->makeAddresses();
41
    }
42
43
    /**
44
     * Получить случайный адрес
45
     *
46
     * @param string|null $forCity Имя города, для которого генерировать адрес. По умолчанию null - из любого установленного
47
     * @return Address
48
     * @throws CityNotFound Город не найден в списке доступных
49
     */
50
    public function getRandomAddress($forCity = null): Address
51
    {
52
        $forCity = $forCity ?: $this->getCities()->random();
53
54
        $forCity = Helper::prepare($forCity);
55
56
        $cityId = $this->getCityIdByName($forCity);
57
58
        $address = $this->availableAddresses->get($cityId)->random();
59
60
        return $address;
61
    }
62
63
    /**
64
     * Получить несколько случайных адресов
65
     *
66
     * @param int $count Кол-во требуемых адресов
67
     * @param null $forCity  Имя города, для которого генерировать адрес. По умолчанию null - из любого установленного
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $forCity is correct as it would always require null to be passed?
Loading history...
68
     * @return Collection
69
     */
70
    public function getRandomAddresses(int $count, $forCity = null): Collection
71
    {
72
        $addresses = new Collection();
73
74
        for ($i = 1; $i <= $count; $i++) {
75
            $addresses->push($this->getRandomAddress($forCity));
76
        }
77
78
        return $addresses;
79
    }
80
81
    /**
82
     * Добавить город в список, для которого будем генерировать адреса
83
     *
84
     * @param string $city
85
     * @return Generator
86
     * @throws CityNotFound Город не найден в списке доступных
87
     */
88
    public function addCity(string $city): Generator
89
    {
90
        $key = $this->getCityIdByName($city);
91
92
        if (!$this->cities->contains($city)) {
93
            $this->cities->put($key, $city);
94
        }
95
96
        return $this;
97
    }
98
99
    /**
100
     * Добавить несколько городо в список, для которого будем генерировать адреса
101
     *
102
     * @param array ...$cities
103
     * @return Generator
104
     */
105
    public function addCities(...$cities): Generator
106
    {
107
        foreach ($cities as $city) {
108
            if (!is_array($city)) {
109
                $city = [$city];
110
            }
111
            foreach ($city as $item) {
112
                $this->addCity($item);
113
            }
114
        }
115
116
        return $this;
117
    }
118
119
    /**
120
     * Установить список городов, для которого будем генерировать адреса
121
     *
122
     * @param array ...$cities
123
     * @return Generator
124
     */
125
    public function setCities(...$cities): Generator
126
    {
127
        $this->clearCities();
128
129
        if (sizeof($cities) === 1 && is_array($cities[0])) {
130
            $cities = $cities[0];
131
        }
132
133
        $this->addCities($cities);
134
135
        return $this;
136
    }
137
138
    /**
139
     * Очистить список гордов, для которых можно генерировать адреса
140
     *
141
     * @return Generator
142
     */
143
    public function clearCities(): Generator
144
    {
145
        $this->cities = new Collection();
146
147
        return $this;
148
    }
149
150
    /**
151
     * Получить коллекцию городов, для которых можно получать адреса.
152
     *
153
     * Если города заданы, то их. Если нет, то все доступные города.
154
     *
155
     * @return Collection
156
     */
157
    public function getCities(): Collection
158
    {
159
        return $this->cities->isEmpty() ? $this->availableCities : $this->cities;
160
    }
161
162
    /**
163
     * Получить имена городов, установленные для которых можно получать адреса
164
     *
165
     * @return Collection
166
     */
167
    public function getCityNames(): Collection
168
    {
169
        return $this->cities->values();
170
    }
171
172
    /**
173
     * Получить ID города по его имени
174
     *
175
     * @param string $name
176
     * @return int
177
     * @throws CityNotFound
178
     */
179
    protected function getCityIdByName(string $name): int
180
    {
181
        $key = $this->searchableCityNames->get(Helper::prepare($name));
182
183
        if (empty($key)) {
184
            throw new CityNotFound();
185
        }
186
187
        return $key;
188
    }
189
190
    /**
191
     * Генерируем коллекцию всех доступных адресов
192
     */
193
    private function makeAddresses(): void
194
    {
195
        $this->availableAddresses = new Collection();
196
197
        foreach ($this->availableCities as $key => $city) {
198
            $rawData = include('data/ru/' . $key . '.php');
199
            $addresses = new Collection();
200
201
            foreach ($rawData as $street => $buildings) {
202
                foreach ($buildings as $building) {
203
                    $address = new Address($city, $street, $building);
204
                    $addresses->push($address);
205
                }
206
            }
207
208
            $this->availableAddresses->put($key, $addresses);
209
        }
210
    }
211
212
    /**
213
     * Генерирум коллекцию всех доступных городов
214
     */
215
    private function makeCities(): void
216
    {
217
        $this->availableCities = new Collection();
218
219
        $this->searchableCityNames = new Collection();
220
221
        foreach (include('data/cities.php') as $key => $items) {
222
223
            $this->availableCities->put($key, $items[0]);
224
225
            foreach ($items as $item) {
226
                $item = Helper::prepare($item);
227
228
                if (!$this->searchableCityNames->contains($item)) {
229
                    $this->searchableCityNames->put($item, $key);
230
                }
231
            }
232
        }
233
    }
234
}