Passed
Push — master ( 9a6e88...b49093 )
by Denis
03:14
created

Generator::getAllAddresses()   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
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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
     * @var Collection Список городов, для которых сгенерированы адреса
33
     */
34
    protected $usedCities;
35
36
    /**
37
     * Generator constructor.
38
     */
39
    public function __construct()
40
    {
41
        $this->cities = new Collection();
42
43
        $this->usedCities = new Collection();
44
45
        $this->availableAddresses = new Collection();
46
47
        $this->makeCities();
48
    }
49
50
    /**
51
     * Получить случайный адрес
52
     *
53
     * @param string|null $forCity Имя города, для которого генерировать адрес. По умолчанию null - из любого установленного
54
     * @return Address
55
     * @throws CityNotFound Город не найден в списке доступных
56
     */
57
    public function getRandomAddress($forCity = null): Address
58
    {
59
        $forCity = $forCity ?: $this->getCities()->random();
60
61
        $forCity = Helper::prepare($forCity);
62
63
        $cityId = $this->getCityIdByName($forCity);
64
65
        if ($this->usedCities->contains($cityId) === false) {
66
            $this->makeAddresses($cityId);
67
        }
68
69
        $address = $this->availableAddresses->get($cityId)->random();
70
71
        return $address;
72
    }
73
74
    /**
75
     * Получить все сгенированные адреса
76
     *
77
     * @return Collection
78
     */
79
    public function getAllAddresses(): Collection
80
    {
81
        return $this->availableAddresses;
82
    }
83
84
    /**
85
     * Получить несколько случайных адресов
86
     *
87
     * @param int $count Кол-во требуемых адресов
88
     * @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...
89
     * @return Collection
90
     */
91
    public function getRandomAddresses(int $count, $forCity = null): Collection
92
    {
93
        $addresses = new Collection();
94
95
        for ($i = 1; $i <= $count; $i++) {
96
            $addresses->push($this->getRandomAddress($forCity));
97
        }
98
99
        return $addresses;
100
    }
101
102
    /**
103
     * Добавить город в список, для которого будем генерировать адреса
104
     *
105
     * @param string $city
106
     * @return Generator
107
     * @throws CityNotFound Город не найден в списке доступных
108
     */
109
    public function addCity(string $city): Generator
110
    {
111
        $key = $this->getCityIdByName($city);
112
113
        if (!$this->cities->contains($city)) {
114
            $this->cities->put($key, $city);
115
        }
116
117
        return $this;
118
    }
119
120
    /**
121
     * Добавить несколько городо в список, для которого будем генерировать адреса
122
     *
123
     * @param array ...$cities
124
     * @return Generator
125
     */
126
    public function addCities(...$cities): Generator
127
    {
128
        foreach ($cities as $city) {
129
            if (!is_array($city)) {
130
                $city = [$city];
131
            }
132
            foreach ($city as $item) {
133
                $this->addCity($item);
134
            }
135
        }
136
137
        return $this;
138
    }
139
140
    /**
141
     * Установить список городов, для которого будем генерировать адреса
142
     *
143
     * @param array ...$cities
144
     * @return Generator
145
     */
146
    public function setCities(...$cities): Generator
147
    {
148
        $this->clearCities();
149
150
        if (sizeof($cities) === 1 && is_array($cities[0])) {
151
            $cities = $cities[0];
152
        }
153
154
        $this->addCities($cities);
155
156
        return $this;
157
    }
158
159
    /**
160
     * Очистить список гордов, для которых можно генерировать адреса
161
     *
162
     * @return Generator
163
     */
164
    public function clearCities(): Generator
165
    {
166
        $this->cities = new Collection();
167
168
        return $this;
169
    }
170
171
    /**
172
     * Очистить список сгенерированных адресов
173
     *
174
     * @return Generator
175
     */
176
    public function clearAddresses(): Generator
177
    {
178
        $this->availableAddresses = new Collection();
179
180
        $this->usedCities = new Collection();
181
182
        return $this;
183
    }
184
185
    /**
186
     * Получить коллекцию городов, для которых можно получать адреса.
187
     *
188
     * Если города заданы, то их. Если нет, то все доступные города.
189
     *
190
     * @return Collection
191
     */
192
    public function getCities(): Collection
193
    {
194
        return $this->cities->isEmpty() ? $this->availableCities : $this->cities;
195
    }
196
197
    /**
198
     * Получить имена городов, установленные для которых можно получать адреса
199
     *
200
     * @return Collection
201
     */
202
    public function getCityNames(): Collection
203
    {
204
        return $this->cities->values();
205
    }
206
207
    /**
208
     * Получить ID города по его имени
209
     *
210
     * @param string $name
211
     * @return int
212
     * @throws CityNotFound
213
     */
214
    protected function getCityIdByName(string $name): int
215
    {
216
        $key = $this->searchableCityNames->get(Helper::prepare($name));
217
218
        if (empty($key)) {
219
            throw new CityNotFound();
220
        }
221
222
        return $key;
223
    }
224
225
    /**
226
     * Генерируем коллекцию всех доступных адресов для указанного города
227
     *
228
     * @param int $cityId
229
     */
230
    private function makeAddresses(int $cityId): void
231
    {
232
        $city = $this->availableCities->get($cityId);
233
234
        $rawData = include('data/ru/' . $cityId . '.php');
235
        $addresses = new Collection();
236
237
        foreach ($rawData as $street => $buildings) {
238
            foreach ($buildings as $building) {
239
                $address = new Address($city, $street, $building);
240
                $addresses->push($address);
241
            }
242
        }
243
244
        $this->usedCities->push($cityId);
245
246
        $this->availableAddresses->put($cityId, $addresses);
247
    }
248
249
    /**
250
     * Генерирум коллекцию всех доступных городов
251
     */
252
    private function makeCities(): void
253
    {
254
        $this->availableCities = new Collection();
255
256
        $this->searchableCityNames = new Collection();
257
258
        foreach (include('data/cities.php') as $key => $items) {
259
260
            $this->availableCities->put($key, $items[0]);
261
262
            foreach ($items as $item) {
263
                $item = Helper::prepare($item);
264
265
                if (!$this->searchableCityNames->contains($item)) {
266
                    $this->searchableCityNames->put($item, $key);
267
                }
268
            }
269
        }
270
    }
271
}