@whiteslove/parsing-lexicon 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/index.d.ts +375 -0
  4. package/package.json +75 -0
  5. package/src/central-asia-locations.js +211 -0
  6. package/src/central-asia.js +233 -0
  7. package/src/contact.d.ts +44 -0
  8. package/src/contact.js +159 -0
  9. package/src/countries.js +175 -0
  10. package/src/country-context.d.ts +10 -0
  11. package/src/country-context.js +22 -0
  12. package/src/currency.d.ts +14 -0
  13. package/src/currency.js +66 -0
  14. package/src/geo.js +169 -0
  15. package/src/geography-central-asia.js +42 -0
  16. package/src/geography-detection.d.ts +14 -0
  17. package/src/geography-detection.js +64 -0
  18. package/src/geography-display.d.ts +13 -0
  19. package/src/geography-display.js +113 -0
  20. package/src/geography.js +210 -0
  21. package/src/hiring-advanced.js +147 -0
  22. package/src/hiring-candidate-fields.d.ts +9 -0
  23. package/src/hiring-candidate-fields.js +92 -0
  24. package/src/hiring-context.d.ts +64 -0
  25. package/src/hiring-context.js +412 -0
  26. package/src/hiring-language-extensions.d.ts +19 -0
  27. package/src/hiring-language-extensions.js +139 -0
  28. package/src/hiring-languages.js +135 -0
  29. package/src/hiring-location-fields.d.ts +3 -0
  30. package/src/hiring-location-fields.js +53 -0
  31. package/src/hiring-professions-ro.js +191 -0
  32. package/src/hiring-professions.js +437 -0
  33. package/src/hiring-requirements.d.ts +16 -0
  34. package/src/hiring-requirements.js +170 -0
  35. package/src/hiring-salary-context.d.ts +27 -0
  36. package/src/hiring-salary-context.js +76 -0
  37. package/src/hiring-semantics.d.ts +29 -0
  38. package/src/hiring-semantics.js +218 -0
  39. package/src/hiring-skills.d.ts +21 -0
  40. package/src/hiring-skills.js +315 -0
  41. package/src/hiring-source-aliases.d.ts +32 -0
  42. package/src/hiring-source-aliases.js +186 -0
  43. package/src/hiring-source-semantics.d.ts +31 -0
  44. package/src/hiring-source-semantics.js +293 -0
  45. package/src/hiring-temporal.d.ts +15 -0
  46. package/src/hiring-temporal.js +67 -0
  47. package/src/hiring-vacancy-fields.d.ts +5 -0
  48. package/src/hiring-vacancy-fields.js +23 -0
  49. package/src/hiring-work-semantics.d.ts +34 -0
  50. package/src/hiring-work-semantics.js +72 -0
  51. package/src/hiring.js +180 -0
  52. package/src/housing-address.d.ts +18 -0
  53. package/src/housing-address.js +210 -0
  54. package/src/housing-context.d.ts +36 -0
  55. package/src/housing-context.js +183 -0
  56. package/src/housing-features.js +30 -0
  57. package/src/housing-intent.d.ts +9 -0
  58. package/src/housing-intent.js +132 -0
  59. package/src/housing-listing-fields.js +131 -0
  60. package/src/housing-money.d.ts +7 -0
  61. package/src/housing-money.js +102 -0
  62. package/src/housing-source-aliases.d.ts +8 -0
  63. package/src/housing-source-aliases.js +51 -0
  64. package/src/housing-structured.d.ts +55 -0
  65. package/src/housing-structured.js +219 -0
  66. package/src/housing.js +200 -0
  67. package/src/index.js +44 -0
  68. package/src/kz-location-extensions.js +307 -0
  69. package/src/landmarks.js +21 -0
  70. package/src/lexicon-core.js +58 -0
  71. package/src/location-merge.js +106 -0
  72. package/src/locations.js +456 -0
  73. package/src/money-core.d.ts +10 -0
  74. package/src/money-core.js +81 -0
  75. package/src/money-lexicon.d.ts +5 -0
  76. package/src/money-lexicon.js +79 -0
  77. package/src/money.js +154 -0
  78. package/src/normalization.js +384 -0
  79. package/src/odesa-metropolitan.js +145 -0
  80. package/src/romania-geography.js +47 -0
  81. package/src/tashkent-colloquial.js +72 -0
  82. package/src/tashkent-housing-geography.d.ts +38 -0
  83. package/src/tashkent-housing-geography.js +211 -0
  84. package/src/tashkent-pois.js +215 -0
  85. package/src/tashkent-residential-complexes.js +272 -0
  86. package/src/ua-location-extensions-major.js +118 -0
  87. package/src/ua-location-extensions-metro.js +9 -0
  88. package/src/ua-location-extensions-regional.js +246 -0
  89. package/src/ua-secondary-cities.d.ts +2 -0
  90. package/src/ua-secondary-cities.js +57 -0
  91. package/src/ukraine.js +75 -0
  92. package/src/uz-location-extensions.js +259 -0
@@ -0,0 +1,215 @@
1
+ import { aliasesToRegex } from './normalization.js';
2
+
3
+ function poi(name, category, aliases = [], options = {}) {
4
+ const all = [...new Set([name, ...aliases].filter(Boolean))];
5
+ return Object.freeze({
6
+ canonical: name,
7
+ name,
8
+ category,
9
+ categories: Object.freeze([...new Set([category, ...(options.categories || [])])]),
10
+ aliases: Object.freeze(all),
11
+ re: aliasesToRegex(all),
12
+ contextRequired: Boolean(options.contextRequired),
13
+ contextRe: options.context ? new RegExp(options.context, 'iu') : null,
14
+ });
15
+ }
16
+
17
+ const MALL_CONTEXT = '(?:mall|молл|трц|тц|торгов(?:ый|ого)\\s+центр|savdo\\s+markazi|shopping\\s+(?:center|centre))';
18
+
19
+ export const TASHKENT_PARKS = Object.freeze([
20
+ poi('Tashkent City Park', 'park', ['Ташкент Сити парк', 'Парк Tashkent City']),
21
+ poi('Magic City', 'park', ['Magic City Park', 'Magic Park', 'Мэджик Сити']),
22
+ poi('Ecopark', 'park', ['Eco Park', 'Экопарк', 'Центральный экопарк']),
23
+ poi('Central Park Mirzo Ulugbek', 'park', ['Центральный парк имени Мирзо Улугбека', 'Центральный парк', 'Central Park', 'Парк Мирзо Улугбека']),
24
+ poi('Japanese Garden', 'park', ['Японский сад', "Yapon bog'i", 'Yapon bog‘i', 'Yapon bogʻI']),
25
+ poi('Milliy Bog Park', 'park', ['Миллий бог', "Milliy Bog'", 'Milliy Bog‘', 'Milliy Bogʻ', 'Национальный парк'], { contextRequired: true, context: '(?:парк|bog|боғ|park|national)' }),
26
+ poi('Alisher Navoi National Park', 'park', ['Парк имени Алишера Навои']),
27
+ poi('Dream Park', 'park', ['Dream Park имени Гафура Гуляма', 'Парк имени Гафура Гуляма', 'Парк Гафура Гуляма']),
28
+ poi('Anhor Park', 'park', ['Anhor', 'Анхор']),
29
+ poi('Lokomotiv Park', 'park', ['Anhor Lokomotiv', 'Анхор Локомотив', 'Парк Локомотив']),
30
+ poi('Tashkentland', 'park', ['Ташкентленд']),
31
+ poi('Victory Park', 'park', ['Парк Победы', "G'alaba Bog'i", 'G‘alaba Bog‘i', 'Gʻalaba Bogʻi']),
32
+ poi('Ashgabat Park', 'park', ['Ашхабад парк', 'Ashxobod Park']),
33
+ poi('Dostlik Park', 'park', ['Парк Дустлик', "Do'stlik Park", 'Do‘stlik Park', 'Doʻstlik Park']),
34
+ poi('Navruz Park', 'park', ['Парк Навруз']),
35
+ poi('Bobur Park', 'park', ['Парк Бабура', 'Парк Бобура', "Bobur bog'i", 'Bobur bog‘i']),
36
+ poi('Furqat Park', 'park', ['Парк Фурката']),
37
+ poi('Yakub Kolas Park', 'park', ['Парк Якуба Коласа', 'Парк имени Якуба Коласа']),
38
+ poi('Friendship of Peoples Park', 'park', ['Парк Дружбы народов']),
39
+ poi('Yangi Ozbekiston Park', 'park', ["Yangi O'zbekiston Bog'i", 'Yangi O‘zbekiston Bog‘i', 'Парк Новый Узбекистан', 'Новый Узбекистан', "Yangi O'zbekiston Park"]),
40
+ ]);
41
+
42
+ export const TASHKENT_SQUARES = Object.freeze([
43
+ poi('Amir Timur Square', 'square', ['Площадь Амира Темура', 'Amir Temur Square', 'Сквер Амира Темура', 'Сквер']),
44
+ poi('Independence Square', 'square', ['Площадь Независимости', 'Mustaqillik Maydoni', 'Mustaqillik Square', 'Площадь Мустакиллик', 'Мустақиллик майдони']),
45
+ poi('Friendship of Peoples Square', 'square', ['Площадь Дружбы народов']),
46
+ poi('Khadra', 'square', ['Хадра', 'Xadra']),
47
+ poi('Broadway Sayilgoh', 'square', ['Broadway', 'Бродвей', 'Сайилгох', 'Sayilgoh']),
48
+ ]);
49
+
50
+ export const TASHKENT_MARKETS = Object.freeze([
51
+ poi('Chorsu Bazaar', 'market', ['Чорсу', 'Chorsu Bazaar', 'Chorsu bozori', 'базар Чорсу', 'Чорсу бозори']),
52
+ poi('Eski Juva Bazaar', 'market', ['Эски Жува', 'Eski Juva']),
53
+ poi('Alay Bazaar', 'market', ['Алайский рынок', 'Алайский базар', 'Oloy bozori', 'Олой бозори']),
54
+ poi('Qoyliq Bazaar', 'market', ['Куйлюк базар', 'Куйлик базар', "Qo'yliq bozori", 'Qo‘yliq bozori', 'Qoʻyliq bozori']),
55
+ poi('Yunusobod Bazaar', 'market', ['Юнусабадский рынок', 'Yunusobod bozori']),
56
+ poi('Farhod Bazaar', 'market', ['Фархадский рынок', 'Фархадский базар', 'Farhod bozori']),
57
+ poi('Uch Qahramon Bazaar', 'market', ['Уч Кахрамон', 'Уч Кахрамон базар']),
58
+ poi('Katartal Bazaar', 'market', ['Катартал', 'Катартал базар']),
59
+ poi('Karakamysh Bazaar', 'market', ['Каракамышский рынок']),
60
+ poi('Parkent Bazaar', 'market', ['Паркентский рынок', 'Parkent bozori']),
61
+ poi('Mirobod Bazaar', 'market', ['Мирабадский рынок', 'Госпитальный рынок', 'Mirobod bozori']),
62
+ poi('Sergeli Bazaar', 'market', ['Сергели рынок', 'Сергели базар']),
63
+ poi('Bek Baraka', 'market', ['Бек Барака']),
64
+ poi('Ippodrom Bazaar', 'market', ['Ипподром']),
65
+ poi('Abu Sahiy', 'market', ['Абу Сахий']),
66
+ poi('Orikzor Bazaar', 'market', ['Урикзор', "O'rikzor", 'O‘rikzor', 'Oʻrikzor']),
67
+ poi('Kadysheva Bazaar', 'market', ['Кадышева рынок', 'Кадышева базар']),
68
+ poi('Yangiobod Bazaar', 'market', ['Янгиабадский рынок', 'Янгиабад', 'Yangiobod bozori']),
69
+ ]);
70
+
71
+ export const TASHKENT_MALLS = Object.freeze([
72
+ poi('Tashkent City Mall', 'mall', ['Ташкент Сити Молл']),
73
+ poi('Samarqand Darvoza', 'mall', ['Самарканд Дарвоза']),
74
+ poi('Compass Mall', 'mall', ['Compass'], { contextRequired: true, context: MALL_CONTEXT }),
75
+ poi('Mega Planet', 'mall', ['MegaPlanet']),
76
+ poi('Riviera Mall', 'mall', ['Riviera'], { contextRequired: true, context: MALL_CONTEXT }),
77
+ poi('NEXT Mall', 'mall', ['Next', 'NEXT'], { contextRequired: true, context: MALL_CONTEXT }),
78
+ poi('Atlas Mall', 'mall', ['Atlas'], { contextRequired: true, context: MALL_CONTEXT }),
79
+ poi('Parus Mall', 'mall', ['Parus'], { contextRequired: true, context: MALL_CONTEXT }),
80
+ poi('Depo Mall', 'mall', ['Depo'], { contextRequired: true, context: MALL_CONTEXT }),
81
+ poi('Vega Centre', 'mall', ['Vega Center']),
82
+ poi('Yunusabad Gallery', 'mall'),
83
+ poi('Poytaxt Mall', 'mall', ['Poytaxt'], { contextRequired: true, context: MALL_CONTEXT }),
84
+ poi('Alfraganus Mall', 'mall', ['Alfraganus'], { contextRequired: true, context: MALL_CONTEXT }),
85
+ poi('HT Mall', 'mall'),
86
+ poi('Seoul Mun Mall', 'mall', ['Seoul Mun'], { contextRequired: true, context: MALL_CONTEXT }),
87
+ poi('Ecobozor', 'mall', ['Eco Bozor']),
88
+ ]);
89
+
90
+ export const TASHKENT_ATTRACTIONS = Object.freeze([
91
+ poi('Tashkent TV Tower', 'attraction', ['Телебашня', 'Ташкентская телебашня']),
92
+ poi('Minor Mosque', 'religious', ['Мечеть Минор', 'Minor masjidi', 'Минор'], { contextRequired: true, context: '(?:мечет|mosque|masjid|масжид)' }),
93
+ poi('Hazrati Imam', 'attraction', ['Хазрати Имам', 'Хаст Имам', 'Hast Imam', 'Khazrati Imam Complex']),
94
+ poi('Kaffal Shashi Mausoleum', 'religious', ['Мавзолей Каффаля Шаши']),
95
+ poi('Barak-Khan Madrasa', 'religious', ['Медресе Баракхан', 'Barak Khan Madrasa']),
96
+ poi('Kukeldash Madrasa', 'religious', ['Медресе Кукельдаш']),
97
+ poi('Khoja Ahrar Vali Mosque', 'religious', ['Мечеть Ходжа Ахрар Вали']),
98
+ poi('Sacred Heart Cathedral', 'religious', ['Собор Святейшего Сердца Иисуса', 'Католический костёл']),
99
+ poi('Holy Assumption Cathedral', 'religious', ['Успенский собор']),
100
+ poi('Sheikh Zayniddin Mosque', 'religious', ['Мечеть Шейха Зайниддина']),
101
+ poi('Suzuk Ota', 'attraction', ['Сузук Ота', 'Комплекс Сузук Ота']),
102
+ poi('Ming Urik Archaeological Site', 'attraction', ['Минг Урик', "Ming O'rik archaeological site", 'Ming Urik'], { contextRequired: true, context: '(?:археолог|archaeolog|site|городищ|комплекс)' }),
103
+ ]);
104
+
105
+ export const TASHKENT_CULTURAL_POIS = Object.freeze([
106
+ poi('Amir Timur Museum', 'museum', ['Государственный музей истории Тимуридов', 'Музей Амира Темура', 'Museum of the Temurids']),
107
+ poi('State Museum of History of Uzbekistan', 'museum', ['Государственный музей истории Узбекистана']),
108
+ poi('Museum of Arts of Uzbekistan', 'museum', ['Государственный музей искусств Узбекистана']),
109
+ poi('Museum of Applied Arts', 'museum', ['Музей прикладного искусства']),
110
+ poi('Railway Museum', 'museum', ['Музей железнодорожной техники']),
111
+ poi('Museum of Olympic Glory', 'museum', ['Музей Олимпийской славы']),
112
+ poi('Tamara Khanum Museum', 'museum', ['Дом-музей Тамары Ханум']),
113
+ poi('Alisher Navoi Museum of Literature', 'museum', ['Музей литературы Алишера Навои']),
114
+ poi('Art Gallery of Uzbekistan', 'museum', ['Государственная галерея искусств']),
115
+ poi('Alisher Navoi Theatre', 'culture', ['Театр имени Алишера Навои', 'Большой театр Навои']),
116
+ poi('Xalqlar Dostligi Palace', 'culture', ['Дворец Дружбы народов', "Xalqlar Do'stligi Palace", 'Xalqlar Do‘stligi Palace']),
117
+ poi('Istiqlol Palace', 'culture', ['Дворец искусств Истиклол']),
118
+ poi('Dom Kino', 'culture', ['Дом кино']),
119
+ poi('Panoramic Cinema', 'culture', ['Панорамный кинотеатр']),
120
+ poi('Alley of Writers', 'culture', ['Аллея литераторов']),
121
+ poi('Tashkent Chimes', 'culture', ['Куранты', 'Ташкентские куранты']),
122
+ ]);
123
+
124
+ export const TASHKENT_TRANSPORT_POIS = Object.freeze([
125
+ poi('Tashkent International Airport', 'airport', ['Международный аэропорт Ташкент', 'Аэропорт имени Ислама Каримова', 'Международный аэропорт имени Ислама Каримова', 'Tashkent Airport', 'Toshkent aeroporti']),
126
+ poi('Tashkent Domestic Airport', 'airport', ['Аэропорт местных авиалиний', 'Аэропорт внутренних рейсов']),
127
+ poi('Tashkent Central Railway Station', 'railway', ['Северный вокзал', 'Ташкент Северный', 'Toshkent Markaziy', 'Центральный вокзал', 'Ташкент Северный вокзал']),
128
+ poi('Tashkent South Railway Station', 'railway', ['Южный вокзал', 'Ташкент Южный', 'Toshkent Janubiy', 'Ташкент Южный вокзал']),
129
+ poi('Tashkent Bus Station', 'bus', ['Автовокзал Ташкент']),
130
+ ]);
131
+
132
+ const TASHKENT_MEDICAL_ACADEMY = poi('Tashkent Medical Academy', 'university', ['ТМА', 'Ташкентская медицинская академия'], { categories: ['medical'] });
133
+
134
+ export const TASHKENT_UNIVERSITIES = Object.freeze([
135
+ poi('National University of Uzbekistan', 'university', ['Национальный университет Узбекистана', 'NUUz', "O'zMU", 'O‘zMU', 'OʻzMU']),
136
+ poi('University of World Economy and Diplomacy', 'university', ['Университет мировой экономики и дипломатии', 'UWED']),
137
+ poi('Westminster International University in Tashkent', 'university', ['WIUT', 'Вестминстер']),
138
+ poi('Turin Polytechnic University in Tashkent', 'university', ['Turin Polytechnic University', 'Туринский политех']),
139
+ poi('INHA University in Tashkent', 'university', ['INHA', 'Университет Инха']),
140
+ poi('Tashkent State Technical University', 'university', ['ТашГТУ', 'ТГТУ']),
141
+ poi('Tashkent State University of Economics', 'university', ['ТГЭУ', 'Ташкентский государственный экономический университет']),
142
+ poi('Tashkent State University of Law', 'university', ['ТГЮУ', 'Ташкентский государственный юридический университет']),
143
+ TASHKENT_MEDICAL_ACADEMY,
144
+ poi('Tashkent University of Information Technologies', 'university', ['TUIT', 'ТУИТ']),
145
+ poi('Webster University Tashkent', 'university', ['Webster']),
146
+ poi('TEAM University', 'university'),
147
+ poi('Kimyo International University', 'university', ['Yeoju']),
148
+ poi('MDIS Tashkent', 'university'),
149
+ poi('Ajou University in Tashkent', 'university', ['ADJU']),
150
+ poi('New Uzbekistan University', 'university', ['Новый университет Узбекистана']),
151
+ ]);
152
+
153
+ export const TASHKENT_MEDICAL_POIS = Object.freeze([
154
+ TASHKENT_MEDICAL_ACADEMY,
155
+ poi('Tashkent City Hospital No. 1', 'medical', ['1-я городская больница']),
156
+ poi('Tashkent City Hospital No. 4', 'medical', ['4-я городская больница']),
157
+ poi('Tashkent City Hospital No. 5', 'medical', ['5-я городская больница']),
158
+ poi('Tashkent City Hospital No. 7', 'medical', ['7-я городская больница']),
159
+ poi('Tashkent City Hospital No. 16', 'medical', ['16-я городская больница', '16-я больница']),
160
+ poi('Republican Oncology Center', 'medical', ['Республиканский онкоцентр', 'Онкология']),
161
+ poi('Republican Cardiology Center', 'medical', ['Республиканский кардиоцентр', 'Кардиоцентр']),
162
+ poi('Republican Emergency Medical Center', 'medical', ['Республиканский центр экстренной медицинской помощи']),
163
+ poi('Republican Perinatal Center', 'medical', ['Республиканский перинатальный центр', 'Перинатальный центр']),
164
+ poi('Institute of Obstetrics and Gynecology', 'medical', ['Институт акушерства и гинекологии']),
165
+ ]);
166
+
167
+ export const TASHKENT_LEGACY_LANDMARKS = Object.freeze([
168
+ poi('TSUM', 'legacy', ['ЦУМ']),
169
+ poi('Main Post Office', 'legacy', ['Главпочтамт']),
170
+ poi('GUM', 'legacy', ['ГУМ']),
171
+ ]);
172
+
173
+ export const TASHKENT_POI_GROUPS = Object.freeze({
174
+ parks: TASHKENT_PARKS,
175
+ squares: TASHKENT_SQUARES,
176
+ markets: TASHKENT_MARKETS,
177
+ malls: TASHKENT_MALLS,
178
+ attractions: TASHKENT_ATTRACTIONS,
179
+ culture: TASHKENT_CULTURAL_POIS,
180
+ transport: TASHKENT_TRANSPORT_POIS,
181
+ universities: TASHKENT_UNIVERSITIES,
182
+ medical: TASHKENT_MEDICAL_POIS,
183
+ legacy: TASHKENT_LEGACY_LANDMARKS,
184
+ });
185
+
186
+ const seen = new Set();
187
+ export const TASHKENT_LANDMARKS = Object.freeze(Object.values(TASHKENT_POI_GROUPS).flat().filter((entry) => {
188
+ const key = entry.name;
189
+ if (seen.has(key)) return false;
190
+ seen.add(key);
191
+ return true;
192
+ }));
193
+
194
+ function hasRequiredContext(entry, text, start, end) {
195
+ if (!entry.contextRequired) return true;
196
+ const around = text.slice(Math.max(0, start - 48), Math.min(text.length, end + 48));
197
+ return entry.contextRe?.test(around) ?? false;
198
+ }
199
+
200
+ export function matchTashkentPoi(value, category = null) {
201
+ const text = String(value ?? '');
202
+ if (!text) return null;
203
+ const catalog = category ? (TASHKENT_POI_GROUPS[category] || []) : TASHKENT_LANDMARKS;
204
+ const matches = [];
205
+ for (const entry of catalog) {
206
+ const match = text.match(entry.re);
207
+ if (!match) continue;
208
+ const start = match.index ?? 0;
209
+ const end = start + match[0].length;
210
+ if (!hasRequiredContext(entry, text, start, end)) continue;
211
+ matches.push({ entry, start, length: match[0].trim().length });
212
+ }
213
+ matches.sort((a, b) => b.length - a.length || a.start - b.start);
214
+ return matches[0]?.entry ?? null;
215
+ }
@@ -0,0 +1,272 @@
1
+ import { aliasesToRegex, findCanonical } from './normalization.js';
2
+
3
+ const AMBIGUOUS_TASHKENT_COMPLEXES = new Set([
4
+ 'Amir Temur',
5
+ 'Bodomzor',
6
+ 'City Mall',
7
+ 'Darhan',
8
+ 'Pushkin',
9
+ ]);
10
+
11
+ function complex(name, aliases = []) {
12
+ const all = [...new Set([name, ...aliases].filter(Boolean))];
13
+ return Object.freeze({
14
+ canonical: name,
15
+ name,
16
+ aliases: Object.freeze(all),
17
+ ambiguous: AMBIGUOUS_TASHKENT_COMPLEXES.has(name),
18
+ re: aliasesToRegex(all),
19
+ });
20
+ }
21
+
22
+ export const TASHKENT_RESIDENTIAL_COMPLEXES = Object.freeze([
23
+ complex('AKAY CITY', ['Акай Сити']),
24
+ complex('Albero'),
25
+ complex('Alfraganus'),
26
+ complex('Amir Temur'),
27
+ complex('Anhor Residence'),
28
+ complex('Anor Development'),
29
+ complex('ARNASAY'),
30
+ complex('Askiya City'),
31
+ complex('Asia House', ['Азиа Хаус', 'Азия Хаус']),
32
+ complex('Assalom Bog\'lar'),
33
+ complex('Assalom Do\'stlik'),
34
+ complex('Assalom Havo'),
35
+ complex('Assalom Maxtumquli'),
36
+ complex('Assalom Sohil', ['Ассалом Сохил']),
37
+ complex('Aviasozlar Plaza'),
38
+ complex('BASHKENT'),
39
+ complex('BASHKENT Mening orzuyim'),
40
+ complex('Baurum'),
41
+ complex('Bayterak'),
42
+ complex('Bi Sado'),
43
+ complex('Binkat', ['Бинкат']),
44
+ complex('Black Tower'),
45
+ complex('Bobur Residence'),
46
+ complex('Bodomzor'),
47
+ complex('Botanika Saroyi', ['Ботаника Саройи']),
48
+ complex('Boulevard', ['Boulevard Residence', 'Бульвар', 'Boulvard']),
49
+ complex('Bridge'),
50
+ complex('Brooklyn', ['Бруклин']),
51
+ complex('Cambridge Residence', ['Кембридж Резиденс']),
52
+ complex('Caravan Avenue'),
53
+ complex('Celebrity Residence'),
54
+ complex('Central Plaza'),
55
+ complex('Charh Novza'),
56
+ complex('Chimgan Hills'),
57
+ complex('City Group Tower'),
58
+ complex('City Life'),
59
+ complex('City Mall'),
60
+ complex('Comfort House', ['Комфорт Хаус']),
61
+ complex('Darhan', ['Darkhan Residence', 'Дархан Резиденс', 'Дархан', 'Darkhan']),
62
+ complex('DARVOZA'),
63
+ complex('Dostlar', ['Do‘stlar', 'Do\'stlar', 'Doʻstlar', 'Дустлар', 'Дўстлар', 'Дустлар ЖК']),
64
+ complex('Dream House', ['Дрим-Хаус', 'Дрим Хаус']),
65
+ complex('Dreamland Aeroport'),
66
+ complex('Dreamland Do\'stlik'),
67
+ complex('Dreamland Parkent'),
68
+ complex('ECO HOUSE'),
69
+ complex('Eco Residence'),
70
+ complex('Eco Smart'),
71
+ complex('Elegant'),
72
+ complex('Ellipse Garden Darhan'),
73
+ complex('Etalon'),
74
+ complex('Family House'),
75
+ complex('Fazo Residents'),
76
+ complex('Flagman'),
77
+ complex('Gardens', ['Gardens Residence', 'Гарденс Резиденс', 'Гарденс']),
78
+ complex('Glinka Premium'),
79
+ complex('Golden Lake Residence'),
80
+ complex('Grand Akkurgan'),
81
+ complex('Grand City'),
82
+ complex('Green Park'),
83
+ complex('Greenpark Bo\'z Suv'),
84
+ complex('Greenwich', ['Гринвич']),
85
+ complex('Harizma'),
86
+ complex('High Town'),
87
+ complex('Hillmar'),
88
+ complex('IKAT'),
89
+ complex('Imperial Club City'),
90
+ complex('Istanbul City', ['Истанбул Сити', 'Истамбул Сити']),
91
+ complex('Jomiy Residence'),
92
+ complex('Kamron Palace'),
93
+ complex('Kiparis'),
94
+ complex('Koh Ota'),
95
+ complex('Kushon'),
96
+ complex('LAFAYETTE'),
97
+ complex('Loft Residence'),
98
+ complex('Luminar House'),
99
+ complex('Maljaan Residence'),
100
+ complex('MANHATTAN'),
101
+ complex('Manzara', ['Манзара']),
102
+ complex('Mashxadi Residence'),
103
+ complex('Mavera Town'),
104
+ complex('Mavrid mavzesi'),
105
+ complex('Mavsum'),
106
+ complex('Mega Dom'),
107
+ complex('MEHRIBON'),
108
+ complex('Mening Uyim'),
109
+ complex('Meridian'),
110
+ complex('METROPOL'),
111
+ complex('Milano'),
112
+ complex('Minar'),
113
+ complex('Ming Chinor'),
114
+ complex('MIRABAD PALACE'),
115
+ complex('Mirabad Avenue', ['Мирабад Авеню']),
116
+ complex('Mirabad City', ['Мирабад Сити']),
117
+ complex('MIRADOR'),
118
+ complex('Modera Towers', ['Модера Товерс']),
119
+ complex('Moderno'),
120
+ complex('Muhtasham'),
121
+ complex('Musaffo'),
122
+ complex('Musaffo Maskan', ['Муссафо Маскан']),
123
+ complex('Navruz'),
124
+ complex('Neo House'),
125
+ complex('NEONIT'),
126
+ complex('New Life'),
127
+ complex('New Port'),
128
+ complex('Nice Villas'),
129
+ complex('Nikitina Residence'),
130
+ complex('NOVDAR'),
131
+ complex('NRG Hayot'),
132
+ complex('NRG Jomiy'),
133
+ complex('NRG Maftun Makon'),
134
+ complex('NRG Meros'),
135
+ complex('NRG Mirzo-Ulugbek'),
136
+ complex('NRG Oybek', ['NRG Ойбек', 'НРГ Ойбек']),
137
+ complex('NRG Park'),
138
+ complex('NRG Qorasuv'),
139
+ complex('NRG U-Tower', ['U Tower', 'U-Tower', 'Ю Тауэр', 'НРГ Ю Тауэр']),
140
+ complex('NRG VOHA'),
141
+ complex('NRG Zamon'),
142
+ complex('Nukus Avenue', ['Нукус Авеню']),
143
+ complex('Nur'),
144
+ complex('Nur Hayot'),
145
+ complex('Nur Namuna'),
146
+ complex('Ocean'),
147
+ complex('Ocean Xon Saroy', ['Xon Saroy Ocean']),
148
+ complex('Obod Maskan'),
149
+ complex('Obi Hayot'),
150
+ complex('Olmos Residence'),
151
+ complex('Olmazor City', ['Алмазар Сити', 'Олмазор Сити']),
152
+ complex('Orzu'),
153
+ complex('OQSAROY', ['ОК САРОЙ', 'Оксарой', 'Oq Saroy', 'Oq-Saroy']),
154
+ complex('O\'zbegim', ['Узбегим', 'O‘zbegim', 'Oʻzbegim', 'Ozbegim']),
155
+ complex('O\'z Mahal', ['Озмахал', 'Узмахал', 'O‘z Mahal', 'Oʻz Mahal', 'Oz Mahal']),
156
+ complex('O\'z Makon'),
157
+ complex('Oz Zamin'),
158
+ complex('Paradise House'),
159
+ complex('Parisien', ['Парисьен']),
160
+ complex('Park City Labzak'),
161
+ complex('Park Residence'),
162
+ complex('Parkent Avenue', ['Паркент Авеню']),
163
+ complex('Parkent Plaza'),
164
+ complex('PARKWOOD'),
165
+ complex('Parlament'),
166
+ complex('Piramit Tower', ['Пирамит Товер', 'Пирамид', 'Pyramid Tower']),
167
+ complex('Poytaht Gavhari'),
168
+ complex('Poytaxt Residence', ['Пойтахт Резиденс', 'Пойтахт Ресиденс']),
169
+ complex('Prestige Gardens'),
170
+ complex('Pushkin'),
171
+ complex('Qadriyat'),
172
+ complex('Qorasuv Plaza'),
173
+ complex('Qorasuv River Residence', ['Карасу Риверс']),
174
+ complex('Regnum Plaza'),
175
+ complex('Renaissance'),
176
+ complex('Resim Tashkent'),
177
+ complex('River Park'),
178
+ complex('Riverside'),
179
+ complex('Riviera', ['Ривьера']),
180
+ complex('Royal House'),
181
+ complex('SAADIYAT'),
182
+ complex('Sado Business'),
183
+ complex('SAF Towers'),
184
+ complex('Salom Qoyliq'),
185
+ complex('Salamatina'),
186
+ complex('Sapphire Terrace'),
187
+ complex('Sayram Avenue'),
188
+ complex('Sayram Plaza'),
189
+ complex('Sayram Tower'),
190
+ complex('Seoul Mun', ['Сеул Мун']),
191
+ complex('Seoul Riverside'),
192
+ complex('Shahriabad'),
193
+ complex('Shohsaroy Towers'),
194
+ complex('Shoshkent'),
195
+ complex('Silk Road'),
196
+ complex('Silk Road Apartments'),
197
+ complex('Silk Way'),
198
+ complex('Silver Tower'),
199
+ complex('Skyline'),
200
+ complex('Sokin Diyor'),
201
+ complex('Solaris', ['Солярис', 'Саларис']),
202
+ complex('Stellar Residence'),
203
+ complex('Sunrise'),
204
+ complex('Tashkent City Gardens'),
205
+ complex('Temur Malik'),
206
+ complex('Tiara Residence'),
207
+ complex('Tower Up'),
208
+ complex('Trinity'),
209
+ complex('Twins'),
210
+ complex('Uchtepa Avenue'),
211
+ complex('VEGAS TOWER', ['Вегас Товер', 'Vegas']),
212
+ complex('Venetsiya', ['Венеция']),
213
+ complex('Viaport'),
214
+ complex('Vita Alliance'),
215
+ complex('Vita Stroy'),
216
+ complex('White House'),
217
+ complex('Wiston'),
218
+ complex('Xon Saroy', ['Хон Сарой', 'Khon Saroy']),
219
+ complex('Xonobod Avenue', ['Хонабод Авеню']),
220
+ complex('Yakkasaray City Mall', ['Яккасарай Сити Молл']),
221
+ complex('Yangi Baxt', ['Янгибахт', 'Янги Бахт']),
222
+ complex('Yangi Mahalla'),
223
+ complex('Yangi O’zbekiston Massivi'),
224
+ complex('Yashil Makon'),
225
+ complex('Yashil Sohil'),
226
+ complex('Yulduz'),
227
+ complex('Yunusabad Residence'),
228
+ complex('Zarafshan City'),
229
+ complex('Zaytunli'),
230
+ complex('Aeroport House', ['Аэропорт Хаус']),
231
+ complex('Besh Chinor', ['Беш Чинор']),
232
+ complex('Bobur Elite', ['Бобур Элит']),
233
+ complex('London', ['Лондон']),
234
+ complex('Madrid', ['Мадрид']),
235
+ complex('Maftun Makon', ['Мафтун Макон']),
236
+ complex('Urikzor Residence', ['Урикзор Резиденс']),
237
+ complex('Nest One', ['Нест Ван']),
238
+ complex('Assalom Jomiy', ['Ассалом Жомий']),
239
+ complex('Infinity', ['Инфинити', 'Инфинити ЖК']),
240
+ ]);
241
+
242
+ const RESIDENTIAL_CONTEXT_RE = /(?:ж\.?\s*к\.?|жил(?:ой|ого)\s+комплекс|новострой(?:ка|ки)?|residential\s+complex|residence|turar\s+joy|uy[-\s]?joy|majmua|массив)/iu;
243
+
244
+ function hasLocalResidentialContext(text, start, end) {
245
+ const before = text.slice(Math.max(0, start - 36), start);
246
+ const after = text.slice(end, end + 36);
247
+ return RESIDENTIAL_CONTEXT_RE.test(before) || RESIDENTIAL_CONTEXT_RE.test(after);
248
+ }
249
+
250
+ export function matchTashkentResidentialComplex(value) {
251
+ const text = String(value ?? '');
252
+ if (!text) return null;
253
+
254
+ const matches = [];
255
+ for (const entry of TASHKENT_RESIDENTIAL_COMPLEXES) {
256
+ const match = text.match(entry.re);
257
+ if (!match) continue;
258
+ const start = match.index ?? 0;
259
+ const end = start + match[0].length;
260
+ if (entry.ambiguous && !hasLocalResidentialContext(text, start, end)) continue;
261
+ matches.push({ entry, length: match[0].trim().length, start });
262
+ }
263
+
264
+ matches.sort((a, b) => b.length - a.length || a.start - b.start);
265
+ return matches[0]?.entry ?? null;
266
+ }
267
+
268
+ export function canonicalTashkentResidentialComplex(value) {
269
+ const direct = findCanonical(value, TASHKENT_RESIDENTIAL_COMPLEXES);
270
+ if (direct) return direct.name;
271
+ return matchTashkentResidentialComplex(value)?.name || null;
272
+ }