text-to-map 1.1.46 → 1.1.48

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 (97) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +69 -69
  3. package/dist/bin/address-points.d.ts +1 -1
  4. package/dist/bin/address-points.js +16 -16
  5. package/dist/bin/cities.d.ts +1 -1
  6. package/dist/bin/cities.js +10 -10
  7. package/dist/bin/clear-all.d.ts +1 -1
  8. package/dist/bin/clear-all.js +13 -13
  9. package/dist/bin/constants.d.ts +2 -2
  10. package/dist/bin/constants.js +4 -4
  11. package/dist/bin/generate-syntax-diagrams.d.ts +1 -1
  12. package/dist/bin/generate-syntax-diagrams.js +20 -20
  13. package/dist/bin/init-db.d.ts +1 -1
  14. package/dist/bin/init-db.js +8 -8
  15. package/dist/bin/knex.d.ts +1 -1
  16. package/dist/bin/knex.js +10 -10
  17. package/dist/bin/parse-ordinance.d.ts +1 -1
  18. package/dist/bin/parse-ordinance.js +74 -74
  19. package/dist/bin/polygons.d.ts +1 -1
  20. package/dist/bin/polygons.js +27 -27
  21. package/dist/bin/regions.d.ts +1 -1
  22. package/dist/bin/regions.js +10 -10
  23. package/dist/bin/schools.d.ts +1 -1
  24. package/dist/bin/schools.js +10 -10
  25. package/dist/bin/streets.d.ts +1 -1
  26. package/dist/bin/streets.js +19 -19
  27. package/dist/bin/sync-all.d.ts +1 -1
  28. package/dist/bin/sync-all.js +4 -4
  29. package/dist/db/address-points.d.ts +59 -59
  30. package/dist/db/address-points.js +406 -399
  31. package/dist/db/cities.d.ts +7 -7
  32. package/dist/db/cities.js +95 -95
  33. package/dist/db/db.d.ts +45 -37
  34. package/dist/db/db.js +212 -191
  35. package/dist/db/founders.d.ts +14 -14
  36. package/dist/db/founders.js +461 -461
  37. package/dist/db/meta.d.ts +4 -4
  38. package/dist/db/meta.js +26 -26
  39. package/dist/db/migrations/20230704125715_initial.js +304 -304
  40. package/dist/db/migrations/20230731232915_city_positions.js +13 -13
  41. package/dist/db/migrations/20240106224603_city_polygon.js +11 -11
  42. package/dist/db/migrations/20240320200534_district_polygon.js +11 -11
  43. package/dist/db/migrations/20250316162700_kindergartens.js +12 -12
  44. package/dist/db/regions.d.ts +31 -31
  45. package/dist/db/regions.js +81 -81
  46. package/dist/db/schools.d.ts +7 -7
  47. package/dist/db/schools.js +95 -95
  48. package/dist/db/street-sync.d.ts +6 -6
  49. package/dist/db/street-sync.js +24 -22
  50. package/dist/db/sync-log.d.ts +9 -9
  51. package/dist/db/sync-log.js +66 -66
  52. package/dist/db/types.d.ts +59 -59
  53. package/dist/db/types.js +26 -26
  54. package/dist/index.d.ts +23 -23
  55. package/dist/index.js +32 -32
  56. package/dist/open-data-sync/address-points.d.ts +2 -2
  57. package/dist/open-data-sync/address-points.js +68 -68
  58. package/dist/open-data-sync/cities.d.ts +2 -2
  59. package/dist/open-data-sync/cities.js +32 -32
  60. package/dist/open-data-sync/common.d.ts +2 -2
  61. package/dist/open-data-sync/common.js +22 -22
  62. package/dist/open-data-sync/regions.d.ts +2 -2
  63. package/dist/open-data-sync/regions.js +37 -37
  64. package/dist/open-data-sync/schools.d.ts +3 -3
  65. package/dist/open-data-sync/schools.js +207 -207
  66. package/dist/open-data-sync/streets.d.ts +2 -2
  67. package/dist/open-data-sync/streets.js +132 -132
  68. package/dist/smd-to-csv/json-to-csv.d.ts +1 -1
  69. package/dist/smd-to-csv/json-to-csv.js +154 -154
  70. package/dist/smd-to-csv/ordinance-to-csv-rules.d.ts +1 -1
  71. package/dist/smd-to-csv/ordinance-to-csv-rules.js +23 -23
  72. package/dist/smd-to-csv/txt-to-json.d.ts +1 -1
  73. package/dist/smd-to-csv/txt-to-json.js +92 -92
  74. package/dist/souradnice.csv +6260 -6260
  75. package/dist/street-markdown/municipality.d.ts +11 -11
  76. package/dist/street-markdown/municipality.js +116 -116
  77. package/dist/street-markdown/polygons.d.ts +7 -7
  78. package/dist/street-markdown/polygons.js +261 -261
  79. package/dist/street-markdown/roman-numerals.d.ts +1 -1
  80. package/dist/street-markdown/roman-numerals.js +68 -68
  81. package/dist/street-markdown/smd-line-parser.d.ts +4 -4
  82. package/dist/street-markdown/smd-line-parser.js +40 -40
  83. package/dist/street-markdown/smd-parser.d.ts +23 -23
  84. package/dist/street-markdown/smd-parser.js +393 -393
  85. package/dist/street-markdown/smd.d.ts +24 -24
  86. package/dist/street-markdown/smd.js +440 -440
  87. package/dist/street-markdown/token-definition.d.ts +25 -25
  88. package/dist/street-markdown/token-definition.js +168 -168
  89. package/dist/street-markdown/types.d.ts +148 -148
  90. package/dist/street-markdown/types.js +13 -13
  91. package/dist/utils/atom.d.ts +2 -2
  92. package/dist/utils/atom.js +57 -57
  93. package/dist/utils/helpers.d.ts +28 -28
  94. package/dist/utils/helpers.js +176 -176
  95. package/dist/utils/jtsk2wgs84.d.ts +17 -17
  96. package/dist/utils/jtsk2wgs84.js +82 -82
  97. package/package.json +109 -109
@@ -1,399 +1,406 @@
1
- import { AddressPointType, createSingleLineAddress } from "czech-address";
2
- import { SeriesType, isNegativeSeriesSpec, isRange, isSeriesSpecArray, } from "../street-markdown/types";
3
- import { findClosestString, roundToNDecimalPlaces } from "../utils/helpers";
4
- import jtsk2wgs84 from "../utils/jtsk2wgs84";
5
- import { extractKeyValuesPairs, generate2DPlaceholders, getKnexDb, insertMultipleRows, isMysql, isSqlite, nonEmptyOrNull, rawQuery, } from "./db";
6
- import { getFounderCityCode } from "./founders";
7
- import { MunicipalityType } from "./types";
8
- import chunk from "lodash/chunk";
9
- const DescriptiveType = "č.p.";
10
- const RegistrationType = "č.ev.";
11
- const ObjectTypes = {
12
- [DescriptiveType]: 1,
13
- [RegistrationType]: 2,
14
- };
15
- export const Column = {
16
- admCode: 0,
17
- cityCode: 1,
18
- cityName: 2,
19
- districtCode: 3,
20
- districtName: 4,
21
- pragueDistrictCode: 5,
22
- pragueDistrictName: 6,
23
- municipalityPartCode: 7,
24
- municipalityPartName: 8,
25
- streetCode: 9,
26
- streetName: 10,
27
- objectType: 11,
28
- houseNumber: 12,
29
- orientationalNumber: 13,
30
- orientationalNumberLetter: 14,
31
- postalCode: 15,
32
- yCoordinate: 16,
33
- xCoordinate: 17,
34
- validFrom: 18,
35
- };
36
- const columnNames = [
37
- "id",
38
- "street_code",
39
- "object_type_id",
40
- "descriptive_number",
41
- "orientational_number",
42
- "orientational_number_letter",
43
- "city_code",
44
- "city_district_code",
45
- "municipality_part_code",
46
- "prague_district_code",
47
- "postal_code",
48
- "jtsk_x",
49
- "jtsk_y",
50
- "wgs84_latitude",
51
- "wgs84_longitude",
52
- ];
53
- export const commitAddressPoints = async (buffer) => {
54
- if (buffer.length === 0) {
55
- return 0;
56
- }
57
- await insertCities(buffer);
58
- await insertDistricts(buffer);
59
- await insertMunicipalityParts(buffer);
60
- await insertStreets(buffer);
61
- await insertPragueDistricts(buffer);
62
- const params = {};
63
- buffer.forEach((data) => {
64
- let latOrNull, lonOrNull;
65
- latOrNull = null;
66
- lonOrNull = null;
67
- if (data[Column.xCoordinate] && data[Column.yCoordinate]) {
68
- const { lat, lon } = jtsk2wgs84(parseFloat(data[Column.xCoordinate]), parseFloat(data[Column.yCoordinate]));
69
- [latOrNull, lonOrNull] = [lat.toString(), lon.toString()];
70
- }
71
- params[data[Column.admCode]] = [
72
- data[Column.admCode],
73
- nonEmptyOrNull(data[Column.streetCode]),
74
- ObjectTypes[data[Column.objectType]],
75
- nonEmptyOrNull(data[Column.houseNumber]),
76
- nonEmptyOrNull(data[Column.orientationalNumber]),
77
- nonEmptyOrNull(data[Column.orientationalNumberLetter]),
78
- data[Column.cityCode],
79
- nonEmptyOrNull(data[Column.districtCode]),
80
- nonEmptyOrNull(data[Column.municipalityPartCode]),
81
- nonEmptyOrNull(data[Column.pragueDistrictCode]),
82
- data[Column.postalCode],
83
- nonEmptyOrNull(data[Column.xCoordinate]),
84
- nonEmptyOrNull(data[Column.yCoordinate]),
85
- latOrNull,
86
- lonOrNull,
87
- ];
88
- });
89
- // find already existing rows
90
- const existingRows = await rawQuery(`SELECT * FROM address_point WHERE id IN (${buffer
91
- .map((data) => data[Column.admCode])
92
- .join(",")})`);
93
- const queries = [];
94
- for (const row of existingRows) {
95
- const toInsert = params[row.id];
96
- const values = Object.values(row);
97
- if (!toInsert.every((v, i) => valuesEqual(v, values[i]))) {
98
- // update those whose values differ
99
- queries.push(rawQuery(`UPDATE address_point SET ${columnNames
100
- .map((c) => `${c} = ?`)
101
- .join(", ")} WHERE id = ?`, [...toInsert, row.id]));
102
- }
103
- }
104
- await Promise.all(queries);
105
- const placeHolders = generate2DPlaceholders(columnNames.length, buffer.length);
106
- const knex = getKnexDb();
107
- await rawQuery(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO address_point (${columnNames.join(",")}) VALUES ${placeHolders} ${!isMysql(knex) ? "ON CONFLICT (id) DO NOTHING" : ""}`, Object.values(params).flat());
108
- return buffer.length;
109
- };
110
- export async function removeDeprecatedAddressPoints(allIds) {
111
- const knex = getKnexDb();
112
- const existingIds = await knex.pluck("id").from("address_point");
113
- const toRemove = existingIds.filter((id) => !allIds.has(id));
114
- const chunks = chunk(toRemove, 1000);
115
- for (const chunk of chunks) {
116
- await knex("address_point").whereIn("id", chunk).delete();
117
- }
118
- console.log(`Removed ${toRemove.length} deprecated address points.`);
119
- }
120
- function valuesEqual(a, b) {
121
- return sanitizeValue(a) === sanitizeValue(b);
122
- }
123
- function sanitizeValue(value) {
124
- if (value === null) {
125
- return null;
126
- }
127
- value = value.toString();
128
- if (/\d+\.\d+/.test(value)) {
129
- return roundToNDecimalPlaces(parseFloat(value), 6).toString();
130
- }
131
- return value;
132
- }
133
- export const insertCities = async (buffer) => {
134
- return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.cityCode, [Column.cityName]), "city", ["code", "name"]);
135
- };
136
- export const insertDistricts = async (buffer) => {
137
- return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.districtCode, [
138
- Column.cityCode,
139
- Column.districtName,
140
- ]), "city_district", ["code", "city_code", "name"]);
141
- };
142
- export const insertMunicipalityParts = async (buffer) => {
143
- return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.municipalityPartCode, [
144
- Column.municipalityPartName,
145
- Column.cityCode,
146
- ]), "municipality_part", ["code", "name", "city_code"]);
147
- };
148
- export const insertPragueDistricts = async (buffer) => {
149
- return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.pragueDistrictCode, [
150
- Column.pragueDistrictName,
151
- ]), "prague_district", ["code", "name"]);
152
- };
153
- export const insertStreets = async (buffer) => {
154
- return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.streetCode, [
155
- Column.cityCode,
156
- Column.streetName,
157
- ]), "street", ["code", "city_code", "name"]);
158
- };
159
- export const areAddressPointsSynced = async () => {
160
- const result = await getKnexDb()
161
- .count("*", { as: "countAll" })
162
- .from("address_point")
163
- .first();
164
- return Number(result.countAll) >= 2900000; // total is almost 3 million
165
- };
166
- const addressPointSelect = `
167
- SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
168
- a.orientational_number, a.orientational_number_letter, c.name AS city_name,
169
- m.name AS municipality_part_name, p.name AS prague_district_name,
170
- d.name AS district_name, a.postal_code, a.wgs84_latitude, a.wgs84_longitude
171
- FROM address_point a
172
- LEFT JOIN street s ON a.street_code = s.code
173
- INNER JOIN object_type o ON o.id = a.object_type_id
174
- INNER JOIN city c ON c.code = a.city_code
175
- LEFT JOIN city_district d ON a.city_district_code = d.code
176
- LEFT JOIN prague_district p ON a.prague_district_code = p.code
177
- LEFT JOIN municipality_part m ON a.municipality_part_code = m.code`;
178
- export const getAddressPointById = async (addressPointId) => {
179
- const row = await rawQuery(`${addressPointSelect}
180
- WHERE a.id = ?`, [addressPointId]);
181
- if (row.length === 0) {
182
- return null;
183
- }
184
- return rowToAddressPoint(row[0]);
185
- };
186
- let lastFounder = null;
187
- let allStreets = [];
188
- export const checkStreetExists = async (streetName, founder) => {
189
- const knex = getKnexDb();
190
- const errors = [];
191
- // we check the whole city
192
- const cityCode = await getFounderCityCode(founder.municipalityType, founder.municipalityCode);
193
- const rowList = await rawQuery(`SELECT name AS street_name
194
- FROM street
195
- WHERE city_code = ? AND name = ? ${isSqlite(knex) ? "COLLATE NOCASE" : ""}`, [cityCode, streetName]);
196
- if (rowList.length > 0) {
197
- const row = rowList[0];
198
- if (row.street_name !== streetName) {
199
- // errors.push(
200
- // `Street '${streetName}' has wrong case, correct case: '${row.street_name}'.`
201
- // );
202
- }
203
- return { exists: true, errors };
204
- }
205
- if (lastFounder !== founder) {
206
- allStreets = await getAllStreets(cityCode);
207
- lastFounder = founder;
208
- }
209
- const match = allStreets.find((s) => s.toLocaleLowerCase("cs-CZ") === streetName.toLocaleLowerCase("cs-CZ"));
210
- let exists = false;
211
- if (match) {
212
- exists = true;
213
- if (streetName !== match) {
214
- // errors.push(
215
- // `Street '${streetName}' has wrong case, correct case: '${match}'.`
216
- // );
217
- }
218
- }
219
- else {
220
- const closest = findClosestString(streetName, allStreets);
221
- errors.push({
222
- message: `Ulice '${streetName}' v této obci neexistuje, mysleli jste '${closest}'?`,
223
- startOffset: 0,
224
- endOffset: streetName.length + 1,
225
- });
226
- }
227
- return { exists: false, errors };
228
- };
229
- const getAllStreets = async (cityCode) => {
230
- const knex = getKnexDb();
231
- return await knex.pluck("name").from("street").where("city_code", cityCode);
232
- };
233
- export const findAddressPoints = async (params) => {
234
- const queryParams = getQueryParams(params);
235
- const streetJoinCondition = getStreetJoinCondition(params);
236
- const whereCondition = getWhereCondition(params);
237
- const queryResult = await rawQuery(`SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
238
- a.orientational_number, a.orientational_number_letter, c.name AS city_name,
239
- d.name AS district_name, m.name AS municipality_part_name, p.name AS prague_district_name,
240
- a.postal_code, a.wgs84_latitude, a.wgs84_longitude
241
- FROM address_point a
242
- ${streetJoinCondition}
243
- INNER JOIN object_type o ON o.id = a.object_type_id
244
- INNER JOIN city c ON c.code = a.city_code
245
- LEFT JOIN city_district d ON a.city_district_code = d.code
246
- LEFT JOIN municipality_part m ON a.municipality_part_code = m.code
247
- LEFT JOIN prague_district p ON a.prague_district_code = p.code
248
- WHERE ${whereCondition}`, queryParams);
249
- return filterAddressPoints(queryResult.map(rowToAddressPoint), params);
250
- };
251
- export const filterAddressPoints = (addressPoints, params) => {
252
- if (params.type === "wholeMunicipality" ||
253
- params.type === "wholeMunicipalityNoStreetName" ||
254
- params.type === "wholeMunicipalityPart") {
255
- return addressPoints;
256
- }
257
- const result = [];
258
- const numberSpec = params.smdLine.numberSpec;
259
- if (isSeriesSpecArray(numberSpec)) {
260
- numberSpec.forEach((seriesSpec) => {
261
- result.push(...filterAddressPointsByRanges(addressPoints, seriesSpec));
262
- });
263
- // when no number specs are present, we take everything
264
- if (numberSpec.length === 0) {
265
- result.push(...addressPoints);
266
- }
267
- }
268
- else if (isNegativeSeriesSpec(numberSpec)) {
269
- // negative number spec (e.g. odd numbers except 13-17)
270
- const toExclude = filterAddressPointsByRanges(addressPoints, numberSpec);
271
- result.push(...addressPoints.filter((addressPoint) => !toExclude.includes(addressPoint)));
272
- }
273
- return result;
274
- };
275
- const filterAddressPointsByRanges = (addressPoints, seriesSpec) => {
276
- const result = [];
277
- seriesSpec.ranges.forEach((range) => {
278
- result.push(...addressPoints.filter((addressPoint) => {
279
- if (isRange(range)) {
280
- const number = getNumberByType(seriesSpec.type, addressPoint);
281
- return (isInRange(number, seriesSpec.type !== SeriesType.Description
282
- ? addressPoint.orientationalNumberLetter ?? null
283
- : null, range) && fitsType(number, seriesSpec.type));
284
- }
285
- else {
286
- const fullStreetNumber = range;
287
- return equalsFullStreetNumber(fullStreetNumber, addressPoint);
288
- }
289
- }));
290
- });
291
- // when no series specs are present, we take everything that fits the type
292
- if (seriesSpec.ranges.length === 0) {
293
- result.push(...addressPoints.filter((addressPoint) => fitsType(getNumberByType(seriesSpec.type, addressPoint), seriesSpec.type)));
294
- }
295
- return result;
296
- };
297
- export const getQueryParams = (params) => {
298
- if (params.type === "smdLine" && params.smdLine.type === "street") {
299
- return [params.smdLine.street, params.municipality.code];
300
- }
301
- if ((params.type === "smdLine" && params.smdLine.type === "municipalityPart") ||
302
- params.type === "wholeMunicipalityPart") {
303
- return [params.municipalityPartCode];
304
- }
305
- return [params.municipality.code];
306
- };
307
- export const getStreetJoinCondition = (params) => {
308
- if (params.type === "smdLine" && params.smdLine.type === "street") {
309
- return `JOIN street s ON a.street_code = s.code AND s.name = ? ${isSqlite(getKnexDb()) ? "COLLATE NOCASE" : ""}`;
310
- }
311
- return "LEFT JOIN street s ON a.street_code = s.code";
312
- };
313
- export const getWhereCondition = (params) => {
314
- if ((params.type === "smdLine" && params.smdLine.type === "municipalityPart") ||
315
- params.type === "wholeMunicipalityPart") {
316
- return "a.municipality_part_code = ?";
317
- }
318
- if (params.type === "wholeMunicipalityNoStreetName") {
319
- return `${getMunicipalityWhere("a", params.municipality)} AND a.street_code IS NULL`;
320
- }
321
- return getMunicipalityWhere("a", params.municipality);
322
- };
323
- export const isInRange = (number, letter, range) => {
324
- if (number === null) {
325
- return !range.from && !range.to;
326
- }
327
- // explainer: either the lower bound is not set, or it is lower than the number
328
- // if it's equal to the number, we also have to check the letter - if it's not set, we don't care
329
- // if from.letter is set, we need to have a letter set and it has to be greater or equal:
330
- // number without letter counts lower than number with letter 'a' (e.g. 23 < 23a)
331
- const satisfiesFrom = !range.from ||
332
- number > range.from.number ||
333
- (number === range.from.number &&
334
- (!range.from.letter || (!!letter && letter >= range.from.letter)));
335
- const satisfiesTo = !range.to ||
336
- number < range.to.number ||
337
- (number === range.to.number &&
338
- (!letter ||
339
- (!!range.to.letter && !!letter && letter <= range.to.letter)));
340
- return satisfiesFrom && satisfiesTo;
341
- };
342
- export const fitsType = (number, type) => {
343
- return (type === SeriesType.Description ||
344
- type === SeriesType.All ||
345
- (type === SeriesType.Odd && number % 2 === 1) ||
346
- (type === SeriesType.Even && number % 2 === 0));
347
- };
348
- export const equalsFullStreetNumber = (fullStreetNumber, addressPoint) => {
349
- return (fullStreetNumber.descriptionNumber.number === addressPoint.houseNumber &&
350
- fullStreetNumber.orientationalNumber.number ===
351
- addressPoint.orientationalNumber &&
352
- ((!fullStreetNumber.orientationalNumber.letter &&
353
- !addressPoint.orientationalNumberLetter) ||
354
- fullStreetNumber.orientationalNumber.letter ===
355
- addressPoint.orientationalNumberLetter));
356
- };
357
- const getNumberByType = (type, addressPoint) => {
358
- return type === SeriesType.Description
359
- ? addressPoint.houseNumber
360
- : addressPoint.orientationalNumber ?? null;
361
- };
362
- const getMunicipalityWhere = (alias, municipality) => {
363
- return municipality.type === MunicipalityType.City
364
- ? `${alias}.city_code = ?`
365
- : `${alias}.city_district_code = ?`;
366
- };
367
- const rowToAddressPoint = (row) => {
368
- const point = {
369
- id: row.id,
370
- address: "",
371
- type: row.object_type_name === DescriptiveType
372
- ? AddressPointType.Description
373
- : AddressPointType.Registration,
374
- houseNumber: row.descriptive_number,
375
- city: row.city_name,
376
- municipalityPart: row.municipality_part_name,
377
- postalCode: row.postal_code,
378
- lat: row.wgs84_latitude,
379
- lng: row.wgs84_longitude,
380
- };
381
- if (row.street_name !== null) {
382
- point.street = row.street_name;
383
- }
384
- if (row.orientational_number !== null) {
385
- point.orientationalNumber = row.orientational_number;
386
- }
387
- if (row.orientational_number_letter !== null) {
388
- point.orientationalNumberLetter = row.orientational_number_letter;
389
- }
390
- if (row.district_name !== null) {
391
- point.district = row.district_name;
392
- }
393
- if (row.prague_district_name !== null) {
394
- point.pragueDistrict = row.prague_district_name;
395
- }
396
- point.address = createSingleLineAddress(point);
397
- return point;
398
- };
399
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkcmVzcy1wb2ludHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGIvYWRkcmVzcy1wb2ludHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFFLE9BQU8sRUFLTCxVQUFVLEVBR1Ysb0JBQW9CLEVBQ3BCLE9BQU8sRUFDUCxpQkFBaUIsR0FDbEIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM1RSxPQUFPLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixTQUFTLEVBQ1Qsa0JBQWtCLEVBQ2xCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsY0FBYyxFQUNkLFFBQVEsR0FDVCxNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNoRCxPQUFPLEVBQXlCLGdCQUFnQixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xFLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUVqQyxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUM7QUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUM7QUFFakMsTUFBTSxXQUFXLEdBQUc7SUFDbEIsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO0lBQ3BCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO0NBQ3RCLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUc7SUFDcEIsT0FBTyxFQUFFLENBQUM7SUFDVixRQUFRLEVBQUUsQ0FBQztJQUNYLFFBQVEsRUFBRSxDQUFDO0lBQ1gsWUFBWSxFQUFFLENBQUM7SUFDZixZQUFZLEVBQUUsQ0FBQztJQUNmLGtCQUFrQixFQUFFLENBQUM7SUFD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YUFBYSxDQUFDO0tBQ3BDO0lBQ0QsSUFBSSxHQUFHLENBQUMsb0JBQW9CLEtBQUssSUFBSSxFQUFFO1FBQ3JDLEtBQUssQ0FBQyxjQUFjLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUFDO0tBQ2pEO0lBQ0QsS0FBSyxDQUFDLE9BQU8sR0FBRyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQyxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFkZHJlc3NQb2ludFR5cGUsIGNyZWF0ZVNpbmdsZUxpbmVBZGRyZXNzIH0gZnJvbSBcImN6ZWNoLWFkZHJlc3NcIjtcclxuaW1wb3J0IHtcclxuICBBZGRyZXNzUG9pbnQsXHJcbiAgRnVsbFN0cmVldE51bWJlcixcclxuICBSYW5nZVNwZWMsXHJcbiAgU2VyaWVzU3BlYyxcclxuICBTZXJpZXNUeXBlLFxyXG4gIFNtZEVycm9yLFxyXG4gIFNtZExpbmUsXHJcbiAgaXNOZWdhdGl2ZVNlcmllc1NwZWMsXHJcbiAgaXNSYW5nZSxcclxuICBpc1Nlcmllc1NwZWNBcnJheSxcclxufSBmcm9tIFwiLi4vc3RyZWV0LW1hcmtkb3duL3R5cGVzXCI7XHJcbmltcG9ydCB7IGZpbmRDbG9zZXN0U3RyaW5nLCByb3VuZFRvTkRlY2ltYWxQbGFjZXMgfSBmcm9tIFwiLi4vdXRpbHMvaGVscGVyc1wiO1xyXG5pbXBvcnQganRzazJ3Z3M4NCBmcm9tIFwiLi4vdXRpbHMvanRzazJ3Z3M4NFwiO1xyXG5pbXBvcnQge1xyXG4gIGV4dHJhY3RLZXlWYWx1ZXNQYWlycyxcclxuICBnZW5lcmF0ZTJEUGxhY2Vob2xkZXJzLFxyXG4gIGdldEtuZXhEYixcclxuICBpbnNlcnRNdWx0aXBsZVJvd3MsXHJcbiAgaXNNeXNxbCxcclxuICBpc1NxbGl0ZSxcclxuICBub25FbXB0eU9yTnVsbCxcclxuICByYXdRdWVyeSxcclxufSBmcm9tIFwiLi9kYlwiO1xyXG5pbXBvcnQgeyBnZXRGb3VuZGVyQ2l0eUNvZGUgfSBmcm9tIFwiLi9mb3VuZGVyc1wiO1xyXG5pbXBvcnQgeyBGb3VuZGVyLCBNdW5pY2lwYWxpdHksIE11bmljaXBhbGl0eVR5cGUgfSBmcm9tIFwiLi90eXBlc1wiO1xyXG5pbXBvcnQgY2h1bmsgZnJvbSBcImxvZGFzaC9jaHVua1wiO1xyXG5cclxuY29uc3QgRGVzY3JpcHRpdmVUeXBlID0gXCLEjS5wLlwiO1xyXG5jb25zdCBSZWdpc3RyYXRpb25UeXBlID0gXCLEjS5ldi5cIjtcclxuXHJcbmNvbnN0IE9iamVjdFR5cGVzID0ge1xyXG4gIFtEZXNjcmlwdGl2ZVR5cGVdOiAxLFxyXG4gIFtSZWdpc3RyYXRpb25UeXBlXTogMixcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBDb2x1bW4gPSB7XHJcbiAgYWRtQ29kZTogMCxcclxuICBjaXR5Q29kZTogMSxcclxuICBjaXR5TmFtZTogMixcclxuICBkaXN0cmljdENvZGU6IDMsXHJcbiAgZGlzdHJpY3ROYW1lOiA0LFxyXG4gIHByYWd1ZURpc3RyaWN0Q29kZTogNSxcclxuICBwcmFndWVEaXN0cmljdE5hbWU6IDYsXHJcbiAgbXVuaWNpcGFsaXR5UGFydENvZGU6IDcsXHJcbiAgbXVuaWNpcGFsaXR5UGFydE5hbWU6IDgsXHJcbiAgc3RyZWV0Q29kZTogOSxcclxuICBzdHJlZXROYW1lOiAxMCxcclxuICBvYmplY3RUeXBlOiAxMSxcclxuICBob3VzZU51bWJlcjogMTIsXHJcbiAgb3JpZW50YXRpb25hbE51bWJlcjogMTMsXHJcbiAgb3JpZW50YXRpb25hbE51bWJlckxldHRlcjogMTQsXHJcbiAgcG9zdGFsQ29kZTogMTUsXHJcbiAgeUNvb3JkaW5hdGU6IDE2LFxyXG4gIHhDb29yZGluYXRlOiAxNyxcclxuICB2YWxpZEZyb206IDE4LFxyXG59O1xyXG5cclxuY29uc3QgY29sdW1uTmFtZXMgPSBbXHJcbiAgXCJpZFwiLFxyXG4gIFwic3RyZWV0X2NvZGVcIixcclxuICBcIm9iamVjdF90eXBlX2lkXCIsXHJcbiAgXCJkZXNjcmlwdGl2ZV9udW1iZXJcIixcclxuICBcIm9yaWVudGF0aW9uYWxfbnVtYmVyXCIsXHJcbiAgXCJvcmllbnRhdGlvbmFsX251bWJlcl9sZXR0ZXJcIixcclxuICBcImNpdHlfY29kZVwiLFxyXG4gIFwiY2l0eV9kaXN0cmljdF9jb2RlXCIsXHJcbiAgXCJtdW5pY2lwYWxpdHlfcGFydF9jb2RlXCIsXHJcbiAgXCJwcmFndWVfZGlzdHJpY3RfY29kZVwiLFxyXG4gIFwicG9zdGFsX2NvZGVcIixcclxuICBcImp0c2tfeFwiLFxyXG4gIFwianRza195XCIsXHJcbiAgXCJ3Z3M4NF9sYXRpdHVkZVwiLFxyXG4gIFwid2dzODRfbG9uZ2l0dWRlXCIsXHJcbl07XHJcblxyXG5leHBvcnQgY29uc3QgY29tbWl0QWRkcmVzc1BvaW50cyA9IGFzeW5jIChcclxuICBidWZmZXI6IHN0cmluZ1tdW11cclxuKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcclxuICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgcmV0dXJuIDA7XHJcbiAgfVxyXG4gIGF3YWl0IGluc2VydENpdGllcyhidWZmZXIpO1xyXG4gIGF3YWl0IGluc2VydERpc3RyaWN0cyhidWZmZXIpO1xyXG4gIGF3YWl0IGluc2VydE11bmljaXBhbGl0eVBhcnRzKGJ1ZmZlcik7XHJcbiAgYXdhaXQgaW5zZXJ0U3RyZWV0cyhidWZmZXIpO1xyXG4gIGF3YWl0IGluc2VydFByYWd1ZURpc3RyaWN0cyhidWZmZXIpO1xyXG5cclxuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIChzdHJpbmcgfCBudWxsKVtdPiA9IHt9O1xyXG4gIGJ1ZmZlci5mb3JFYWNoKChkYXRhKSA9PiB7XHJcbiAgICBsZXQgbGF0T3JOdWxsOiBzdHJpbmcsIGxvbk9yTnVsbDogc3RyaW5nO1xyXG4gICAgbGF0T3JOdWxsID0gbnVsbDtcclxuICAgIGxvbk9yTnVsbCA9IG51bGw7XHJcbiAgICBpZiAoZGF0YVtDb2x1bW4ueENvb3JkaW5hdGVdICYmIGRhdGFbQ29sdW1uLnlDb29yZGluYXRlXSkge1xyXG4gICAgICBjb25zdCB7IGxhdCwgbG9uIH0gPSBqdHNrMndnczg0KFxyXG4gICAgICAgIHBhcnNlRmxvYXQoZGF0YVtDb2x1bW4ueENvb3JkaW5hdGVdKSxcclxuICAgICAgICBwYXJzZUZsb2F0KGRhdGFbQ29sdW1uLnlDb29yZGluYXRlXSlcclxuICAgICAgKTtcclxuICAgICAgW2xhdE9yTnVsbCwgbG9uT3JOdWxsXSA9IFtsYXQudG9TdHJpbmcoKSwgbG9uLnRvU3RyaW5nKCldO1xyXG4gICAgfVxyXG4gICAgcGFyYW1zW2RhdGFbQ29sdW1uLmFkbUNvZGVdXSA9IFtcclxuICAgICAgZGF0YVtDb2x1bW4uYWRtQ29kZV0sXHJcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLnN0cmVldENvZGVdKSxcclxuICAgICAgT2JqZWN0VHlwZXNbZGF0YVtDb2x1bW4ub2JqZWN0VHlwZV1dLFxyXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi5ob3VzZU51bWJlcl0pLFxyXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi5vcmllbnRhdGlvbmFsTnVtYmVyXSksXHJcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLm9yaWVudGF0aW9uYWxOdW1iZXJMZXR0ZXJdKSxcclxuICAgICAgZGF0YVtDb2x1bW4uY2l0eUNvZGVdLFxyXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi5kaXN0cmljdENvZGVdKSxcclxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4ubXVuaWNpcGFsaXR5UGFydENvZGVdKSxcclxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4ucHJhZ3VlRGlzdHJpY3RDb2RlXSksXHJcbiAgICAgIGRhdGFbQ29sdW1uLnBvc3RhbENvZGVdLFxyXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi54Q29vcmRpbmF0ZV0pLFxyXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi55Q29vcmRpbmF0ZV0pLFxyXG4gICAgICBsYXRPck51bGwsXHJcbiAgICAgIGxvbk9yTnVsbCxcclxuICAgIF07XHJcbiAgfSk7XHJcblxyXG4gIC8vIGZpbmQgYWxyZWFkeSBleGlzdGluZyByb3dzXHJcbiAgY29uc3QgZXhpc3RpbmdSb3dzID0gYXdhaXQgcmF3UXVlcnkoXHJcbiAgICBgU0VMRUNUICogRlJPTSBhZGRyZXNzX3BvaW50IFdIRVJFIGlkIElOICgke2J1ZmZlclxyXG4gICAgICAubWFwKChkYXRhKSA9PiBkYXRhW0NvbHVtbi5hZG1Db2RlXSlcclxuICAgICAgLmpvaW4oXCIsXCIpfSlgXHJcbiAgKTtcclxuXHJcbiAgY29uc3QgcXVlcmllcyA9IFtdO1xyXG4gIGZvciAoY29uc3Qgcm93IG9mIGV4aXN0aW5nUm93cykge1xyXG4gICAgY29uc3QgdG9JbnNlcnQgPSBwYXJhbXNbcm93LmlkXTtcclxuICAgIGNvbnN0IHZhbHVlcyA9IE9iamVjdC52YWx1ZXMocm93KTtcclxuICAgIGlmICghdG9JbnNlcnQuZXZlcnkoKHYsIGkpID0+IHZhbHVlc0VxdWFsKHYsIHZhbHVlc1tpXSkpKSB7XHJcbiAgICAgIC8vIHVwZGF0ZSB0aG9zZSB3aG9zZSB2YWx1ZXMgZGlmZmVyXHJcbiAgICAgIHF1ZXJpZXMucHVzaChcclxuICAgICAgICByYXdRdWVyeShcclxuICAgICAgICAgIGBVUERBVEUgYWRkcmVzc19wb2ludCBTRVQgJHtjb2x1bW5OYW1lc1xyXG4gICAgICAgICAgICAubWFwKChjKSA9PiBgJHtjfSA9ID9gKVxyXG4gICAgICAgICAgICAuam9pbihcIiwgXCIpfSBXSEVSRSBpZCA9ID9gLFxyXG4gICAgICAgICAgWy4uLnRvSW5zZXJ0LCByb3cuaWRdXHJcbiAgICAgICAgKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXdhaXQgUHJvbWlzZS5hbGwocXVlcmllcyk7XHJcblxyXG4gIGNvbnN0IHBsYWNlSG9sZGVycyA9IGdlbmVyYXRlMkRQbGFjZWhvbGRlcnMoXHJcbiAgICBjb2x1bW5OYW1lcy5sZW5ndGgsXHJcbiAgICBidWZmZXIubGVuZ3RoXHJcbiAgKTtcclxuXHJcbiAgY29uc3Qga25leCA9IGdldEtuZXhEYigpO1xyXG4gIGF3YWl0IHJhd1F1ZXJ5KFxyXG4gICAgYElOU0VSVCAke1xyXG4gICAgICBpc015c3FsKGtuZXgpID8gXCJJR05PUkVcIiA6IFwiXCJcclxuICAgIH0gSU5UTyBhZGRyZXNzX3BvaW50ICgke2NvbHVtbk5hbWVzLmpvaW4oXCIsXCIpfSkgVkFMVUVTICR7cGxhY2VIb2xkZXJzfSAke1xyXG4gICAgICAhaXNNeXNxbChrbmV4KSA/IFwiT04gQ09ORkxJQ1QgKGlkKSBETyBOT1RISU5HXCIgOiBcIlwiXHJcbiAgICB9YCxcclxuICAgIE9iamVjdC52YWx1ZXMocGFyYW1zKS5mbGF0KClcclxuICApO1xyXG5cclxuICByZXR1cm4gYnVmZmVyLmxlbmd0aDtcclxufTtcclxuXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW1vdmVEZXByZWNhdGVkQWRkcmVzc1BvaW50cyhcclxuICBhbGxJZHM6IFNldDxudW1iZXI+XHJcbik6IFByb21pc2U8dm9pZD4ge1xyXG4gIGNvbnN0IGtuZXggPSBnZXRLbmV4RGIoKTtcclxuICBjb25zdCBleGlzdGluZ0lkcyA9IGF3YWl0IGtuZXgucGx1Y2soXCJpZFwiKS5mcm9tKFwiYWRkcmVzc19wb2ludFwiKTtcclxuICBjb25zdCB0b1JlbW92ZSA9IGV4aXN0aW5nSWRzLmZpbHRlcigoaWQpID0+ICFhbGxJZHMuaGFzKGlkKSk7XHJcbiAgY29uc3QgY2h1bmtzID0gY2h1bmsodG9SZW1vdmUsIDEwMDApO1xyXG4gIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XHJcbiAgICBhd2FpdCBrbmV4KFwiYWRkcmVzc19wb2ludFwiKS53aGVyZUluKFwiaWRcIiwgY2h1bmspLmRlbGV0ZSgpO1xyXG4gIH1cclxuICBjb25zb2xlLmxvZyhgUmVtb3ZlZCAke3RvUmVtb3ZlLmxlbmd0aH0gZGVwcmVjYXRlZCBhZGRyZXNzIHBvaW50cy5gKTtcclxufVxyXG5cclxuZnVuY3Rpb24gdmFsdWVzRXF1YWwoYTogYW55LCBiOiBhbnkpOiBib29sZWFuIHtcclxuICByZXR1cm4gc2FuaXRpemVWYWx1ZShhKSA9PT0gc2FuaXRpemVWYWx1ZShiKTtcclxufVxyXG5cclxuZnVuY3Rpb24gc2FuaXRpemVWYWx1ZSh2YWx1ZTogYW55KTogYW55IHtcclxuICBpZiAodmFsdWUgPT09IG51bGwpIHtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XHJcblxyXG4gIGlmICgvXFxkK1xcLlxcZCsvLnRlc3QodmFsdWUpKSB7XHJcbiAgICByZXR1cm4gcm91bmRUb05EZWNpbWFsUGxhY2VzKHBhcnNlRmxvYXQodmFsdWUpLCA2KS50b1N0cmluZygpO1xyXG4gIH1cclxuICByZXR1cm4gdmFsdWU7XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBpbnNlcnRDaXRpZXMgPSBhc3luYyAoYnVmZmVyOiBzdHJpbmdbXVtdKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcclxuICByZXR1cm4gYXdhaXQgaW5zZXJ0TXVsdGlwbGVSb3dzKFxyXG4gICAgZXh0cmFjdEtleVZhbHVlc1BhaXJzKGJ1ZmZlciwgQ29sdW1uLmNpdHlDb2RlLCBbQ29sdW1uLmNpdHlOYW1lXSksXHJcbiAgICBcImNpdHlcIixcclxuICAgIFtcImNvZGVcIiwgXCJuYW1lXCJdXHJcbiAgKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBpbnNlcnREaXN0cmljdHMgPSBhc3luYyAoYnVmZmVyOiBzdHJpbmdbXVtdKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcclxuICByZXR1cm4gYXdhaXQgaW5zZXJ0TXVsdGlwbGVSb3dzKFxyXG4gICAgZXh0cmFjdEtleVZhbHVlc1BhaXJzKGJ1ZmZlciwgQ29sdW1uLmRpc3RyaWN0Q29kZSwgW1xyXG4gICAgICBDb2x1bW4uY2l0eUNvZGUsXHJcbiAgICAgIENvbHVtbi5kaXN0cmljdE5hbWUsXHJcbiAgICBdKSxcclxuICAgIFwiY2l0eV9kaXN0cmljdFwiLFxyXG4gICAgW1wiY29kZVwiLCBcImNpdHlfY29kZVwiLCBcIm5hbWVcIl1cclxuICApO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGluc2VydE11bmljaXBhbGl0eVBhcnRzID0gYXN5bmMgKFxyXG4gIGJ1ZmZlcjogc3RyaW5nW11bXVxyXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xyXG4gIHJldHVybiBhd2FpdCBpbnNlcnRNdWx0aXBsZVJvd3MoXHJcbiAgICBleHRyYWN0S2V5VmFsdWVzUGFpcnMoYnVmZmVyLCBDb2x1bW4ubXVuaWNpcGFsaXR5UGFydENvZGUsIFtcclxuICAgICAgQ29sdW1uLm11bmljaXBhbGl0eVBhcnROYW1lLFxyXG4gICAgICBDb2x1bW4uY2l0eUNvZGUsXHJcbiAgICBdKSxcclxuICAgIFwibXVuaWNpcGFsaXR5X3BhcnRcIixcclxuICAgIFtcImNvZGVcIiwgXCJuYW1lXCIsIFwiY2l0eV9jb2RlXCJdXHJcbiAgKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBpbnNlcnRQcmFndWVEaXN0cmljdHMgPSBhc3luYyAoXHJcbiAgYnVmZmVyOiBzdHJpbmdbXVtdXHJcbik6IFByb21pc2U8bnVtYmVyPiA9PiB7XHJcbiAgcmV0dXJuIGF3YWl0IGluc2VydE11bHRpcGxlUm93cyhcclxuICAgIGV4dHJhY3RLZXlWYWx1ZXNQYWlycyhidWZmZXIsIENvbHVtbi5wcmFndWVEaXN0cmljdENvZGUsIFtcclxuICAgICAgQ29sdW1uLnByYWd1ZURpc3RyaWN0TmFtZSxcclxuICAgIF0pLFxyXG4gICAgXCJwcmFndWVfZGlzdHJpY3RcIixcclxuICAgIFtcImNvZGVcIiwgXCJuYW1lXCJdXHJcbiAgKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBpbnNlcnRTdHJlZXRzID0gYXN5bmMgKGJ1ZmZlcjogc3RyaW5nW11bXSk6IFByb21pc2U8bnVtYmVyPiA9PiB7XHJcbiAgcmV0dXJuIGF3YWl0IGluc2VydE11bHRpcGxlUm93cyhcclxuICAgIGV4dHJhY3RLZXlWYWx1ZXNQYWlycyhidWZmZXIsIENvbHVtbi5zdHJlZXRDb2RlLCBbXHJcbiAgICAgIENvbHVtbi5jaXR5Q29kZSxcclxuICAgICAgQ29sdW1uLnN0cmVldE5hbWUsXHJcbiAgICBdKSxcclxuICAgIFwic3RyZWV0XCIsXHJcbiAgICBbXCJjb2RlXCIsIFwiY2l0eV9jb2RlXCIsIFwibmFtZVwiXVxyXG4gICk7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgYXJlQWRkcmVzc1BvaW50c1N5bmNlZCA9IGFzeW5jICgpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcclxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRLbmV4RGIoKVxyXG4gICAgLmNvdW50KFwiKlwiLCB7IGFzOiBcImNvdW50QWxsXCIgfSlcclxuICAgIC5mcm9tKFwiYWRkcmVzc19wb2ludFwiKVxyXG4gICAgLmZpcnN0KCk7XHJcbiAgcmV0dXJuIE51bWJlcihyZXN1bHQuY291bnRBbGwpID49IDI5MDAwMDA7IC8vIHRvdGFsIGlzIGFsbW9zdCAzIG1pbGxpb25cclxufTtcclxuXHJcbmNvbnN0IGFkZHJlc3NQb2ludFNlbGVjdCA9IGBcclxuICBTRUxFQ1QgYS5pZCwgcy5uYW1lIEFTIHN0cmVldF9uYW1lLCBvLm5hbWUgQVMgb2JqZWN0X3R5cGVfbmFtZSwgYS5kZXNjcmlwdGl2ZV9udW1iZXIsXHJcbiAgICAgICAgYS5vcmllbnRhdGlvbmFsX251bWJlciwgYS5vcmllbnRhdGlvbmFsX251bWJlcl9sZXR0ZXIsIGMubmFtZSBBUyBjaXR5X25hbWUsXHJcbiAgICAgICAgbS5uYW1lIEFTIG11bmljaXBhbGl0eV9wYXJ0X25hbWUsIHAubmFtZSBBUyBwcmFndWVfZGlzdHJpY3RfbmFtZSxcclxuICAgICAgICBkLm5hbWUgQVMgZGlzdHJpY3RfbmFtZSwgYS5wb3N0YWxfY29kZSwgYS53Z3M4NF9sYXRpdHVkZSwgYS53Z3M4NF9sb25naXR1ZGVcclxuICBGUk9NIGFkZHJlc3NfcG9pbnQgYVxyXG4gIExFRlQgSk9JTiBzdHJlZXQgcyBPTiBhLnN0cmVldF9jb2RlID0gcy5jb2RlXHJcbiAgSU5ORVIgSk9JTiBvYmplY3RfdHlwZSBvIE9OIG8uaWQgPSBhLm9iamVjdF90eXBlX2lkXHJcbiAgSU5ORVIgSk9JTiBjaXR5IGMgT04gYy5jb2RlID0gYS5jaXR5X2NvZGVcclxuICBMRUZUIEpPSU4gY2l0eV9kaXN0cmljdCBkIE9OIGEuY2l0eV9kaXN0cmljdF9jb2RlID0gZC5jb2RlXHJcbiAgTEVGVCBKT0lOIHByYWd1ZV9kaXN0cmljdCBwIE9OIGEucHJhZ3VlX2Rpc3RyaWN0X2NvZGUgPSBwLmNvZGVcclxuICBMRUZUIEpPSU4gbXVuaWNpcGFsaXR5X3BhcnQgbSBPTiBhLm11bmljaXBhbGl0eV9wYXJ0X2NvZGUgPSBtLmNvZGVgO1xyXG5cclxuZXhwb3J0IGNvbnN0IGdldEFkZHJlc3NQb2ludEJ5SWQgPSBhc3luYyAoXHJcbiAgYWRkcmVzc1BvaW50SWQ6IG51bWJlclxyXG4pOiBQcm9taXNlPEFkZHJlc3NQb2ludCB8IG51bGw+ID0+IHtcclxuICBjb25zdCByb3cgPSBhd2FpdCByYXdRdWVyeShcclxuICAgIGAke2FkZHJlc3NQb2ludFNlbGVjdH1cclxuICAgICAgV0hFUkUgYS5pZCA9ID9gLFxyXG4gICAgW2FkZHJlc3NQb2ludElkXVxyXG4gICk7XHJcbiAgaWYgKHJvdy5sZW5ndGggPT09IDApIHtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuICByZXR1cm4gcm93VG9BZGRyZXNzUG9pbnQocm93WzBdKTtcclxufTtcclxuXHJcbmxldCBsYXN0Rm91bmRlcjogRm91bmRlciB8IG51bGwgPSBudWxsO1xyXG5sZXQgYWxsU3RyZWV0czogc3RyaW5nW10gPSBbXTtcclxuXHJcbmV4cG9ydCBjb25zdCBjaGVja1N0cmVldEV4aXN0cyA9IGFzeW5jIChcclxuICBzdHJlZXROYW1lOiBzdHJpbmcsXHJcbiAgZm91bmRlcjogRm91bmRlclxyXG4pOiBQcm9taXNlPHsgZXhpc3RzOiBib29sZWFuOyBlcnJvcnM6IFNtZEVycm9yW10gfT4gPT4ge1xyXG4gIGNvbnN0IGtuZXggPSBnZXRLbmV4RGIoKTtcclxuICBjb25zdCBlcnJvcnM6IFNtZEVycm9yW10gPSBbXTtcclxuXHJcbiAgLy8gd2UgY2hlY2sgdGhlIHdob2xlIGNpdHlcclxuICBjb25zdCBjaXR5Q29kZSA9IGF3YWl0IGdldEZvdW5kZXJDaXR5Q29kZShcclxuICAgIGZvdW5kZXIubXVuaWNpcGFsaXR5VHlwZSxcclxuICAgIGZvdW5kZXIubXVuaWNpcGFsaXR5Q29kZVxyXG4gICk7XHJcbiAgY29uc3Qgcm93TGlzdCA9IGF3YWl0IHJhd1F1ZXJ5KFxyXG4gICAgYFNFTEVDVCBuYW1lIEFTIHN0cmVldF9uYW1lXHJcbiAgICBGUk9NIHN0cmVldFxyXG4gICAgV0hFUkUgY2l0eV9jb2RlID0gPyBBTkQgbmFtZSA9ID8gICR7XHJcbiAgICAgIGlzU3FsaXRlKGtuZXgpID8gXCJDT0xMQVRFIE5PQ0FTRVwiIDogXCJcIlxyXG4gICAgfWAsXHJcbiAgICBbY2l0eUNvZGUsIHN0cmVldE5hbWVdXHJcbiAgKTtcclxuXHJcbiAgaWYgKHJvd0xpc3QubGVuZ3RoID4gMCkge1xyXG4gICAgY29uc3Qgcm93ID0gcm93TGlzdFswXTtcclxuICAgIGlmIChyb3cuc3RyZWV0X25hbWUgIT09IHN0cmVldE5hbWUpIHtcclxuICAgICAgLy8gZXJyb3JzLnB1c2goXHJcbiAgICAgIC8vICAgYFN0cmVldCAnJHtzdHJlZXROYW1lfScgaGFzIHdyb25nIGNhc2UsIGNvcnJlY3QgY2FzZTogJyR7cm93LnN0cmVldF9uYW1lfScuYFxyXG4gICAgICAvLyApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHsgZXhpc3RzOiB0cnVlLCBlcnJvcnMgfTtcclxuICB9XHJcblxyXG4gIGlmIChsYXN0Rm91bmRlciAhPT0gZm91bmRlcikge1xyXG4gICAgYWxsU3RyZWV0cyA9IGF3YWl0IGdldEFsbFN0cmVldHMoY2l0eUNvZGUpO1xyXG4gICAgbGFzdEZvdW5kZXIgPSBmb3VuZGVyO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgbWF0Y2ggPSBhbGxTdHJlZXRzLmZpbmQoXHJcbiAgICAocykgPT5cclxuICAgICAgcy50b0xvY2FsZUxvd2VyQ2FzZShcImNzLUNaXCIpID09PSBzdHJlZXROYW1lLnRvTG9jYWxlTG93ZXJDYXNlKFwiY3MtQ1pcIilcclxuICApO1xyXG4gIGxldCBleGlzdHMgPSBmYWxzZTtcclxuICBpZiAobWF0Y2gpIHtcclxuICAgIGV4aXN0cyA9IHRydWU7XHJcbiAgICBpZiAoc3RyZWV0TmFtZSAhPT0gbWF0Y2gpIHtcclxuICAgICAgLy8gZXJyb3JzLnB1c2goXHJcbiAgICAgIC8vICAgYFN0cmVldCAnJHtzdHJlZXROYW1lfScgaGFzIHdyb25nIGNhc2UsIGNvcnJlY3QgY2FzZTogJyR7bWF0Y2h9Jy5gXHJcbiAgICAgIC8vICk7XHJcbiAgICB9XHJcbiAgfSBlbHNlIHtcclxuICAgIGNvbnN0IGNsb3Nlc3QgPSBmaW5kQ2xvc2VzdFN0cmluZyhzdHJlZXROYW1lLCBhbGxTdHJlZXRzKTtcclxuICAgIGVycm9ycy5wdXNoKHtcclxuICAgICAgbWVzc2FnZTogYFVsaWNlICcke3N0cmVldE5hbWV9JyB2IHTDqXRvIG9iY2kgbmVleGlzdHVqZSwgbXlzbGVsaSBqc3RlICcke2Nsb3Nlc3R9Jz9gLFxyXG4gICAgICBzdGFydE9mZnNldDogMCxcclxuICAgICAgZW5kT2Zmc2V0OiBzdHJlZXROYW1lLmxlbmd0aCArIDEsXHJcbiAgICB9KTtcclxuICB9XHJcbiAgcmV0dXJuIHsgZXhpc3RzOiBmYWxzZSwgZXJyb3JzIH07XHJcbn07XHJcblxyXG5jb25zdCBnZXRBbGxTdHJlZXRzID0gYXN5bmMgKGNpdHlDb2RlOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZ1tdPiA9PiB7XHJcbiAgY29uc3Qga25leCA9IGdldEtuZXhEYigpO1xyXG4gIHJldHVybiBhd2FpdCBrbmV4LnBsdWNrKFwibmFtZVwiKS5mcm9tKFwic3RyZWV0XCIpLndoZXJlKFwiY2l0eV9jb2RlXCIsIGNpdHlDb2RlKTtcclxufTtcclxuXHJcbmV4cG9ydCB0eXBlIEZpbmRBZGRyZXNzUG9pbnRzUGFyYW1zID1cclxuICB8IHtcclxuICAgICAgdHlwZTogXCJzbWRMaW5lXCI7XHJcbiAgICAgIHNtZExpbmU6IFNtZExpbmU7XHJcbiAgICAgIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5O1xyXG4gICAgICBtdW5pY2lwYWxpdHlQYXJ0Q29kZT86IG51bWJlcjtcclxuICAgIH1cclxuICB8IHtcclxuICAgICAgdHlwZTogXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIjtcclxuICAgICAgbXVuaWNpcGFsaXR5UGFydENvZGU6IG51bWJlcjtcclxuICAgIH1cclxuICB8IHtcclxuICAgICAgdHlwZTogXCJ3aG9sZU11bmljaXBhbGl0eVwiO1xyXG4gICAgICBtdW5pY2lwYWxpdHk6IE11bmljaXBhbGl0eTtcclxuICAgIH1cclxuICB8IHtcclxuICAgICAgdHlwZTogXCJ3aG9sZU11bmljaXBhbGl0eU5vU3RyZWV0TmFtZVwiO1xyXG4gICAgICBtdW5pY2lwYWxpdHk6IE11bmljaXBhbGl0eTtcclxuICAgIH07XHJcblxyXG5leHBvcnQgY29uc3QgZmluZEFkZHJlc3NQb2ludHMgPSBhc3luYyAoXHJcbiAgcGFyYW1zOiBGaW5kQWRkcmVzc1BvaW50c1BhcmFtc1xyXG4pOiBQcm9taXNlPEFkZHJlc3NQb2ludFtdPiA9PiB7XHJcbiAgY29uc3QgcXVlcnlQYXJhbXMgPSBnZXRRdWVyeVBhcmFtcyhwYXJhbXMpO1xyXG4gIGNvbnN0IHN0cmVldEpvaW5Db25kaXRpb24gPSBnZXRTdHJlZXRKb2luQ29uZGl0aW9uKHBhcmFtcyk7XHJcblxyXG4gIGNvbnN0IHdoZXJlQ29uZGl0aW9uID0gZ2V0V2hlcmVDb25kaXRpb24ocGFyYW1zKTtcclxuXHJcbiAgY29uc3QgcXVlcnlSZXN1bHQgPSBhd2FpdCByYXdRdWVyeShcclxuICAgIGBTRUxFQ1QgYS5pZCwgcy5uYW1lIEFTIHN0cmVldF9uYW1lLCBvLm5hbWUgQVMgb2JqZWN0X3R5cGVfbmFtZSwgYS5kZXNjcmlwdGl2ZV9udW1iZXIsXHJcbiAgICAgIGEub3JpZW50YXRpb25hbF9udW1iZXIsIGEub3JpZW50YXRpb25hbF9udW1iZXJfbGV0dGVyLCBjLm5hbWUgQVMgY2l0eV9uYW1lLFxyXG4gICAgICBkLm5hbWUgQVMgZGlzdHJpY3RfbmFtZSwgbS5uYW1lIEFTIG11bmljaXBhbGl0eV9wYXJ0X25hbWUsIHAubmFtZSBBUyBwcmFndWVfZGlzdHJpY3RfbmFtZSxcclxuICAgICAgYS5wb3N0YWxfY29kZSwgYS53Z3M4NF9sYXRpdHVkZSwgYS53Z3M4NF9sb25naXR1ZGVcclxuICAgIEZST00gYWRkcmVzc19wb2ludCBhXHJcbiAgICAke3N0cmVldEpvaW5Db25kaXRpb259XHJcbiAgICBJTk5FUiBKT0lOIG9iamVjdF90eXBlIG8gT04gby5pZCA9IGEub2JqZWN0X3R5cGVfaWRcclxuICAgIElOTkVSIEpPSU4gY2l0eSBjIE9OIGMuY29kZSA9IGEuY2l0eV9jb2RlXHJcbiAgICBMRUZUIEpPSU4gY2l0eV9kaXN0cmljdCBkIE9OIGEuY2l0eV9kaXN0cmljdF9jb2RlID0gZC5jb2RlXHJcbiAgICBMRUZUIEpPSU4gbXVuaWNpcGFsaXR5X3BhcnQgbSBPTiBhLm11bmljaXBhbGl0eV9wYXJ0X2NvZGUgPSBtLmNvZGVcclxuICAgIExFRlQgSk9JTiBwcmFndWVfZGlzdHJpY3QgcCBPTiBhLnByYWd1ZV9kaXN0cmljdF9jb2RlID0gcC5jb2RlXHJcbiAgICBXSEVSRSAke3doZXJlQ29uZGl0aW9ufWAsXHJcbiAgICBxdWVyeVBhcmFtc1xyXG4gICk7XHJcblxyXG4gIHJldHVybiBmaWx0ZXJBZGRyZXNzUG9pbnRzKHF1ZXJ5UmVzdWx0Lm1hcChyb3dUb0FkZHJlc3NQb2ludCksIHBhcmFtcyk7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgZmlsdGVyQWRkcmVzc1BvaW50cyA9IChcclxuICBhZGRyZXNzUG9pbnRzOiBBZGRyZXNzUG9pbnRbXSxcclxuICBwYXJhbXM6IEZpbmRBZGRyZXNzUG9pbnRzUGFyYW1zXHJcbik6IEFkZHJlc3NQb2ludFtdID0+IHtcclxuICBpZiAoXHJcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eVwiIHx8XHJcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eU5vU3RyZWV0TmFtZVwiIHx8XHJcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIlxyXG4gICkge1xyXG4gICAgcmV0dXJuIGFkZHJlc3NQb2ludHM7XHJcbiAgfVxyXG5cclxuICBjb25zdCByZXN1bHQ6IEFkZHJlc3NQb2ludFtdID0gW107XHJcbiAgY29uc3QgbnVtYmVyU3BlYyA9IHBhcmFtcy5zbWRMaW5lLm51bWJlclNwZWM7XHJcbiAgaWYgKGlzU2VyaWVzU3BlY0FycmF5KG51bWJlclNwZWMpKSB7XHJcbiAgICBudW1iZXJTcGVjLmZvckVhY2goKHNlcmllc1NwZWMpID0+IHtcclxuICAgICAgcmVzdWx0LnB1c2goLi4uZmlsdGVyQWRkcmVzc1BvaW50c0J5UmFuZ2VzKGFkZHJlc3NQb2ludHMsIHNlcmllc1NwZWMpKTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIHdoZW4gbm8gbnVtYmVyIHNwZWNzIGFyZSBwcmVzZW50LCB3ZSB0YWtlIGV2ZXJ5dGhpbmdcclxuICAgIGlmIChudW1iZXJTcGVjLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICByZXN1bHQucHVzaCguLi5hZGRyZXNzUG9pbnRzKTtcclxuICAgIH1cclxuICB9IGVsc2UgaWYgKGlzTmVnYXRpdmVTZXJpZXNTcGVjKG51bWJlclNwZWMpKSB7XHJcbiAgICAvLyBuZWdhdGl2ZSBudW1iZXIgc3BlYyAoZS5nLiBvZGQgbnVtYmVycyBleGNlcHQgMTMtMTcpXHJcbiAgICBjb25zdCB0b0V4Y2x1ZGUgPSBmaWx0ZXJBZGRyZXNzUG9pbnRzQnlSYW5nZXMoYWRkcmVzc1BvaW50cywgbnVtYmVyU3BlYyk7XHJcbiAgICByZXN1bHQucHVzaChcclxuICAgICAgLi4uYWRkcmVzc1BvaW50cy5maWx0ZXIoXHJcbiAgICAgICAgKGFkZHJlc3NQb2ludCkgPT4gIXRvRXhjbHVkZS5pbmNsdWRlcyhhZGRyZXNzUG9pbnQpXHJcbiAgICAgIClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmVzdWx0O1xyXG59O1xyXG5cclxuY29uc3QgZmlsdGVyQWRkcmVzc1BvaW50c0J5UmFuZ2VzID0gKFxyXG4gIGFkZHJlc3NQb2ludHM6IEFkZHJlc3NQb2ludFtdLFxyXG4gIHNlcmllc1NwZWM6IFNlcmllc1NwZWNcclxuKTogQWRkcmVzc1BvaW50W10gPT4ge1xyXG4gIGNvbnN0IHJlc3VsdDogQWRkcmVzc1BvaW50W10gPSBbXTtcclxuICBzZXJpZXNTcGVjLnJhbmdlcy5mb3JFYWNoKChyYW5nZSkgPT4ge1xyXG4gICAgcmVzdWx0LnB1c2goXHJcbiAgICAgIC4uLmFkZHJlc3NQb2ludHMuZmlsdGVyKChhZGRyZXNzUG9pbnQpID0+IHtcclxuICAgICAgICBpZiAoaXNSYW5nZShyYW5nZSkpIHtcclxuICAgICAgICAgIGNvbnN0IG51bWJlciA9IGdldE51bWJlckJ5VHlwZShzZXJpZXNTcGVjLnR5cGUsIGFkZHJlc3NQb2ludCk7XHJcbiAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICBpc0luUmFuZ2UoXHJcbiAgICAgICAgICAgICAgbnVtYmVyLFxyXG4gICAgICAgICAgICAgIHNlcmllc1NwZWMudHlwZSAhPT0gU2VyaWVzVHlwZS5EZXNjcmlwdGlvblxyXG4gICAgICAgICAgICAgICAgPyBhZGRyZXNzUG9pbnQub3JpZW50YXRpb25hbE51bWJlckxldHRlciA/PyBudWxsXHJcbiAgICAgICAgICAgICAgICA6IG51bGwsXHJcbiAgICAgICAgICAgICAgcmFuZ2VcclxuICAgICAgICAgICAgKSAmJiBmaXRzVHlwZShudW1iZXIsIHNlcmllc1NwZWMudHlwZSlcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IGZ1bGxTdHJlZXROdW1iZXI6IEZ1bGxTdHJlZXROdW1iZXIgPSByYW5nZTtcclxuICAgICAgICAgIHJldHVybiBlcXVhbHNGdWxsU3RyZWV0TnVtYmVyKGZ1bGxTdHJlZXROdW1iZXIsIGFkZHJlc3NQb2ludCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KVxyXG4gICAgKTtcclxuICB9KTtcclxuXHJcbiAgLy8gd2hlbiBubyBzZXJpZXMgc3BlY3MgYXJlIHByZXNlbnQsIHdlIHRha2UgZXZlcnl0aGluZyB0aGF0IGZpdHMgdGhlIHR5cGVcclxuICBpZiAoc2VyaWVzU3BlYy5yYW5nZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICByZXN1bHQucHVzaChcclxuICAgICAgLi4uYWRkcmVzc1BvaW50cy5maWx0ZXIoKGFkZHJlc3NQb2ludCkgPT5cclxuICAgICAgICBmaXRzVHlwZShcclxuICAgICAgICAgIGdldE51bWJlckJ5VHlwZShzZXJpZXNTcGVjLnR5cGUsIGFkZHJlc3NQb2ludCksXHJcbiAgICAgICAgICBzZXJpZXNTcGVjLnR5cGVcclxuICAgICAgICApXHJcbiAgICAgIClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmVzdWx0O1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGdldFF1ZXJ5UGFyYW1zID0gKFxyXG4gIHBhcmFtczogRmluZEFkZHJlc3NQb2ludHNQYXJhbXNcclxuKTogKHN0cmluZyB8IG51bWJlcilbXSA9PiB7XHJcbiAgaWYgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcInN0cmVldFwiKSB7XHJcbiAgICByZXR1cm4gW3BhcmFtcy5zbWRMaW5lLnN0cmVldCwgcGFyYW1zLm11bmljaXBhbGl0eS5jb2RlXTtcclxuICB9XHJcblxyXG4gIGlmIChcclxuICAgIChwYXJhbXMudHlwZSA9PT0gXCJzbWRMaW5lXCIgJiYgcGFyYW1zLnNtZExpbmUudHlwZSA9PT0gXCJtdW5pY2lwYWxpdHlQYXJ0XCIpIHx8XHJcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIlxyXG4gICkge1xyXG4gICAgcmV0dXJuIFtwYXJhbXMubXVuaWNpcGFsaXR5UGFydENvZGVdO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIFtwYXJhbXMubXVuaWNpcGFsaXR5LmNvZGVdO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGdldFN0cmVldEpvaW5Db25kaXRpb24gPSAoXHJcbiAgcGFyYW1zOiBGaW5kQWRkcmVzc1BvaW50c1BhcmFtc1xyXG4pOiBzdHJpbmcgPT4ge1xyXG4gIGlmIChwYXJhbXMudHlwZSA9PT0gXCJzbWRMaW5lXCIgJiYgcGFyYW1zLnNtZExpbmUudHlwZSA9PT0gXCJzdHJlZXRcIikge1xyXG4gICAgcmV0dXJuIGBKT0lOIHN0cmVldCBzIE9OIGEuc3RyZWV0X2NvZGUgPSBzLmNvZGUgQU5EIHMubmFtZSA9ID8gJHtcclxuICAgICAgaXNTcWxpdGUoZ2V0S25leERiKCkpID8gXCJDT0xMQVRFIE5PQ0FTRVwiIDogXCJcIlxyXG4gICAgfWA7XHJcbiAgfVxyXG4gIHJldHVybiBcIkxFRlQgSk9JTiBzdHJlZXQgcyBPTiBhLnN0cmVldF9jb2RlID0gcy5jb2RlXCI7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgZ2V0V2hlcmVDb25kaXRpb24gPSAocGFyYW1zOiBGaW5kQWRkcmVzc1BvaW50c1BhcmFtcyk6IHN0cmluZyA9PiB7XHJcbiAgaWYgKFxyXG4gICAgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcIm11bmljaXBhbGl0eVBhcnRcIikgfHxcclxuICAgIHBhcmFtcy50eXBlID09PSBcIndob2xlTXVuaWNpcGFsaXR5UGFydFwiXHJcbiAgKSB7XHJcbiAgICByZXR1cm4gXCJhLm11bmljaXBhbGl0eV9wYXJ0X2NvZGUgPSA/XCI7XHJcbiAgfVxyXG5cclxuICBpZiAocGFyYW1zLnR5cGUgPT09IFwid2hvbGVNdW5pY2lwYWxpdHlOb1N0cmVldE5hbWVcIikge1xyXG4gICAgcmV0dXJuIGAke2dldE11bmljaXBhbGl0eVdoZXJlKFxyXG4gICAgICBcImFcIixcclxuICAgICAgcGFyYW1zLm11bmljaXBhbGl0eVxyXG4gICAgKX0gQU5EIGEuc3RyZWV0X2NvZGUgSVMgTlVMTGA7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gZ2V0TXVuaWNpcGFsaXR5V2hlcmUoXCJhXCIsIHBhcmFtcy5tdW5pY2lwYWxpdHkpO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGlzSW5SYW5nZSA9IChcclxuICBudW1iZXI6IG51bWJlciB8IG51bGwsXHJcbiAgbGV0dGVyOiBzdHJpbmcgfCBudWxsLFxyXG4gIHJhbmdlOiBSYW5nZVNwZWNcclxuKTogYm9vbGVhbiA9PiB7XHJcbiAgaWYgKG51bWJlciA9PT0gbnVsbCkge1xyXG4gICAgcmV0dXJuICFyYW5nZS5mcm9tICYmICFyYW5nZS50bztcclxuICB9XHJcblxyXG4gIC8vIGV4cGxhaW5lcjogZWl0aGVyIHRoZSBsb3dlciBib3VuZCBpcyBub3Qgc2V0LCBvciBpdCBpcyBsb3dlciB0aGFuIHRoZSBudW1iZXJcclxuICAvLyBpZiBpdCdzIGVxdWFsIHRvIHRoZSBudW1iZXIsIHdlIGFsc28gaGF2ZSB0byBjaGVjayB0aGUgbGV0dGVyIC0gaWYgaXQncyBub3Qgc2V0LCB3ZSBkb24ndCBjYXJlXHJcbiAgLy8gaWYgZnJvbS5sZXR0ZXIgaXMgc2V0LCB3ZSBuZWVkIHRvIGhhdmUgYSBsZXR0ZXIgc2V0IGFuZCBpdCBoYXMgdG8gYmUgZ3JlYXRlciBvciBlcXVhbDpcclxuICAvLyBudW1iZXIgd2l0aG91dCBsZXR0ZXIgY291bnRzIGxvd2VyIHRoYW4gbnVtYmVyIHdpdGggbGV0dGVyICdhJyAoZS5nLiAyMyA8IDIzYSlcclxuICBjb25zdCBzYXRpc2ZpZXNGcm9tID1cclxuICAgICFyYW5nZS5mcm9tIHx8XHJcbiAgICBudW1iZXIgPiByYW5nZS5mcm9tLm51bWJlciB8fFxyXG4gICAgKG51bWJlciA9PT0gcmFuZ2UuZnJvbS5udW1iZXIgJiZcclxuICAgICAgKCFyYW5nZS5mcm9tLmxldHRlciB8fCAoISFsZXR0ZXIgJiYgbGV0dGVyID49IHJhbmdlLmZyb20ubGV0dGVyKSkpO1xyXG5cclxuICBjb25zdCBzYXRpc2ZpZXNUbyA9XHJcbiAgICAhcmFuZ2UudG8gfHxcclxuICAgIG51bWJlciA8IHJhbmdlLnRvLm51bWJlciB8fFxyXG4gICAgKG51bWJlciA9PT0gcmFuZ2UudG8ubnVtYmVyICYmXHJcbiAgICAgICghbGV0dGVyIHx8XHJcbiAgICAgICAgKCEhcmFuZ2UudG8ubGV0dGVyICYmICEhbGV0dGVyICYmIGxldHRlciA8PSByYW5nZS50by5sZXR0ZXIpKSk7XHJcblxyXG4gIHJldHVybiBzYXRpc2ZpZXNGcm9tICYmIHNhdGlzZmllc1RvO1xyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IGZpdHNUeXBlID0gKG51bWJlcjogbnVtYmVyIHwgbnVsbCwgdHlwZTogU2VyaWVzVHlwZSk6IGJvb2xlYW4gPT4ge1xyXG4gIHJldHVybiAoXHJcbiAgICB0eXBlID09PSBTZXJpZXNUeXBlLkRlc2NyaXB0aW9uIHx8XHJcbiAgICB0eXBlID09PSBTZXJpZXNUeXBlLkFsbCB8fFxyXG4gICAgKHR5cGUgPT09IFNlcmllc1R5cGUuT2RkICYmIG51bWJlciAlIDIgPT09IDEpIHx8XHJcbiAgICAodHlwZSA9PT0gU2VyaWVzVHlwZS5FdmVuICYmIG51bWJlciAlIDIgPT09IDApXHJcbiAgKTtcclxufTtcclxuXHJcbmV4cG9ydCBjb25zdCBlcXVhbHNGdWxsU3RyZWV0TnVtYmVyID0gKFxyXG4gIGZ1bGxTdHJlZXROdW1iZXI6IEZ1bGxTdHJlZXROdW1iZXIsXHJcbiAgYWRkcmVzc1BvaW50OiBBZGRyZXNzUG9pbnRcclxuKTogYm9vbGVhbiA9PiB7XHJcbiAgcmV0dXJuIChcclxuICAgIGZ1bGxTdHJlZXROdW1iZXIuZGVzY3JpcHRpb25OdW1iZXIubnVtYmVyID09PSBhZGRyZXNzUG9pbnQuaG91c2VOdW1iZXIgJiZcclxuICAgIGZ1bGxTdHJlZXROdW1iZXIub3JpZW50YXRpb25hbE51bWJlci5udW1iZXIgPT09XHJcbiAgICAgIGFkZHJlc3NQb2ludC5vcmllbnRhdGlvbmFsTnVtYmVyICYmXHJcbiAgICAoKCFmdWxsU3RyZWV0TnVtYmVyLm9yaWVudGF0aW9uYWxOdW1iZXIubGV0dGVyICYmXHJcbiAgICAgICFhZGRyZXNzUG9pbnQub3JpZW50YXRpb25hbE51bWJlckxldHRlcikgfHxcclxuICAgICAgZnVsbFN0cmVldE51bWJlci5vcmllbnRhdGlvbmFsTnVtYmVyLmxldHRlciA9PT1cclxuICAgICAgICBhZGRyZXNzUG9pbnQub3JpZW50YXRpb25hbE51bWJlckxldHRlcilcclxuICApO1xyXG59O1xyXG5cclxuY29uc3QgZ2V0TnVtYmVyQnlUeXBlID0gKFxyXG4gIHR5cGU6IFNlcmllc1R5cGUsXHJcbiAgYWRkcmVzc1BvaW50OiBBZGRyZXNzUG9pbnRcclxuKTogbnVtYmVyIHwgbnVsbCA9PiB7XHJcbiAgcmV0dXJuIHR5cGUgPT09IFNlcmllc1R5cGUuRGVzY3JpcHRpb25cclxuICAgID8gYWRkcmVzc1BvaW50LmhvdXNlTnVtYmVyXHJcbiAgICA6IGFkZHJlc3NQb2ludC5vcmllbnRhdGlvbmFsTnVtYmVyID8/IG51bGw7XHJcbn07XHJcblxyXG5jb25zdCBnZXRNdW5pY2lwYWxpdHlXaGVyZSA9IChcclxuICBhbGlhczogc3RyaW5nLFxyXG4gIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5XHJcbik6IHN0cmluZyA9PiB7XHJcbiAgcmV0dXJuIG11bmljaXBhbGl0eS50eXBlID09PSBNdW5pY2lwYWxpdHlUeXBlLkNpdHlcclxuICAgID8gYCR7YWxpYXN9LmNpdHlfY29kZSA9ID9gXHJcbiAgICA6IGAke2FsaWFzfS5jaXR5X2Rpc3RyaWN0X2NvZGUgPSA/YDtcclxufTtcclxuXHJcbmNvbnN0IHJvd1RvQWRkcmVzc1BvaW50ID0gKHJvdzogYW55KTogQWRkcmVzc1BvaW50ID0+IHtcclxuICBjb25zdCBwb2ludDogQWRkcmVzc1BvaW50ID0ge1xyXG4gICAgaWQ6IHJvdy5pZCxcclxuICAgIGFkZHJlc3M6IFwiXCIsXHJcbiAgICB0eXBlOlxyXG4gICAgICByb3cub2JqZWN0X3R5cGVfbmFtZSA9PT0gRGVzY3JpcHRpdmVUeXBlXHJcbiAgICAgICAgPyBBZGRyZXNzUG9pbnRUeXBlLkRlc2NyaXB0aW9uXHJcbiAgICAgICAgOiBBZGRyZXNzUG9pbnRUeXBlLlJlZ2lzdHJhdGlvbixcclxuICAgIGhvdXNlTnVtYmVyOiByb3cuZGVzY3JpcHRpdmVfbnVtYmVyLFxyXG4gICAgY2l0eTogcm93LmNpdHlfbmFtZSxcclxuICAgIG11bmljaXBhbGl0eVBhcnQ6IHJvdy5tdW5pY2lwYWxpdHlfcGFydF9uYW1lLFxyXG4gICAgcG9zdGFsQ29kZTogcm93LnBvc3RhbF9jb2RlLFxyXG4gICAgbGF0OiByb3cud2dzODRfbGF0aXR1ZGUsXHJcbiAgICBsbmc6IHJvdy53Z3M4NF9sb25naXR1ZGUsXHJcbiAgfTtcclxuICBpZiAocm93LnN0cmVldF9uYW1lICE9PSBudWxsKSB7XHJcbiAgICBwb2ludC5zdHJlZXQgPSByb3cuc3RyZWV0X25hbWU7XHJcbiAgfVxyXG4gIGlmIChyb3cub3JpZW50YXRpb25hbF9udW1iZXIgIT09IG51bGwpIHtcclxuICAgIHBvaW50Lm9yaWVudGF0aW9uYWxOdW1iZXIgPSByb3cub3JpZW50YXRpb25hbF9udW1iZXI7XHJcbiAgfVxyXG4gIGlmIChyb3cub3JpZW50YXRpb25hbF9udW1iZXJfbGV0dGVyICE9PSBudWxsKSB7XHJcbiAgICBwb2ludC5vcmllbnRhdGlvbmFsTnVtYmVyTGV0dGVyID0gcm93Lm9yaWVudGF0aW9uYWxfbnVtYmVyX2xldHRlcjtcclxuICB9XHJcbiAgaWYgKHJvdy5kaXN0cmljdF9uYW1lICE9PSBudWxsKSB7XHJcbiAgICBwb2ludC5kaXN0cmljdCA9IHJvdy5kaXN0cmljdF9uYW1lO1xyXG4gIH1cclxuICBpZiAocm93LnByYWd1ZV9kaXN0cmljdF9uYW1lICE9PSBudWxsKSB7XHJcbiAgICBwb2ludC5wcmFndWVEaXN0cmljdCA9IHJvdy5wcmFndWVfZGlzdHJpY3RfbmFtZTtcclxuICB9XHJcbiAgcG9pbnQuYWRkcmVzcyA9IGNyZWF0ZVNpbmdsZUxpbmVBZGRyZXNzKHBvaW50KTtcclxuICByZXR1cm4gcG9pbnQ7XHJcbn07XHJcbiJdfQ==
1
+ import { AddressPointType, createSingleLineAddress } from "czech-address";
2
+ import { SeriesType, isNegativeSeriesSpec, isRange, isSeriesSpecArray, } from "../street-markdown/types";
3
+ import { findClosestString, roundToNDecimalPlaces } from "../utils/helpers";
4
+ import jtsk2wgs84 from "../utils/jtsk2wgs84";
5
+ import { extractKeyValuesPairs, generate2DPlaceholders, getKnexDb, insertMultipleRows, isMysql, isSqlite, nonEmptyOrNull, rawQuery, } from "./db";
6
+ import { getFounderCityCode } from "./founders";
7
+ import { MunicipalityType } from "./types";
8
+ import chunk from "lodash/chunk";
9
+ const DescriptiveType = "č.p.";
10
+ const RegistrationType = "č.ev.";
11
+ const ObjectTypes = {
12
+ [DescriptiveType]: 1,
13
+ [RegistrationType]: 2,
14
+ };
15
+ export const Column = {
16
+ admCode: 0,
17
+ cityCode: 1,
18
+ cityName: 2,
19
+ districtCode: 3,
20
+ districtName: 4,
21
+ pragueDistrictCode: 5,
22
+ pragueDistrictName: 6,
23
+ municipalityPartCode: 7,
24
+ municipalityPartName: 8,
25
+ streetCode: 9,
26
+ streetName: 10,
27
+ objectType: 11,
28
+ houseNumber: 12,
29
+ orientationalNumber: 13,
30
+ orientationalNumberLetter: 14,
31
+ postalCode: 15,
32
+ yCoordinate: 16,
33
+ xCoordinate: 17,
34
+ validFrom: 18,
35
+ };
36
+ const columnNames = [
37
+ "id",
38
+ "street_code",
39
+ "object_type_id",
40
+ "descriptive_number",
41
+ "orientational_number",
42
+ "orientational_number_letter",
43
+ "city_code",
44
+ "city_district_code",
45
+ "municipality_part_code",
46
+ "prague_district_code",
47
+ "postal_code",
48
+ "jtsk_x",
49
+ "jtsk_y",
50
+ "wgs84_latitude",
51
+ "wgs84_longitude",
52
+ ];
53
+ export const commitAddressPoints = async (buffer) => {
54
+ if (buffer.length === 0) {
55
+ return 0;
56
+ }
57
+ await insertCities(buffer);
58
+ await insertDistricts(buffer);
59
+ await insertMunicipalityParts(buffer);
60
+ await insertStreets(buffer);
61
+ await insertPragueDistricts(buffer);
62
+ const params = {};
63
+ buffer.forEach((data) => {
64
+ let latOrNull, lonOrNull;
65
+ latOrNull = null;
66
+ lonOrNull = null;
67
+ if (data[Column.xCoordinate] && data[Column.yCoordinate]) {
68
+ const { lat, lon } = jtsk2wgs84(parseFloat(data[Column.xCoordinate]), parseFloat(data[Column.yCoordinate]));
69
+ [latOrNull, lonOrNull] = [lat.toString(), lon.toString()];
70
+ }
71
+ params[data[Column.admCode]] = [
72
+ data[Column.admCode],
73
+ nonEmptyOrNull(data[Column.streetCode]),
74
+ ObjectTypes[data[Column.objectType]],
75
+ nonEmptyOrNull(data[Column.houseNumber]),
76
+ nonEmptyOrNull(data[Column.orientationalNumber]),
77
+ nonEmptyOrNull(data[Column.orientationalNumberLetter]),
78
+ data[Column.cityCode],
79
+ nonEmptyOrNull(data[Column.districtCode]),
80
+ nonEmptyOrNull(data[Column.municipalityPartCode]),
81
+ nonEmptyOrNull(data[Column.pragueDistrictCode]),
82
+ data[Column.postalCode],
83
+ nonEmptyOrNull(data[Column.xCoordinate]),
84
+ nonEmptyOrNull(data[Column.yCoordinate]),
85
+ latOrNull,
86
+ lonOrNull,
87
+ ];
88
+ });
89
+ // find already existing rows
90
+ const existingRows = await rawQuery(`SELECT * FROM address_point WHERE id IN (${buffer
91
+ .map((data) => data[Column.admCode])
92
+ .join(",")})`);
93
+ const queries = [];
94
+ for (const row of existingRows) {
95
+ const toInsert = params[row.id];
96
+ const values = Object.values(row);
97
+ if (!toInsert.every((v, i) => valuesEqual(v, values[i]))) {
98
+ // update those whose values differ
99
+ queries.push(rawQuery(`UPDATE address_point SET ${columnNames
100
+ .map((c) => `${c} = ?`)
101
+ .join(", ")} WHERE id = ?`, [...toInsert, row.id]));
102
+ }
103
+ }
104
+ await Promise.all(queries);
105
+ const placeHolders = generate2DPlaceholders(columnNames.length, buffer.length);
106
+ const knex = getKnexDb();
107
+ await rawQuery(`INSERT ${isMysql(knex) ? "IGNORE" : ""} INTO address_point (${columnNames.join(",")}) VALUES ${placeHolders} ${!isMysql(knex) ? "ON CONFLICT (id) DO NOTHING" : ""}`, Object.values(params).flat());
108
+ return buffer.length;
109
+ };
110
+ export async function removeDeprecatedAddressPoints(allIds) {
111
+ const knex = getKnexDb();
112
+ const existingIds = await knex.pluck("id").from("address_point");
113
+ const toRemove = existingIds.filter((id) => !allIds.has(id));
114
+ const chunks = chunk(toRemove, 1000);
115
+ for (const chunk of chunks) {
116
+ await knex("address_point").whereIn("id", chunk).delete();
117
+ }
118
+ console.log(`Removed ${toRemove.length} deprecated address points.`);
119
+ }
120
+ function valuesEqual(a, b) {
121
+ return sanitizeValue(a) === sanitizeValue(b);
122
+ }
123
+ function sanitizeValue(value) {
124
+ if (value === null) {
125
+ return null;
126
+ }
127
+ value = value.toString();
128
+ if (/\d+\.\d+/.test(value)) {
129
+ return roundToNDecimalPlaces(parseFloat(value), 6).toString();
130
+ }
131
+ return value;
132
+ }
133
+ // names of cities, streets etc. can change while their code stays the same
134
+ const updateNameOnConflict = {
135
+ conflictColumns: ["code"],
136
+ updateColumns: ["name"],
137
+ };
138
+ export const insertCities = async (buffer) => {
139
+ return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.cityCode, [Column.cityName]), "city", ["code", "name"], true, updateNameOnConflict);
140
+ };
141
+ export const insertDistricts = async (buffer) => {
142
+ return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.districtCode, [
143
+ Column.cityCode,
144
+ Column.districtName,
145
+ ]), "city_district", ["code", "city_code", "name"], true, updateNameOnConflict);
146
+ };
147
+ export const insertMunicipalityParts = async (buffer) => {
148
+ return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.municipalityPartCode, [
149
+ Column.municipalityPartName,
150
+ Column.cityCode,
151
+ ]), "municipality_part", ["code", "name", "city_code"], true, updateNameOnConflict);
152
+ };
153
+ export const insertPragueDistricts = async (buffer) => {
154
+ return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.pragueDistrictCode, [
155
+ Column.pragueDistrictName,
156
+ ]), "prague_district", ["code", "name"], true, updateNameOnConflict);
157
+ };
158
+ export const insertStreets = async (buffer) => {
159
+ return await insertMultipleRows(extractKeyValuesPairs(buffer, Column.streetCode, [
160
+ Column.cityCode,
161
+ Column.streetName,
162
+ ]), "street", ["code", "city_code", "name"], true, updateNameOnConflict);
163
+ };
164
+ export const areAddressPointsSynced = async () => {
165
+ const result = await getKnexDb()
166
+ .count("*", { as: "countAll" })
167
+ .from("address_point")
168
+ .first();
169
+ return Number(result.countAll) >= 2900000; // total is almost 3 million
170
+ };
171
+ const addressPointSelect = `
172
+ SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
173
+ a.orientational_number, a.orientational_number_letter, c.name AS city_name,
174
+ m.name AS municipality_part_name, p.name AS prague_district_name,
175
+ d.name AS district_name, a.postal_code, a.wgs84_latitude, a.wgs84_longitude
176
+ FROM address_point a
177
+ LEFT JOIN street s ON a.street_code = s.code
178
+ INNER JOIN object_type o ON o.id = a.object_type_id
179
+ INNER JOIN city c ON c.code = a.city_code
180
+ LEFT JOIN city_district d ON a.city_district_code = d.code
181
+ LEFT JOIN prague_district p ON a.prague_district_code = p.code
182
+ LEFT JOIN municipality_part m ON a.municipality_part_code = m.code`;
183
+ export const getAddressPointById = async (addressPointId) => {
184
+ const row = await rawQuery(`${addressPointSelect}
185
+ WHERE a.id = ?`, [addressPointId]);
186
+ if (row.length === 0) {
187
+ return null;
188
+ }
189
+ return rowToAddressPoint(row[0]);
190
+ };
191
+ let lastFounder = null;
192
+ let allStreets = [];
193
+ export const checkStreetExists = async (streetName, founder) => {
194
+ const knex = getKnexDb();
195
+ const errors = [];
196
+ // we check the whole city
197
+ const cityCode = await getFounderCityCode(founder.municipalityType, founder.municipalityCode);
198
+ const rowList = await rawQuery(`SELECT name AS street_name
199
+ FROM street
200
+ WHERE city_code = ? AND name = ? ${isSqlite(knex) ? "COLLATE NOCASE" : ""}`, [cityCode, streetName]);
201
+ if (rowList.length > 0) {
202
+ const row = rowList[0];
203
+ if (row.street_name !== streetName) {
204
+ // errors.push(
205
+ // `Street '${streetName}' has wrong case, correct case: '${row.street_name}'.`
206
+ // );
207
+ }
208
+ return { exists: true, errors };
209
+ }
210
+ if (lastFounder !== founder) {
211
+ allStreets = await getAllStreets(cityCode);
212
+ lastFounder = founder;
213
+ }
214
+ const match = allStreets.find((s) => s.toLocaleLowerCase("cs-CZ") === streetName.toLocaleLowerCase("cs-CZ"));
215
+ let exists = false;
216
+ if (match) {
217
+ exists = true;
218
+ if (streetName !== match) {
219
+ // errors.push(
220
+ // `Street '${streetName}' has wrong case, correct case: '${match}'.`
221
+ // );
222
+ }
223
+ }
224
+ else {
225
+ const closest = findClosestString(streetName, allStreets);
226
+ errors.push({
227
+ message: `Ulice '${streetName}' v této obci neexistuje, mysleli jste '${closest}'?`,
228
+ startOffset: 0,
229
+ endOffset: streetName.length + 1,
230
+ });
231
+ }
232
+ return { exists: false, errors };
233
+ };
234
+ const getAllStreets = async (cityCode) => {
235
+ const knex = getKnexDb();
236
+ return await knex.pluck("name").from("street").where("city_code", cityCode);
237
+ };
238
+ export const findAddressPoints = async (params) => {
239
+ const queryParams = getQueryParams(params);
240
+ const streetJoinCondition = getStreetJoinCondition(params);
241
+ const whereCondition = getWhereCondition(params);
242
+ const queryResult = await rawQuery(`SELECT a.id, s.name AS street_name, o.name AS object_type_name, a.descriptive_number,
243
+ a.orientational_number, a.orientational_number_letter, c.name AS city_name,
244
+ d.name AS district_name, m.name AS municipality_part_name, p.name AS prague_district_name,
245
+ a.postal_code, a.wgs84_latitude, a.wgs84_longitude
246
+ FROM address_point a
247
+ ${streetJoinCondition}
248
+ INNER JOIN object_type o ON o.id = a.object_type_id
249
+ INNER JOIN city c ON c.code = a.city_code
250
+ LEFT JOIN city_district d ON a.city_district_code = d.code
251
+ LEFT JOIN municipality_part m ON a.municipality_part_code = m.code
252
+ LEFT JOIN prague_district p ON a.prague_district_code = p.code
253
+ WHERE ${whereCondition}`, queryParams);
254
+ return filterAddressPoints(queryResult.map(rowToAddressPoint), params);
255
+ };
256
+ export const filterAddressPoints = (addressPoints, params) => {
257
+ if (params.type === "wholeMunicipality" ||
258
+ params.type === "wholeMunicipalityNoStreetName" ||
259
+ params.type === "wholeMunicipalityPart") {
260
+ return addressPoints;
261
+ }
262
+ const result = [];
263
+ const numberSpec = params.smdLine.numberSpec;
264
+ if (isSeriesSpecArray(numberSpec)) {
265
+ numberSpec.forEach((seriesSpec) => {
266
+ result.push(...filterAddressPointsByRanges(addressPoints, seriesSpec));
267
+ });
268
+ // when no number specs are present, we take everything
269
+ if (numberSpec.length === 0) {
270
+ result.push(...addressPoints);
271
+ }
272
+ }
273
+ else if (isNegativeSeriesSpec(numberSpec)) {
274
+ // negative number spec (e.g. odd numbers except 13-17)
275
+ const toExclude = filterAddressPointsByRanges(addressPoints, numberSpec);
276
+ result.push(...addressPoints.filter((addressPoint) => !toExclude.includes(addressPoint)));
277
+ }
278
+ return result;
279
+ };
280
+ const filterAddressPointsByRanges = (addressPoints, seriesSpec) => {
281
+ const result = [];
282
+ seriesSpec.ranges.forEach((range) => {
283
+ result.push(...addressPoints.filter((addressPoint) => {
284
+ if (isRange(range)) {
285
+ const number = getNumberByType(seriesSpec.type, addressPoint);
286
+ return (isInRange(number, seriesSpec.type !== SeriesType.Description
287
+ ? addressPoint.orientationalNumberLetter ?? null
288
+ : null, range) && fitsType(number, seriesSpec.type));
289
+ }
290
+ else {
291
+ const fullStreetNumber = range;
292
+ return equalsFullStreetNumber(fullStreetNumber, addressPoint);
293
+ }
294
+ }));
295
+ });
296
+ // when no series specs are present, we take everything that fits the type
297
+ if (seriesSpec.ranges.length === 0) {
298
+ result.push(...addressPoints.filter((addressPoint) => fitsType(getNumberByType(seriesSpec.type, addressPoint), seriesSpec.type)));
299
+ }
300
+ return result;
301
+ };
302
+ export const getQueryParams = (params) => {
303
+ if (params.type === "smdLine" && params.smdLine.type === "street") {
304
+ return [params.smdLine.street, params.municipality.code];
305
+ }
306
+ if ((params.type === "smdLine" && params.smdLine.type === "municipalityPart") ||
307
+ params.type === "wholeMunicipalityPart") {
308
+ return [params.municipalityPartCode];
309
+ }
310
+ return [params.municipality.code];
311
+ };
312
+ export const getStreetJoinCondition = (params) => {
313
+ if (params.type === "smdLine" && params.smdLine.type === "street") {
314
+ return `JOIN street s ON a.street_code = s.code AND s.name = ? ${isSqlite(getKnexDb()) ? "COLLATE NOCASE" : ""}`;
315
+ }
316
+ return "LEFT JOIN street s ON a.street_code = s.code";
317
+ };
318
+ export const getWhereCondition = (params) => {
319
+ if ((params.type === "smdLine" && params.smdLine.type === "municipalityPart") ||
320
+ params.type === "wholeMunicipalityPart") {
321
+ return "a.municipality_part_code = ?";
322
+ }
323
+ if (params.type === "wholeMunicipalityNoStreetName") {
324
+ return `${getMunicipalityWhere("a", params.municipality)} AND a.street_code IS NULL`;
325
+ }
326
+ return getMunicipalityWhere("a", params.municipality);
327
+ };
328
+ export const isInRange = (number, letter, range) => {
329
+ if (number === null) {
330
+ return !range.from && !range.to;
331
+ }
332
+ // explainer: either the lower bound is not set, or it is lower than the number
333
+ // if it's equal to the number, we also have to check the letter - if it's not set, we don't care
334
+ // if from.letter is set, we need to have a letter set and it has to be greater or equal:
335
+ // number without letter counts lower than number with letter 'a' (e.g. 23 < 23a)
336
+ const satisfiesFrom = !range.from ||
337
+ number > range.from.number ||
338
+ (number === range.from.number &&
339
+ (!range.from.letter || (!!letter && letter >= range.from.letter)));
340
+ const satisfiesTo = !range.to ||
341
+ number < range.to.number ||
342
+ (number === range.to.number &&
343
+ (!letter ||
344
+ (!!range.to.letter && !!letter && letter <= range.to.letter)));
345
+ return satisfiesFrom && satisfiesTo;
346
+ };
347
+ export const fitsType = (number, type) => {
348
+ return (type === SeriesType.Description ||
349
+ type === SeriesType.All ||
350
+ // a missing number (e.g. no orientational number) is neither odd nor even,
351
+ // careful: null % 2 === 0 in JS
352
+ (type === SeriesType.Odd && number !== null && number % 2 === 1) ||
353
+ (type === SeriesType.Even && number !== null && number % 2 === 0));
354
+ };
355
+ export const equalsFullStreetNumber = (fullStreetNumber, addressPoint) => {
356
+ return (fullStreetNumber.descriptionNumber.number === addressPoint.houseNumber &&
357
+ fullStreetNumber.orientationalNumber.number ===
358
+ addressPoint.orientationalNumber &&
359
+ ((!fullStreetNumber.orientationalNumber.letter &&
360
+ !addressPoint.orientationalNumberLetter) ||
361
+ fullStreetNumber.orientationalNumber.letter ===
362
+ addressPoint.orientationalNumberLetter));
363
+ };
364
+ const getNumberByType = (type, addressPoint) => {
365
+ return type === SeriesType.Description
366
+ ? addressPoint.houseNumber
367
+ : addressPoint.orientationalNumber ?? null;
368
+ };
369
+ const getMunicipalityWhere = (alias, municipality) => {
370
+ return municipality.type === MunicipalityType.City
371
+ ? `${alias}.city_code = ?`
372
+ : `${alias}.city_district_code = ?`;
373
+ };
374
+ const rowToAddressPoint = (row) => {
375
+ const point = {
376
+ id: row.id,
377
+ address: "",
378
+ type: row.object_type_name === DescriptiveType
379
+ ? AddressPointType.Description
380
+ : AddressPointType.Registration,
381
+ houseNumber: row.descriptive_number,
382
+ city: row.city_name,
383
+ municipalityPart: row.municipality_part_name,
384
+ postalCode: row.postal_code,
385
+ lat: row.wgs84_latitude,
386
+ lng: row.wgs84_longitude,
387
+ };
388
+ if (row.street_name !== null) {
389
+ point.street = row.street_name;
390
+ }
391
+ if (row.orientational_number !== null) {
392
+ point.orientationalNumber = row.orientational_number;
393
+ }
394
+ if (row.orientational_number_letter !== null) {
395
+ point.orientationalNumberLetter = row.orientational_number_letter;
396
+ }
397
+ if (row.district_name !== null) {
398
+ point.district = row.district_name;
399
+ }
400
+ if (row.prague_district_name !== null) {
401
+ point.pragueDistrict = row.prague_district_name;
402
+ }
403
+ point.address = createSingleLineAddress(point);
404
+ return point;
405
+ };
406
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkcmVzcy1wb2ludHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGIvYWRkcmVzcy1wb2ludHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFFLE9BQU8sRUFLTCxVQUFVLEVBR1Ysb0JBQW9CLEVBQ3BCLE9BQU8sRUFDUCxpQkFBaUIsR0FDbEIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM1RSxPQUFPLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixTQUFTLEVBQ1Qsa0JBQWtCLEVBQ2xCLE9BQU8sRUFDUCxRQUFRLEVBQ1IsY0FBYyxFQUNkLFFBQVEsR0FDVCxNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNoRCxPQUFPLEVBQXlCLGdCQUFnQixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xFLE9BQU8sS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUVqQyxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUM7QUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUM7QUFFakMsTUFBTSxXQUFXLEdBQUc7SUFDbEIsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO0lBQ3BCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO0NBQ3RCLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUc7SUFDcEIsT0FBTyxFQUFFLENBQUM7SUFDVixRQUFRLEVBQUUsQ0FBQztJQUNYLFFBQVEsRUFBRSxDQUFDO0lBQ1gsWUFBWSxFQUFFLENBQUM7SUFDZixZQUFZLEVBQUUsQ0FBQztJQUNmLGtCQUFrQixFQUFFLENBQUM7SUFD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LFdBQVcsQ0FBQztLQUNoQztJQUNELElBQUksR0FBRyxDQUFDLG9CQUFvQixLQUFLLElBQUksRUFBRTtRQUNyQyxLQUFLLENBQUMsbUJBQW1CLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUFDO0tBQ3REO0lBQ0QsSUFBSSxHQUFHLENBQUMsMkJBQTJCLEtBQUssSUFBSSxFQUFFO1FBQzVDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxHQUFHLENBQUMsMkJBQTJCLENBQUM7S0FDbkU7SUFDRCxJQUFJLEdBQUcsQ0FBQyxhQUFhLEtBQUssSUFBSSxFQUFFO1FBQzlCLEtBQUssQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztLQUNwQztJQUNELElBQUksR0FBRyxDQUFDLG9CQUFvQixLQUFLLElBQUksRUFBRTtRQUNyQyxLQUFLLENBQUMsY0FBYyxHQUFHLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQztLQUNqRDtJQUNELEtBQUssQ0FBQyxPQUFPLEdBQUcsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZGRyZXNzUG9pbnRUeXBlLCBjcmVhdGVTaW5nbGVMaW5lQWRkcmVzcyB9IGZyb20gXCJjemVjaC1hZGRyZXNzXCI7XG5pbXBvcnQge1xuICBBZGRyZXNzUG9pbnQsXG4gIEZ1bGxTdHJlZXROdW1iZXIsXG4gIFJhbmdlU3BlYyxcbiAgU2VyaWVzU3BlYyxcbiAgU2VyaWVzVHlwZSxcbiAgU21kRXJyb3IsXG4gIFNtZExpbmUsXG4gIGlzTmVnYXRpdmVTZXJpZXNTcGVjLFxuICBpc1JhbmdlLFxuICBpc1Nlcmllc1NwZWNBcnJheSxcbn0gZnJvbSBcIi4uL3N0cmVldC1tYXJrZG93bi90eXBlc1wiO1xuaW1wb3J0IHsgZmluZENsb3Nlc3RTdHJpbmcsIHJvdW5kVG9ORGVjaW1hbFBsYWNlcyB9IGZyb20gXCIuLi91dGlscy9oZWxwZXJzXCI7XG5pbXBvcnQganRzazJ3Z3M4NCBmcm9tIFwiLi4vdXRpbHMvanRzazJ3Z3M4NFwiO1xuaW1wb3J0IHtcbiAgZXh0cmFjdEtleVZhbHVlc1BhaXJzLFxuICBnZW5lcmF0ZTJEUGxhY2Vob2xkZXJzLFxuICBnZXRLbmV4RGIsXG4gIGluc2VydE11bHRpcGxlUm93cyxcbiAgaXNNeXNxbCxcbiAgaXNTcWxpdGUsXG4gIG5vbkVtcHR5T3JOdWxsLFxuICByYXdRdWVyeSxcbn0gZnJvbSBcIi4vZGJcIjtcbmltcG9ydCB7IGdldEZvdW5kZXJDaXR5Q29kZSB9IGZyb20gXCIuL2ZvdW5kZXJzXCI7XG5pbXBvcnQgeyBGb3VuZGVyLCBNdW5pY2lwYWxpdHksIE11bmljaXBhbGl0eVR5cGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IGNodW5rIGZyb20gXCJsb2Rhc2gvY2h1bmtcIjtcblxuY29uc3QgRGVzY3JpcHRpdmVUeXBlID0gXCLEjS5wLlwiO1xuY29uc3QgUmVnaXN0cmF0aW9uVHlwZSA9IFwixI0uZXYuXCI7XG5cbmNvbnN0IE9iamVjdFR5cGVzID0ge1xuICBbRGVzY3JpcHRpdmVUeXBlXTogMSxcbiAgW1JlZ2lzdHJhdGlvblR5cGVdOiAyLFxufTtcblxuZXhwb3J0IGNvbnN0IENvbHVtbiA9IHtcbiAgYWRtQ29kZTogMCxcbiAgY2l0eUNvZGU6IDEsXG4gIGNpdHlOYW1lOiAyLFxuICBkaXN0cmljdENvZGU6IDMsXG4gIGRpc3RyaWN0TmFtZTogNCxcbiAgcHJhZ3VlRGlzdHJpY3RDb2RlOiA1LFxuICBwcmFndWVEaXN0cmljdE5hbWU6IDYsXG4gIG11bmljaXBhbGl0eVBhcnRDb2RlOiA3LFxuICBtdW5pY2lwYWxpdHlQYXJ0TmFtZTogOCxcbiAgc3RyZWV0Q29kZTogOSxcbiAgc3RyZWV0TmFtZTogMTAsXG4gIG9iamVjdFR5cGU6IDExLFxuICBob3VzZU51bWJlcjogMTIsXG4gIG9yaWVudGF0aW9uYWxOdW1iZXI6IDEzLFxuICBvcmllbnRhdGlvbmFsTnVtYmVyTGV0dGVyOiAxNCxcbiAgcG9zdGFsQ29kZTogMTUsXG4gIHlDb29yZGluYXRlOiAxNixcbiAgeENvb3JkaW5hdGU6IDE3LFxuICB2YWxpZEZyb206IDE4LFxufTtcblxuY29uc3QgY29sdW1uTmFtZXMgPSBbXG4gIFwiaWRcIixcbiAgXCJzdHJlZXRfY29kZVwiLFxuICBcIm9iamVjdF90eXBlX2lkXCIsXG4gIFwiZGVzY3JpcHRpdmVfbnVtYmVyXCIsXG4gIFwib3JpZW50YXRpb25hbF9udW1iZXJcIixcbiAgXCJvcmllbnRhdGlvbmFsX251bWJlcl9sZXR0ZXJcIixcbiAgXCJjaXR5X2NvZGVcIixcbiAgXCJjaXR5X2Rpc3RyaWN0X2NvZGVcIixcbiAgXCJtdW5pY2lwYWxpdHlfcGFydF9jb2RlXCIsXG4gIFwicHJhZ3VlX2Rpc3RyaWN0X2NvZGVcIixcbiAgXCJwb3N0YWxfY29kZVwiLFxuICBcImp0c2tfeFwiLFxuICBcImp0c2tfeVwiLFxuICBcIndnczg0X2xhdGl0dWRlXCIsXG4gIFwid2dzODRfbG9uZ2l0dWRlXCIsXG5dO1xuXG5leHBvcnQgY29uc3QgY29tbWl0QWRkcmVzc1BvaW50cyA9IGFzeW5jIChcbiAgYnVmZmVyOiBzdHJpbmdbXVtdXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIGF3YWl0IGluc2VydENpdGllcyhidWZmZXIpO1xuICBhd2FpdCBpbnNlcnREaXN0cmljdHMoYnVmZmVyKTtcbiAgYXdhaXQgaW5zZXJ0TXVuaWNpcGFsaXR5UGFydHMoYnVmZmVyKTtcbiAgYXdhaXQgaW5zZXJ0U3RyZWV0cyhidWZmZXIpO1xuICBhd2FpdCBpbnNlcnRQcmFndWVEaXN0cmljdHMoYnVmZmVyKTtcblxuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIChzdHJpbmcgfCBudWxsKVtdPiA9IHt9O1xuICBidWZmZXIuZm9yRWFjaCgoZGF0YSkgPT4ge1xuICAgIGxldCBsYXRPck51bGw6IHN0cmluZywgbG9uT3JOdWxsOiBzdHJpbmc7XG4gICAgbGF0T3JOdWxsID0gbnVsbDtcbiAgICBsb25Pck51bGwgPSBudWxsO1xuICAgIGlmIChkYXRhW0NvbHVtbi54Q29vcmRpbmF0ZV0gJiYgZGF0YVtDb2x1bW4ueUNvb3JkaW5hdGVdKSB7XG4gICAgICBjb25zdCB7IGxhdCwgbG9uIH0gPSBqdHNrMndnczg0KFxuICAgICAgICBwYXJzZUZsb2F0KGRhdGFbQ29sdW1uLnhDb29yZGluYXRlXSksXG4gICAgICAgIHBhcnNlRmxvYXQoZGF0YVtDb2x1bW4ueUNvb3JkaW5hdGVdKVxuICAgICAgKTtcbiAgICAgIFtsYXRPck51bGwsIGxvbk9yTnVsbF0gPSBbbGF0LnRvU3RyaW5nKCksIGxvbi50b1N0cmluZygpXTtcbiAgICB9XG4gICAgcGFyYW1zW2RhdGFbQ29sdW1uLmFkbUNvZGVdXSA9IFtcbiAgICAgIGRhdGFbQ29sdW1uLmFkbUNvZGVdLFxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4uc3RyZWV0Q29kZV0pLFxuICAgICAgT2JqZWN0VHlwZXNbZGF0YVtDb2x1bW4ub2JqZWN0VHlwZV1dLFxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4uaG91c2VOdW1iZXJdKSxcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLm9yaWVudGF0aW9uYWxOdW1iZXJdKSxcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLm9yaWVudGF0aW9uYWxOdW1iZXJMZXR0ZXJdKSxcbiAgICAgIGRhdGFbQ29sdW1uLmNpdHlDb2RlXSxcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLmRpc3RyaWN0Q29kZV0pLFxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4ubXVuaWNpcGFsaXR5UGFydENvZGVdKSxcbiAgICAgIG5vbkVtcHR5T3JOdWxsKGRhdGFbQ29sdW1uLnByYWd1ZURpc3RyaWN0Q29kZV0pLFxuICAgICAgZGF0YVtDb2x1bW4ucG9zdGFsQ29kZV0sXG4gICAgICBub25FbXB0eU9yTnVsbChkYXRhW0NvbHVtbi54Q29vcmRpbmF0ZV0pLFxuICAgICAgbm9uRW1wdHlPck51bGwoZGF0YVtDb2x1bW4ueUNvb3JkaW5hdGVdKSxcbiAgICAgIGxhdE9yTnVsbCxcbiAgICAgIGxvbk9yTnVsbCxcbiAgICBdO1xuICB9KTtcblxuICAvLyBmaW5kIGFscmVhZHkgZXhpc3Rpbmcgcm93c1xuICBjb25zdCBleGlzdGluZ1Jvd3MgPSBhd2FpdCByYXdRdWVyeShcbiAgICBgU0VMRUNUICogRlJPTSBhZGRyZXNzX3BvaW50IFdIRVJFIGlkIElOICgke2J1ZmZlclxuICAgICAgLm1hcCgoZGF0YSkgPT4gZGF0YVtDb2x1bW4uYWRtQ29kZV0pXG4gICAgICAuam9pbihcIixcIil9KWBcbiAgKTtcblxuICBjb25zdCBxdWVyaWVzID0gW107XG4gIGZvciAoY29uc3Qgcm93IG9mIGV4aXN0aW5nUm93cykge1xuICAgIGNvbnN0IHRvSW5zZXJ0ID0gcGFyYW1zW3Jvdy5pZF07XG4gICAgY29uc3QgdmFsdWVzID0gT2JqZWN0LnZhbHVlcyhyb3cpO1xuICAgIGlmICghdG9JbnNlcnQuZXZlcnkoKHYsIGkpID0+IHZhbHVlc0VxdWFsKHYsIHZhbHVlc1tpXSkpKSB7XG4gICAgICAvLyB1cGRhdGUgdGhvc2Ugd2hvc2UgdmFsdWVzIGRpZmZlclxuICAgICAgcXVlcmllcy5wdXNoKFxuICAgICAgICByYXdRdWVyeShcbiAgICAgICAgICBgVVBEQVRFIGFkZHJlc3NfcG9pbnQgU0VUICR7Y29sdW1uTmFtZXNcbiAgICAgICAgICAgIC5tYXAoKGMpID0+IGAke2N9ID0gP2ApXG4gICAgICAgICAgICAuam9pbihcIiwgXCIpfSBXSEVSRSBpZCA9ID9gLFxuICAgICAgICAgIFsuLi50b0luc2VydCwgcm93LmlkXVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGF3YWl0IFByb21pc2UuYWxsKHF1ZXJpZXMpO1xuXG4gIGNvbnN0IHBsYWNlSG9sZGVycyA9IGdlbmVyYXRlMkRQbGFjZWhvbGRlcnMoXG4gICAgY29sdW1uTmFtZXMubGVuZ3RoLFxuICAgIGJ1ZmZlci5sZW5ndGhcbiAgKTtcblxuICBjb25zdCBrbmV4ID0gZ2V0S25leERiKCk7XG4gIGF3YWl0IHJhd1F1ZXJ5KFxuICAgIGBJTlNFUlQgJHtcbiAgICAgIGlzTXlzcWwoa25leCkgPyBcIklHTk9SRVwiIDogXCJcIlxuICAgIH0gSU5UTyBhZGRyZXNzX3BvaW50ICgke2NvbHVtbk5hbWVzLmpvaW4oXCIsXCIpfSkgVkFMVUVTICR7cGxhY2VIb2xkZXJzfSAke1xuICAgICAgIWlzTXlzcWwoa25leCkgPyBcIk9OIENPTkZMSUNUIChpZCkgRE8gTk9USElOR1wiIDogXCJcIlxuICAgIH1gLFxuICAgIE9iamVjdC52YWx1ZXMocGFyYW1zKS5mbGF0KClcbiAgKTtcblxuICByZXR1cm4gYnVmZmVyLmxlbmd0aDtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW1vdmVEZXByZWNhdGVkQWRkcmVzc1BvaW50cyhcbiAgYWxsSWRzOiBTZXQ8bnVtYmVyPlxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGtuZXggPSBnZXRLbmV4RGIoKTtcbiAgY29uc3QgZXhpc3RpbmdJZHMgPSBhd2FpdCBrbmV4LnBsdWNrKFwiaWRcIikuZnJvbShcImFkZHJlc3NfcG9pbnRcIik7XG4gIGNvbnN0IHRvUmVtb3ZlID0gZXhpc3RpbmdJZHMuZmlsdGVyKChpZCkgPT4gIWFsbElkcy5oYXMoaWQpKTtcbiAgY29uc3QgY2h1bmtzID0gY2h1bmsodG9SZW1vdmUsIDEwMDApO1xuICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykge1xuICAgIGF3YWl0IGtuZXgoXCJhZGRyZXNzX3BvaW50XCIpLndoZXJlSW4oXCJpZFwiLCBjaHVuaykuZGVsZXRlKCk7XG4gIH1cbiAgY29uc29sZS5sb2coYFJlbW92ZWQgJHt0b1JlbW92ZS5sZW5ndGh9IGRlcHJlY2F0ZWQgYWRkcmVzcyBwb2ludHMuYCk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlc0VxdWFsKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiBzYW5pdGl6ZVZhbHVlKGEpID09PSBzYW5pdGl6ZVZhbHVlKGIpO1xufVxuXG5mdW5jdGlvbiBzYW5pdGl6ZVZhbHVlKHZhbHVlOiBhbnkpOiBhbnkge1xuICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG5cbiAgaWYgKC9cXGQrXFwuXFxkKy8udGVzdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gcm91bmRUb05EZWNpbWFsUGxhY2VzKHBhcnNlRmxvYXQodmFsdWUpLCA2KS50b1N0cmluZygpO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLy8gbmFtZXMgb2YgY2l0aWVzLCBzdHJlZXRzIGV0Yy4gY2FuIGNoYW5nZSB3aGlsZSB0aGVpciBjb2RlIHN0YXlzIHRoZSBzYW1lXG5jb25zdCB1cGRhdGVOYW1lT25Db25mbGljdCA9IHtcbiAgY29uZmxpY3RDb2x1bW5zOiBbXCJjb2RlXCJdLFxuICB1cGRhdGVDb2x1bW5zOiBbXCJuYW1lXCJdLFxufTtcblxuZXhwb3J0IGNvbnN0IGluc2VydENpdGllcyA9IGFzeW5jIChidWZmZXI6IHN0cmluZ1tdW10pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICByZXR1cm4gYXdhaXQgaW5zZXJ0TXVsdGlwbGVSb3dzKFxuICAgIGV4dHJhY3RLZXlWYWx1ZXNQYWlycyhidWZmZXIsIENvbHVtbi5jaXR5Q29kZSwgW0NvbHVtbi5jaXR5TmFtZV0pLFxuICAgIFwiY2l0eVwiLFxuICAgIFtcImNvZGVcIiwgXCJuYW1lXCJdLFxuICAgIHRydWUsXG4gICAgdXBkYXRlTmFtZU9uQ29uZmxpY3RcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBpbnNlcnREaXN0cmljdHMgPSBhc3luYyAoYnVmZmVyOiBzdHJpbmdbXVtdKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcbiAgcmV0dXJuIGF3YWl0IGluc2VydE11bHRpcGxlUm93cyhcbiAgICBleHRyYWN0S2V5VmFsdWVzUGFpcnMoYnVmZmVyLCBDb2x1bW4uZGlzdHJpY3RDb2RlLCBbXG4gICAgICBDb2x1bW4uY2l0eUNvZGUsXG4gICAgICBDb2x1bW4uZGlzdHJpY3ROYW1lLFxuICAgIF0pLFxuICAgIFwiY2l0eV9kaXN0cmljdFwiLFxuICAgIFtcImNvZGVcIiwgXCJjaXR5X2NvZGVcIiwgXCJuYW1lXCJdLFxuICAgIHRydWUsXG4gICAgdXBkYXRlTmFtZU9uQ29uZmxpY3RcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBpbnNlcnRNdW5pY2lwYWxpdHlQYXJ0cyA9IGFzeW5jIChcbiAgYnVmZmVyOiBzdHJpbmdbXVtdXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICByZXR1cm4gYXdhaXQgaW5zZXJ0TXVsdGlwbGVSb3dzKFxuICAgIGV4dHJhY3RLZXlWYWx1ZXNQYWlycyhidWZmZXIsIENvbHVtbi5tdW5pY2lwYWxpdHlQYXJ0Q29kZSwgW1xuICAgICAgQ29sdW1uLm11bmljaXBhbGl0eVBhcnROYW1lLFxuICAgICAgQ29sdW1uLmNpdHlDb2RlLFxuICAgIF0pLFxuICAgIFwibXVuaWNpcGFsaXR5X3BhcnRcIixcbiAgICBbXCJjb2RlXCIsIFwibmFtZVwiLCBcImNpdHlfY29kZVwiXSxcbiAgICB0cnVlLFxuICAgIHVwZGF0ZU5hbWVPbkNvbmZsaWN0XG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgaW5zZXJ0UHJhZ3VlRGlzdHJpY3RzID0gYXN5bmMgKFxuICBidWZmZXI6IHN0cmluZ1tdW11cbik6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIHJldHVybiBhd2FpdCBpbnNlcnRNdWx0aXBsZVJvd3MoXG4gICAgZXh0cmFjdEtleVZhbHVlc1BhaXJzKGJ1ZmZlciwgQ29sdW1uLnByYWd1ZURpc3RyaWN0Q29kZSwgW1xuICAgICAgQ29sdW1uLnByYWd1ZURpc3RyaWN0TmFtZSxcbiAgICBdKSxcbiAgICBcInByYWd1ZV9kaXN0cmljdFwiLFxuICAgIFtcImNvZGVcIiwgXCJuYW1lXCJdLFxuICAgIHRydWUsXG4gICAgdXBkYXRlTmFtZU9uQ29uZmxpY3RcbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCBpbnNlcnRTdHJlZXRzID0gYXN5bmMgKGJ1ZmZlcjogc3RyaW5nW11bXSk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIHJldHVybiBhd2FpdCBpbnNlcnRNdWx0aXBsZVJvd3MoXG4gICAgZXh0cmFjdEtleVZhbHVlc1BhaXJzKGJ1ZmZlciwgQ29sdW1uLnN0cmVldENvZGUsIFtcbiAgICAgIENvbHVtbi5jaXR5Q29kZSxcbiAgICAgIENvbHVtbi5zdHJlZXROYW1lLFxuICAgIF0pLFxuICAgIFwic3RyZWV0XCIsXG4gICAgW1wiY29kZVwiLCBcImNpdHlfY29kZVwiLCBcIm5hbWVcIl0sXG4gICAgdHJ1ZSxcbiAgICB1cGRhdGVOYW1lT25Db25mbGljdFxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGFyZUFkZHJlc3NQb2ludHNTeW5jZWQgPSBhc3luYyAoKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldEtuZXhEYigpXG4gICAgLmNvdW50KFwiKlwiLCB7IGFzOiBcImNvdW50QWxsXCIgfSlcbiAgICAuZnJvbShcImFkZHJlc3NfcG9pbnRcIilcbiAgICAuZmlyc3QoKTtcbiAgcmV0dXJuIE51bWJlcihyZXN1bHQuY291bnRBbGwpID49IDI5MDAwMDA7IC8vIHRvdGFsIGlzIGFsbW9zdCAzIG1pbGxpb25cbn07XG5cbmNvbnN0IGFkZHJlc3NQb2ludFNlbGVjdCA9IGBcbiAgU0VMRUNUIGEuaWQsIHMubmFtZSBBUyBzdHJlZXRfbmFtZSwgby5uYW1lIEFTIG9iamVjdF90eXBlX25hbWUsIGEuZGVzY3JpcHRpdmVfbnVtYmVyLFxuICAgICAgICBhLm9yaWVudGF0aW9uYWxfbnVtYmVyLCBhLm9yaWVudGF0aW9uYWxfbnVtYmVyX2xldHRlciwgYy5uYW1lIEFTIGNpdHlfbmFtZSxcbiAgICAgICAgbS5uYW1lIEFTIG11bmljaXBhbGl0eV9wYXJ0X25hbWUsIHAubmFtZSBBUyBwcmFndWVfZGlzdHJpY3RfbmFtZSxcbiAgICAgICAgZC5uYW1lIEFTIGRpc3RyaWN0X25hbWUsIGEucG9zdGFsX2NvZGUsIGEud2dzODRfbGF0aXR1ZGUsIGEud2dzODRfbG9uZ2l0dWRlXG4gIEZST00gYWRkcmVzc19wb2ludCBhXG4gIExFRlQgSk9JTiBzdHJlZXQgcyBPTiBhLnN0cmVldF9jb2RlID0gcy5jb2RlXG4gIElOTkVSIEpPSU4gb2JqZWN0X3R5cGUgbyBPTiBvLmlkID0gYS5vYmplY3RfdHlwZV9pZFxuICBJTk5FUiBKT0lOIGNpdHkgYyBPTiBjLmNvZGUgPSBhLmNpdHlfY29kZVxuICBMRUZUIEpPSU4gY2l0eV9kaXN0cmljdCBkIE9OIGEuY2l0eV9kaXN0cmljdF9jb2RlID0gZC5jb2RlXG4gIExFRlQgSk9JTiBwcmFndWVfZGlzdHJpY3QgcCBPTiBhLnByYWd1ZV9kaXN0cmljdF9jb2RlID0gcC5jb2RlXG4gIExFRlQgSk9JTiBtdW5pY2lwYWxpdHlfcGFydCBtIE9OIGEubXVuaWNpcGFsaXR5X3BhcnRfY29kZSA9IG0uY29kZWA7XG5cbmV4cG9ydCBjb25zdCBnZXRBZGRyZXNzUG9pbnRCeUlkID0gYXN5bmMgKFxuICBhZGRyZXNzUG9pbnRJZDogbnVtYmVyXG4pOiBQcm9taXNlPEFkZHJlc3NQb2ludCB8IG51bGw+ID0+IHtcbiAgY29uc3Qgcm93ID0gYXdhaXQgcmF3UXVlcnkoXG4gICAgYCR7YWRkcmVzc1BvaW50U2VsZWN0fVxuICAgICAgV0hFUkUgYS5pZCA9ID9gLFxuICAgIFthZGRyZXNzUG9pbnRJZF1cbiAgKTtcbiAgaWYgKHJvdy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gcm93VG9BZGRyZXNzUG9pbnQocm93WzBdKTtcbn07XG5cbmxldCBsYXN0Rm91bmRlcjogRm91bmRlciB8IG51bGwgPSBudWxsO1xubGV0IGFsbFN0cmVldHM6IHN0cmluZ1tdID0gW107XG5cbmV4cG9ydCBjb25zdCBjaGVja1N0cmVldEV4aXN0cyA9IGFzeW5jIChcbiAgc3RyZWV0TmFtZTogc3RyaW5nLFxuICBmb3VuZGVyOiBGb3VuZGVyXG4pOiBQcm9taXNlPHsgZXhpc3RzOiBib29sZWFuOyBlcnJvcnM6IFNtZEVycm9yW10gfT4gPT4ge1xuICBjb25zdCBrbmV4ID0gZ2V0S25leERiKCk7XG4gIGNvbnN0IGVycm9yczogU21kRXJyb3JbXSA9IFtdO1xuXG4gIC8vIHdlIGNoZWNrIHRoZSB3aG9sZSBjaXR5XG4gIGNvbnN0IGNpdHlDb2RlID0gYXdhaXQgZ2V0Rm91bmRlckNpdHlDb2RlKFxuICAgIGZvdW5kZXIubXVuaWNpcGFsaXR5VHlwZSxcbiAgICBmb3VuZGVyLm11bmljaXBhbGl0eUNvZGVcbiAgKTtcbiAgY29uc3Qgcm93TGlzdCA9IGF3YWl0IHJhd1F1ZXJ5KFxuICAgIGBTRUxFQ1QgbmFtZSBBUyBzdHJlZXRfbmFtZVxuICAgIEZST00gc3RyZWV0XG4gICAgV0hFUkUgY2l0eV9jb2RlID0gPyBBTkQgbmFtZSA9ID8gICR7XG4gICAgICBpc1NxbGl0ZShrbmV4KSA/IFwiQ09MTEFURSBOT0NBU0VcIiA6IFwiXCJcbiAgICB9YCxcbiAgICBbY2l0eUNvZGUsIHN0cmVldE5hbWVdXG4gICk7XG5cbiAgaWYgKHJvd0xpc3QubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IHJvdyA9IHJvd0xpc3RbMF07XG4gICAgaWYgKHJvdy5zdHJlZXRfbmFtZSAhPT0gc3RyZWV0TmFtZSkge1xuICAgICAgLy8gZXJyb3JzLnB1c2goXG4gICAgICAvLyAgIGBTdHJlZXQgJyR7c3RyZWV0TmFtZX0nIGhhcyB3cm9uZyBjYXNlLCBjb3JyZWN0IGNhc2U6ICcke3Jvdy5zdHJlZXRfbmFtZX0nLmBcbiAgICAgIC8vICk7XG4gICAgfVxuICAgIHJldHVybiB7IGV4aXN0czogdHJ1ZSwgZXJyb3JzIH07XG4gIH1cblxuICBpZiAobGFzdEZvdW5kZXIgIT09IGZvdW5kZXIpIHtcbiAgICBhbGxTdHJlZXRzID0gYXdhaXQgZ2V0QWxsU3RyZWV0cyhjaXR5Q29kZSk7XG4gICAgbGFzdEZvdW5kZXIgPSBmb3VuZGVyO1xuICB9XG5cbiAgY29uc3QgbWF0Y2ggPSBhbGxTdHJlZXRzLmZpbmQoXG4gICAgKHMpID0+XG4gICAgICBzLnRvTG9jYWxlTG93ZXJDYXNlKFwiY3MtQ1pcIikgPT09IHN0cmVldE5hbWUudG9Mb2NhbGVMb3dlckNhc2UoXCJjcy1DWlwiKVxuICApO1xuICBsZXQgZXhpc3RzID0gZmFsc2U7XG4gIGlmIChtYXRjaCkge1xuICAgIGV4aXN0cyA9IHRydWU7XG4gICAgaWYgKHN0cmVldE5hbWUgIT09IG1hdGNoKSB7XG4gICAgICAvLyBlcnJvcnMucHVzaChcbiAgICAgIC8vICAgYFN0cmVldCAnJHtzdHJlZXROYW1lfScgaGFzIHdyb25nIGNhc2UsIGNvcnJlY3QgY2FzZTogJyR7bWF0Y2h9Jy5gXG4gICAgICAvLyApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zdCBjbG9zZXN0ID0gZmluZENsb3Nlc3RTdHJpbmcoc3RyZWV0TmFtZSwgYWxsU3RyZWV0cyk7XG4gICAgZXJyb3JzLnB1c2goe1xuICAgICAgbWVzc2FnZTogYFVsaWNlICcke3N0cmVldE5hbWV9JyB2IHTDqXRvIG9iY2kgbmVleGlzdHVqZSwgbXlzbGVsaSBqc3RlICcke2Nsb3Nlc3R9Jz9gLFxuICAgICAgc3RhcnRPZmZzZXQ6IDAsXG4gICAgICBlbmRPZmZzZXQ6IHN0cmVldE5hbWUubGVuZ3RoICsgMSxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4geyBleGlzdHM6IGZhbHNlLCBlcnJvcnMgfTtcbn07XG5cbmNvbnN0IGdldEFsbFN0cmVldHMgPSBhc3luYyAoY2l0eUNvZGU6IG51bWJlcik6IFByb21pc2U8c3RyaW5nW10+ID0+IHtcbiAgY29uc3Qga25leCA9IGdldEtuZXhEYigpO1xuICByZXR1cm4gYXdhaXQga25leC5wbHVjayhcIm5hbWVcIikuZnJvbShcInN0cmVldFwiKS53aGVyZShcImNpdHlfY29kZVwiLCBjaXR5Q29kZSk7XG59O1xuXG5leHBvcnQgdHlwZSBGaW5kQWRkcmVzc1BvaW50c1BhcmFtcyA9XG4gIHwge1xuICAgICAgdHlwZTogXCJzbWRMaW5lXCI7XG4gICAgICBzbWRMaW5lOiBTbWRMaW5lO1xuICAgICAgbXVuaWNpcGFsaXR5OiBNdW5pY2lwYWxpdHk7XG4gICAgICBtdW5pY2lwYWxpdHlQYXJ0Q29kZT86IG51bWJlcjtcbiAgICB9XG4gIHwge1xuICAgICAgdHlwZTogXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIjtcbiAgICAgIG11bmljaXBhbGl0eVBhcnRDb2RlOiBudW1iZXI7XG4gICAgfVxuICB8IHtcbiAgICAgIHR5cGU6IFwid2hvbGVNdW5pY2lwYWxpdHlcIjtcbiAgICAgIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5O1xuICAgIH1cbiAgfCB7XG4gICAgICB0eXBlOiBcIndob2xlTXVuaWNpcGFsaXR5Tm9TdHJlZXROYW1lXCI7XG4gICAgICBtdW5pY2lwYWxpdHk6IE11bmljaXBhbGl0eTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgZmluZEFkZHJlc3NQb2ludHMgPSBhc3luYyAoXG4gIHBhcmFtczogRmluZEFkZHJlc3NQb2ludHNQYXJhbXNcbik6IFByb21pc2U8QWRkcmVzc1BvaW50W10+ID0+IHtcbiAgY29uc3QgcXVlcnlQYXJhbXMgPSBnZXRRdWVyeVBhcmFtcyhwYXJhbXMpO1xuICBjb25zdCBzdHJlZXRKb2luQ29uZGl0aW9uID0gZ2V0U3RyZWV0Sm9pbkNvbmRpdGlvbihwYXJhbXMpO1xuXG4gIGNvbnN0IHdoZXJlQ29uZGl0aW9uID0gZ2V0V2hlcmVDb25kaXRpb24ocGFyYW1zKTtcblxuICBjb25zdCBxdWVyeVJlc3VsdCA9IGF3YWl0IHJhd1F1ZXJ5KFxuICAgIGBTRUxFQ1QgYS5pZCwgcy5uYW1lIEFTIHN0cmVldF9uYW1lLCBvLm5hbWUgQVMgb2JqZWN0X3R5cGVfbmFtZSwgYS5kZXNjcmlwdGl2ZV9udW1iZXIsXG4gICAgICBhLm9yaWVudGF0aW9uYWxfbnVtYmVyLCBhLm9yaWVudGF0aW9uYWxfbnVtYmVyX2xldHRlciwgYy5uYW1lIEFTIGNpdHlfbmFtZSxcbiAgICAgIGQubmFtZSBBUyBkaXN0cmljdF9uYW1lLCBtLm5hbWUgQVMgbXVuaWNpcGFsaXR5X3BhcnRfbmFtZSwgcC5uYW1lIEFTIHByYWd1ZV9kaXN0cmljdF9uYW1lLFxuICAgICAgYS5wb3N0YWxfY29kZSwgYS53Z3M4NF9sYXRpdHVkZSwgYS53Z3M4NF9sb25naXR1ZGVcbiAgICBGUk9NIGFkZHJlc3NfcG9pbnQgYVxuICAgICR7c3RyZWV0Sm9pbkNvbmRpdGlvbn1cbiAgICBJTk5FUiBKT0lOIG9iamVjdF90eXBlIG8gT04gby5pZCA9IGEub2JqZWN0X3R5cGVfaWRcbiAgICBJTk5FUiBKT0lOIGNpdHkgYyBPTiBjLmNvZGUgPSBhLmNpdHlfY29kZVxuICAgIExFRlQgSk9JTiBjaXR5X2Rpc3RyaWN0IGQgT04gYS5jaXR5X2Rpc3RyaWN0X2NvZGUgPSBkLmNvZGVcbiAgICBMRUZUIEpPSU4gbXVuaWNpcGFsaXR5X3BhcnQgbSBPTiBhLm11bmljaXBhbGl0eV9wYXJ0X2NvZGUgPSBtLmNvZGVcbiAgICBMRUZUIEpPSU4gcHJhZ3VlX2Rpc3RyaWN0IHAgT04gYS5wcmFndWVfZGlzdHJpY3RfY29kZSA9IHAuY29kZVxuICAgIFdIRVJFICR7d2hlcmVDb25kaXRpb259YCxcbiAgICBxdWVyeVBhcmFtc1xuICApO1xuXG4gIHJldHVybiBmaWx0ZXJBZGRyZXNzUG9pbnRzKHF1ZXJ5UmVzdWx0Lm1hcChyb3dUb0FkZHJlc3NQb2ludCksIHBhcmFtcyk7XG59O1xuXG5leHBvcnQgY29uc3QgZmlsdGVyQWRkcmVzc1BvaW50cyA9IChcbiAgYWRkcmVzc1BvaW50czogQWRkcmVzc1BvaW50W10sXG4gIHBhcmFtczogRmluZEFkZHJlc3NQb2ludHNQYXJhbXNcbik6IEFkZHJlc3NQb2ludFtdID0+IHtcbiAgaWYgKFxuICAgIHBhcmFtcy50eXBlID09PSBcIndob2xlTXVuaWNpcGFsaXR5XCIgfHxcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eU5vU3RyZWV0TmFtZVwiIHx8XG4gICAgcGFyYW1zLnR5cGUgPT09IFwid2hvbGVNdW5pY2lwYWxpdHlQYXJ0XCJcbiAgKSB7XG4gICAgcmV0dXJuIGFkZHJlc3NQb2ludHM7XG4gIH1cblxuICBjb25zdCByZXN1bHQ6IEFkZHJlc3NQb2ludFtdID0gW107XG4gIGNvbnN0IG51bWJlclNwZWMgPSBwYXJhbXMuc21kTGluZS5udW1iZXJTcGVjO1xuICBpZiAoaXNTZXJpZXNTcGVjQXJyYXkobnVtYmVyU3BlYykpIHtcbiAgICBudW1iZXJTcGVjLmZvckVhY2goKHNlcmllc1NwZWMpID0+IHtcbiAgICAgIHJlc3VsdC5wdXNoKC4uLmZpbHRlckFkZHJlc3NQb2ludHNCeVJhbmdlcyhhZGRyZXNzUG9pbnRzLCBzZXJpZXNTcGVjKSk7XG4gICAgfSk7XG5cbiAgICAvLyB3aGVuIG5vIG51bWJlciBzcGVjcyBhcmUgcHJlc2VudCwgd2UgdGFrZSBldmVyeXRoaW5nXG4gICAgaWYgKG51bWJlclNwZWMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXN1bHQucHVzaCguLi5hZGRyZXNzUG9pbnRzKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNOZWdhdGl2ZVNlcmllc1NwZWMobnVtYmVyU3BlYykpIHtcbiAgICAvLyBuZWdhdGl2ZSBudW1iZXIgc3BlYyAoZS5nLiBvZGQgbnVtYmVycyBleGNlcHQgMTMtMTcpXG4gICAgY29uc3QgdG9FeGNsdWRlID0gZmlsdGVyQWRkcmVzc1BvaW50c0J5UmFuZ2VzKGFkZHJlc3NQb2ludHMsIG51bWJlclNwZWMpO1xuICAgIHJlc3VsdC5wdXNoKFxuICAgICAgLi4uYWRkcmVzc1BvaW50cy5maWx0ZXIoXG4gICAgICAgIChhZGRyZXNzUG9pbnQpID0+ICF0b0V4Y2x1ZGUuaW5jbHVkZXMoYWRkcmVzc1BvaW50KVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuY29uc3QgZmlsdGVyQWRkcmVzc1BvaW50c0J5UmFuZ2VzID0gKFxuICBhZGRyZXNzUG9pbnRzOiBBZGRyZXNzUG9pbnRbXSxcbiAgc2VyaWVzU3BlYzogU2VyaWVzU3BlY1xuKTogQWRkcmVzc1BvaW50W10gPT4ge1xuICBjb25zdCByZXN1bHQ6IEFkZHJlc3NQb2ludFtdID0gW107XG4gIHNlcmllc1NwZWMucmFuZ2VzLmZvckVhY2goKHJhbmdlKSA9PiB7XG4gICAgcmVzdWx0LnB1c2goXG4gICAgICAuLi5hZGRyZXNzUG9pbnRzLmZpbHRlcigoYWRkcmVzc1BvaW50KSA9PiB7XG4gICAgICAgIGlmIChpc1JhbmdlKHJhbmdlKSkge1xuICAgICAgICAgIGNvbnN0IG51bWJlciA9IGdldE51bWJlckJ5VHlwZShzZXJpZXNTcGVjLnR5cGUsIGFkZHJlc3NQb2ludCk7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGlzSW5SYW5nZShcbiAgICAgICAgICAgICAgbnVtYmVyLFxuICAgICAgICAgICAgICBzZXJpZXNTcGVjLnR5cGUgIT09IFNlcmllc1R5cGUuRGVzY3JpcHRpb25cbiAgICAgICAgICAgICAgICA/IGFkZHJlc3NQb2ludC5vcmllbnRhdGlvbmFsTnVtYmVyTGV0dGVyID8/IG51bGxcbiAgICAgICAgICAgICAgICA6IG51bGwsXG4gICAgICAgICAgICAgIHJhbmdlXG4gICAgICAgICAgICApICYmIGZpdHNUeXBlKG51bWJlciwgc2VyaWVzU3BlYy50eXBlKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgZnVsbFN0cmVldE51bWJlcjogRnVsbFN0cmVldE51bWJlciA9IHJhbmdlO1xuICAgICAgICAgIHJldHVybiBlcXVhbHNGdWxsU3RyZWV0TnVtYmVyKGZ1bGxTdHJlZXROdW1iZXIsIGFkZHJlc3NQb2ludCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfSk7XG5cbiAgLy8gd2hlbiBubyBzZXJpZXMgc3BlY3MgYXJlIHByZXNlbnQsIHdlIHRha2UgZXZlcnl0aGluZyB0aGF0IGZpdHMgdGhlIHR5cGVcbiAgaWYgKHNlcmllc1NwZWMucmFuZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlc3VsdC5wdXNoKFxuICAgICAgLi4uYWRkcmVzc1BvaW50cy5maWx0ZXIoKGFkZHJlc3NQb2ludCkgPT5cbiAgICAgICAgZml0c1R5cGUoXG4gICAgICAgICAgZ2V0TnVtYmVyQnlUeXBlKHNlcmllc1NwZWMudHlwZSwgYWRkcmVzc1BvaW50KSxcbiAgICAgICAgICBzZXJpZXNTcGVjLnR5cGVcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFF1ZXJ5UGFyYW1zID0gKFxuICBwYXJhbXM6IEZpbmRBZGRyZXNzUG9pbnRzUGFyYW1zXG4pOiAoc3RyaW5nIHwgbnVtYmVyKVtdID0+IHtcbiAgaWYgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcInN0cmVldFwiKSB7XG4gICAgcmV0dXJuIFtwYXJhbXMuc21kTGluZS5zdHJlZXQsIHBhcmFtcy5tdW5pY2lwYWxpdHkuY29kZV07XG4gIH1cblxuICBpZiAoXG4gICAgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcIm11bmljaXBhbGl0eVBhcnRcIikgfHxcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIlxuICApIHtcbiAgICByZXR1cm4gW3BhcmFtcy5tdW5pY2lwYWxpdHlQYXJ0Q29kZV07XG4gIH1cblxuICByZXR1cm4gW3BhcmFtcy5tdW5pY2lwYWxpdHkuY29kZV07XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0U3RyZWV0Sm9pbkNvbmRpdGlvbiA9IChcbiAgcGFyYW1zOiBGaW5kQWRkcmVzc1BvaW50c1BhcmFtc1xuKTogc3RyaW5nID0+IHtcbiAgaWYgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcInN0cmVldFwiKSB7XG4gICAgcmV0dXJuIGBKT0lOIHN0cmVldCBzIE9OIGEuc3RyZWV0X2NvZGUgPSBzLmNvZGUgQU5EIHMubmFtZSA9ID8gJHtcbiAgICAgIGlzU3FsaXRlKGdldEtuZXhEYigpKSA/IFwiQ09MTEFURSBOT0NBU0VcIiA6IFwiXCJcbiAgICB9YDtcbiAgfVxuICByZXR1cm4gXCJMRUZUIEpPSU4gc3RyZWV0IHMgT04gYS5zdHJlZXRfY29kZSA9IHMuY29kZVwiO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFdoZXJlQ29uZGl0aW9uID0gKHBhcmFtczogRmluZEFkZHJlc3NQb2ludHNQYXJhbXMpOiBzdHJpbmcgPT4ge1xuICBpZiAoXG4gICAgKHBhcmFtcy50eXBlID09PSBcInNtZExpbmVcIiAmJiBwYXJhbXMuc21kTGluZS50eXBlID09PSBcIm11bmljaXBhbGl0eVBhcnRcIikgfHxcbiAgICBwYXJhbXMudHlwZSA9PT0gXCJ3aG9sZU11bmljaXBhbGl0eVBhcnRcIlxuICApIHtcbiAgICByZXR1cm4gXCJhLm11bmljaXBhbGl0eV9wYXJ0X2NvZGUgPSA/XCI7XG4gIH1cblxuICBpZiAocGFyYW1zLnR5cGUgPT09IFwid2hvbGVNdW5pY2lwYWxpdHlOb1N0cmVldE5hbWVcIikge1xuICAgIHJldHVybiBgJHtnZXRNdW5pY2lwYWxpdHlXaGVyZShcbiAgICAgIFwiYVwiLFxuICAgICAgcGFyYW1zLm11bmljaXBhbGl0eVxuICAgICl9IEFORCBhLnN0cmVldF9jb2RlIElTIE5VTExgO1xuICB9XG5cbiAgcmV0dXJuIGdldE11bmljaXBhbGl0eVdoZXJlKFwiYVwiLCBwYXJhbXMubXVuaWNpcGFsaXR5KTtcbn07XG5cbmV4cG9ydCBjb25zdCBpc0luUmFuZ2UgPSAoXG4gIG51bWJlcjogbnVtYmVyIHwgbnVsbCxcbiAgbGV0dGVyOiBzdHJpbmcgfCBudWxsLFxuICByYW5nZTogUmFuZ2VTcGVjXG4pOiBib29sZWFuID0+IHtcbiAgaWYgKG51bWJlciA9PT0gbnVsbCkge1xuICAgIHJldHVybiAhcmFuZ2UuZnJvbSAmJiAhcmFuZ2UudG87XG4gIH1cblxuICAvLyBleHBsYWluZXI6IGVpdGhlciB0aGUgbG93ZXIgYm91bmQgaXMgbm90IHNldCwgb3IgaXQgaXMgbG93ZXIgdGhhbiB0aGUgbnVtYmVyXG4gIC8vIGlmIGl0J3MgZXF1YWwgdG8gdGhlIG51bWJlciwgd2UgYWxzbyBoYXZlIHRvIGNoZWNrIHRoZSBsZXR0ZXIgLSBpZiBpdCdzIG5vdCBzZXQsIHdlIGRvbid0IGNhcmVcbiAgLy8gaWYgZnJvbS5sZXR0ZXIgaXMgc2V0LCB3ZSBuZWVkIHRvIGhhdmUgYSBsZXR0ZXIgc2V0IGFuZCBpdCBoYXMgdG8gYmUgZ3JlYXRlciBvciBlcXVhbDpcbiAgLy8gbnVtYmVyIHdpdGhvdXQgbGV0dGVyIGNvdW50cyBsb3dlciB0aGFuIG51bWJlciB3aXRoIGxldHRlciAnYScgKGUuZy4gMjMgPCAyM2EpXG4gIGNvbnN0IHNhdGlzZmllc0Zyb20gPVxuICAgICFyYW5nZS5mcm9tIHx8XG4gICAgbnVtYmVyID4gcmFuZ2UuZnJvbS5udW1iZXIgfHxcbiAgICAobnVtYmVyID09PSByYW5nZS5mcm9tLm51bWJlciAmJlxuICAgICAgKCFyYW5nZS5mcm9tLmxldHRlciB8fCAoISFsZXR0ZXIgJiYgbGV0dGVyID49IHJhbmdlLmZyb20ubGV0dGVyKSkpO1xuXG4gIGNvbnN0IHNhdGlzZmllc1RvID1cbiAgICAhcmFuZ2UudG8gfHxcbiAgICBudW1iZXIgPCByYW5nZS50by5udW1iZXIgfHxcbiAgICAobnVtYmVyID09PSByYW5nZS50by5udW1iZXIgJiZcbiAgICAgICghbGV0dGVyIHx8XG4gICAgICAgICghIXJhbmdlLnRvLmxldHRlciAmJiAhIWxldHRlciAmJiBsZXR0ZXIgPD0gcmFuZ2UudG8ubGV0dGVyKSkpO1xuXG4gIHJldHVybiBzYXRpc2ZpZXNGcm9tICYmIHNhdGlzZmllc1RvO1xufTtcblxuZXhwb3J0IGNvbnN0IGZpdHNUeXBlID0gKG51bWJlcjogbnVtYmVyIHwgbnVsbCwgdHlwZTogU2VyaWVzVHlwZSk6IGJvb2xlYW4gPT4ge1xuICByZXR1cm4gKFxuICAgIHR5cGUgPT09IFNlcmllc1R5cGUuRGVzY3JpcHRpb24gfHxcbiAgICB0eXBlID09PSBTZXJpZXNUeXBlLkFsbCB8fFxuICAgIC8vIGEgbWlzc2luZyBudW1iZXIgKGUuZy4gbm8gb3JpZW50YXRpb25hbCBudW1iZXIpIGlzIG5laXRoZXIgb2RkIG5vciBldmVuLFxuICAgIC8vIGNhcmVmdWw6IG51bGwgJSAyID09PSAwIGluIEpTXG4gICAgKHR5cGUgPT09IFNlcmllc1R5cGUuT2RkICYmIG51bWJlciAhPT0gbnVsbCAmJiBudW1iZXIgJSAyID09PSAxKSB8fFxuICAgICh0eXBlID09PSBTZXJpZXNUeXBlLkV2ZW4gJiYgbnVtYmVyICE9PSBudWxsICYmIG51bWJlciAlIDIgPT09IDApXG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgZXF1YWxzRnVsbFN0cmVldE51bWJlciA9IChcbiAgZnVsbFN0cmVldE51bWJlcjogRnVsbFN0cmVldE51bWJlcixcbiAgYWRkcmVzc1BvaW50OiBBZGRyZXNzUG9pbnRcbik6IGJvb2xlYW4gPT4ge1xuICByZXR1cm4gKFxuICAgIGZ1bGxTdHJlZXROdW1iZXIuZGVzY3JpcHRpb25OdW1iZXIubnVtYmVyID09PSBhZGRyZXNzUG9pbnQuaG91c2VOdW1iZXIgJiZcbiAgICBmdWxsU3RyZWV0TnVtYmVyLm9yaWVudGF0aW9uYWxOdW1iZXIubnVtYmVyID09PVxuICAgICAgYWRkcmVzc1BvaW50Lm9yaWVudGF0aW9uYWxOdW1iZXIgJiZcbiAgICAoKCFmdWxsU3RyZWV0TnVtYmVyLm9yaWVudGF0aW9uYWxOdW1iZXIubGV0dGVyICYmXG4gICAgICAhYWRkcmVzc1BvaW50Lm9yaWVudGF0aW9uYWxOdW1iZXJMZXR0ZXIpIHx8XG4gICAgICBmdWxsU3RyZWV0TnVtYmVyLm9yaWVudGF0aW9uYWxOdW1iZXIubGV0dGVyID09PVxuICAgICAgICBhZGRyZXNzUG9pbnQub3JpZW50YXRpb25hbE51bWJlckxldHRlcilcbiAgKTtcbn07XG5cbmNvbnN0IGdldE51bWJlckJ5VHlwZSA9IChcbiAgdHlwZTogU2VyaWVzVHlwZSxcbiAgYWRkcmVzc1BvaW50OiBBZGRyZXNzUG9pbnRcbik6IG51bWJlciB8IG51bGwgPT4ge1xuICByZXR1cm4gdHlwZSA9PT0gU2VyaWVzVHlwZS5EZXNjcmlwdGlvblxuICAgID8gYWRkcmVzc1BvaW50LmhvdXNlTnVtYmVyXG4gICAgOiBhZGRyZXNzUG9pbnQub3JpZW50YXRpb25hbE51bWJlciA/PyBudWxsO1xufTtcblxuY29uc3QgZ2V0TXVuaWNpcGFsaXR5V2hlcmUgPSAoXG4gIGFsaWFzOiBzdHJpbmcsXG4gIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5XG4pOiBzdHJpbmcgPT4ge1xuICByZXR1cm4gbXVuaWNpcGFsaXR5LnR5cGUgPT09IE11bmljaXBhbGl0eVR5cGUuQ2l0eVxuICAgID8gYCR7YWxpYXN9LmNpdHlfY29kZSA9ID9gXG4gICAgOiBgJHthbGlhc30uY2l0eV9kaXN0cmljdF9jb2RlID0gP2A7XG59O1xuXG5jb25zdCByb3dUb0FkZHJlc3NQb2ludCA9IChyb3c6IGFueSk6IEFkZHJlc3NQb2ludCA9PiB7XG4gIGNvbnN0IHBvaW50OiBBZGRyZXNzUG9pbnQgPSB7XG4gICAgaWQ6IHJvdy5pZCxcbiAgICBhZGRyZXNzOiBcIlwiLFxuICAgIHR5cGU6XG4gICAgICByb3cub2JqZWN0X3R5cGVfbmFtZSA9PT0gRGVzY3JpcHRpdmVUeXBlXG4gICAgICAgID8gQWRkcmVzc1BvaW50VHlwZS5EZXNjcmlwdGlvblxuICAgICAgICA6IEFkZHJlc3NQb2ludFR5cGUuUmVnaXN0cmF0aW9uLFxuICAgIGhvdXNlTnVtYmVyOiByb3cuZGVzY3JpcHRpdmVfbnVtYmVyLFxuICAgIGNpdHk6IHJvdy5jaXR5X25hbWUsXG4gICAgbXVuaWNpcGFsaXR5UGFydDogcm93Lm11bmljaXBhbGl0eV9wYXJ0X25hbWUsXG4gICAgcG9zdGFsQ29kZTogcm93LnBvc3RhbF9jb2RlLFxuICAgIGxhdDogcm93Lndnczg0X2xhdGl0dWRlLFxuICAgIGxuZzogcm93Lndnczg0X2xvbmdpdHVkZSxcbiAgfTtcbiAgaWYgKHJvdy5zdHJlZXRfbmFtZSAhPT0gbnVsbCkge1xuICAgIHBvaW50LnN0cmVldCA9IHJvdy5zdHJlZXRfbmFtZTtcbiAgfVxuICBpZiAocm93Lm9yaWVudGF0aW9uYWxfbnVtYmVyICE9PSBudWxsKSB7XG4gICAgcG9pbnQub3JpZW50YXRpb25hbE51bWJlciA9IHJvdy5vcmllbnRhdGlvbmFsX251bWJlcjtcbiAgfVxuICBpZiAocm93Lm9yaWVudGF0aW9uYWxfbnVtYmVyX2xldHRlciAhPT0gbnVsbCkge1xuICAgIHBvaW50Lm9yaWVudGF0aW9uYWxOdW1iZXJMZXR0ZXIgPSByb3cub3JpZW50YXRpb25hbF9udW1iZXJfbGV0dGVyO1xuICB9XG4gIGlmIChyb3cuZGlzdHJpY3RfbmFtZSAhPT0gbnVsbCkge1xuICAgIHBvaW50LmRpc3RyaWN0ID0gcm93LmRpc3RyaWN0X25hbWU7XG4gIH1cbiAgaWYgKHJvdy5wcmFndWVfZGlzdHJpY3RfbmFtZSAhPT0gbnVsbCkge1xuICAgIHBvaW50LnByYWd1ZURpc3RyaWN0ID0gcm93LnByYWd1ZV9kaXN0cmljdF9uYW1lO1xuICB9XG4gIHBvaW50LmFkZHJlc3MgPSBjcmVhdGVTaW5nbGVMaW5lQWRkcmVzcyhwb2ludCk7XG4gIHJldHVybiBwb2ludDtcbn07XG4iXX0=