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,261 +1,261 @@
1
- import { Delaunay } from "d3-delaunay";
2
- import { featureCollection, } from "@turf/helpers";
3
- import intersect from "@turf/intersect";
4
- import { booleanIntersects } from "@turf/boolean-intersects";
5
- import Graph from "graphology";
6
- import { color } from "graphology-color";
7
- import { toMercator, toWgs84 } from "@turf/projection";
8
- import union from "@turf/union";
9
- import { getCityPolygons, getDistrictPolygons } from "../db/cities";
10
- import truncate from "@turf/truncate";
11
- import difference from "@turf/difference";
12
- export const municipalitiesToPolygons = async (municipalities) => {
13
- const { cityCodes, districtCodes } = extractMunicipalityCodes(municipalities);
14
- const cityPolygons = await getCityPolygons(cityCodes);
15
- const districtPolygons = await getDistrictPolygons(districtCodes);
16
- if (Object.keys(cityPolygons).length === 0 &&
17
- Object.keys(districtPolygons).length === 0) {
18
- console.log("No polygons found for given municipalities.");
19
- return {};
20
- }
21
- // municipalityCode -> areas
22
- const extraAreas = getExtraAreas(municipalities);
23
- const collectionMap = new Map();
24
- // areaIndex -> polygon
25
- const extraPolygonsMap = new Map();
26
- for (const municipality of municipalities) {
27
- if (municipality.areas.length === 0) {
28
- continue;
29
- }
30
- const { featureCollection, extraPolygons } = createPolygons(municipality, extraAreas.get(municipality.code) ?? [], getMunicipalityPolygons(municipality, cityPolygons, districtPolygons));
31
- collectionMap.set(municipality.code, featureCollection);
32
- if (extraAreas.has(municipality.code)) {
33
- for (const [areaIndex, extraPolygon] of extraPolygons) {
34
- if (!extraPolygonsMap.has(areaIndex)) {
35
- extraPolygonsMap.set(areaIndex, []);
36
- }
37
- extraPolygonsMap.get(areaIndex).push(extraPolygon);
38
- }
39
- }
40
- }
41
- addExtraPolygons(collectionMap, extraPolygonsMap);
42
- findColoring(collectionMap);
43
- const result = {};
44
- for (const [municipalityCode, collection] of collectionMap) {
45
- result[municipalityCode] = collection;
46
- }
47
- return result;
48
- };
49
- const findColoring = (collectionMap) => {
50
- // put all the features in one array
51
- const allFeatures = Array.from(collectionMap.values()).reduce((acc, collection) => {
52
- acc.push(...collection.features);
53
- return acc;
54
- }, []);
55
- if (allFeatures.length <= 5) {
56
- allFeatures.forEach((feature, index) => {
57
- feature.properties.colorIndex = index;
58
- });
59
- return;
60
- }
61
- const graph = new Graph();
62
- allFeatures.forEach((feature) => {
63
- graph.addNode(feature.properties.areaIndex);
64
- });
65
- for (const feature1 of allFeatures) {
66
- for (const feature2 of allFeatures) {
67
- if (feature1.properties.areaIndex !== feature2.properties.areaIndex &&
68
- booleanIntersects(feature1, feature2)) {
69
- graph.addEdge(feature1.properties.areaIndex, feature2.properties.areaIndex);
70
- }
71
- }
72
- }
73
- color(graph);
74
- allFeatures.forEach((feature) => {
75
- feature.properties.colorIndex = graph.getNodeAttribute(feature.properties.areaIndex, "color");
76
- });
77
- };
78
- const getExtraAreas = (municipalities) => {
79
- // municipalityCode -> areas
80
- const extraAreas = new Map();
81
- for (const municipality of municipalities) {
82
- for (const area of municipality.areas) {
83
- // municipalityCode -> points
84
- const extraPoints = new Map();
85
- for (const point of area.addresses) {
86
- if (point.municipalityCode) {
87
- if (!extraPoints.has(point.municipalityCode)) {
88
- extraPoints.set(point.municipalityCode, []);
89
- }
90
- extraPoints.get(point.municipalityCode).push(point);
91
- }
92
- }
93
- for (const [municipalityCode, points] of extraPoints) {
94
- if (!extraAreas.has(municipalityCode)) {
95
- extraAreas.set(municipalityCode, []);
96
- }
97
- extraAreas.get(municipalityCode).push({
98
- ...area,
99
- addresses: points,
100
- });
101
- }
102
- }
103
- }
104
- return extraAreas;
105
- };
106
- const addExtraPolygons = (collectionMap, extraPolygonsMap) => {
107
- for (const collection of collectionMap.values()) {
108
- for (let i = 0; i < collection.features.length; i++) {
109
- const feature = collection.features[i];
110
- if (extraPolygonsMap.has(feature.properties.areaIndex)) {
111
- const polygons = extraPolygonsMap.get(feature.properties.areaIndex);
112
- const newPolygon = union(featureCollection([...polygons, feature]));
113
- const newFeature = {
114
- ...newPolygon,
115
- properties: { ...feature.properties },
116
- };
117
- collection.features[i] = newFeature;
118
- }
119
- }
120
- }
121
- };
122
- const getMunicipalityPolygons = (municipality, cityPolygons, districtPolygons) => {
123
- const polygons = {};
124
- for (const cityCode of municipality.cityCodes) {
125
- if (cityPolygons[cityCode]) {
126
- polygons[cityCode] = cityPolygons[cityCode];
127
- if (municipality.municipalityType === "city" &&
128
- Object.keys(districtPolygons).length > 0 &&
129
- municipality.municipalityName !== "Brno") {
130
- let cityPolygon = extractPolygonFromCollection(cityPolygons[cityCode]);
131
- // subtract all district polygons from city polygon
132
- for (const [districtCode, districtPolygon] of Object.entries(districtPolygons)) {
133
- if (municipality.districtCodes.includes(parseInt(districtCode))) {
134
- continue;
135
- }
136
- cityPolygon = difference(featureCollection([
137
- cityPolygon,
138
- extractPolygonFromCollection(districtPolygon),
139
- ]));
140
- }
141
- polygons[cityCode] = featureCollection([cityPolygon]);
142
- }
143
- }
144
- }
145
- for (const districtCode of municipality.districtCodes) {
146
- if (districtPolygons[districtCode]) {
147
- polygons[districtCode] = districtPolygons[districtCode];
148
- }
149
- }
150
- return polygons;
151
- };
152
- export const createPolygons = (municipality, extraAreas, municipalityPolygons) => {
153
- const municipalitiesMultipolygon = createMunicipalitiesMultipolygon(Object.values(municipalityPolygons));
154
- const uniquePoints = new Map();
155
- const allAreas = [...municipality.areas, ...extraAreas];
156
- const extraAreasIndexes = new Set(extraAreas.map((area) => area.index));
157
- for (const area of allAreas) {
158
- const points = [...area.addresses];
159
- for (const point of points) {
160
- if (!uniquePoints.has(point.address)) {
161
- addPoint(uniquePoints, point, area.index);
162
- }
163
- else {
164
- uniquePoints.get(point.address).properties.areaIndexes.push(area.index);
165
- }
166
- }
167
- }
168
- const points = {
169
- type: "FeatureCollection",
170
- features: Array.from(uniquePoints.values()),
171
- };
172
- const polygons = d3DelaunayVoronoi(points);
173
- const unitedPolygons = [];
174
- const extraPolygons = new Map();
175
- let colorIndex = 0;
176
- for (const area of allAreas) {
177
- const schoolPolygons = polygons.features.filter((polygon) => polygon.properties.areaIndexes.includes(area.index));
178
- if (schoolPolygons.length === 0) {
179
- continue;
180
- }
181
- const schoolPolygon = intersect(schoolPolygons.length > 1
182
- ? union(featureCollection(schoolPolygons))
183
- : schoolPolygons[0], municipalitiesMultipolygon);
184
- const feature = {
185
- ...schoolPolygon,
186
- properties: {
187
- areaIndex: area.index,
188
- schoolIzos: area.schools.map((school) => school.izo),
189
- colorIndex,
190
- },
191
- };
192
- if (extraAreasIndexes.has(area.index)) {
193
- extraPolygons.set(area.index, feature);
194
- }
195
- else {
196
- unitedPolygons.push(feature);
197
- }
198
- colorIndex++;
199
- }
200
- return {
201
- featureCollection: truncate({
202
- type: "FeatureCollection",
203
- features: [...unitedPolygons],
204
- }),
205
- extraPolygons,
206
- };
207
- };
208
- const addPoint = (uniquePoints, point, areaIndex) => {
209
- if (point.lat === null || point.lng === null) {
210
- return;
211
- }
212
- uniquePoints.set(point.address, {
213
- type: "Feature",
214
- geometry: {
215
- type: "Point",
216
- coordinates: [point.lng, point.lat],
217
- },
218
- properties: {
219
- areaIndexes: [areaIndex],
220
- },
221
- });
222
- };
223
- const d3DelaunayVoronoi = (points) => {
224
- const converted = points.features.map((p) => {
225
- return toMercator([p.geometry.coordinates[0], p.geometry.coordinates[1]]);
226
- });
227
- const bbox = [...toMercator([-180, -85]), ...toMercator([180, 85])];
228
- const delaunay = new Delaunay(Float64Array.of(...converted.flat()));
229
- const voronoi = delaunay.voronoi(bbox);
230
- return {
231
- type: "FeatureCollection",
232
- features: Array.from(voronoi.cellPolygons()).map((polygon) => ({
233
- type: "Feature",
234
- geometry: {
235
- type: "Polygon",
236
- coordinates: [polygon.map((p) => toWgs84(p))],
237
- },
238
- properties: {
239
- areaIndexes: points.features[polygon.index].properties.areaIndexes,
240
- index: polygon.index,
241
- neighbors: new Set(voronoi.neighbors(polygon.index)),
242
- },
243
- })),
244
- };
245
- };
246
- const createMunicipalitiesMultipolygon = (municipalityPolygons) => {
247
- const municipalityPolygonFeatures = municipalityPolygons.reduce((acc, municipalityPolygon) => {
248
- acc.push(...municipalityPolygon.features.filter((f) => f.geometry.type === "Polygon" || f.geometry.type === "MultiPolygon"));
249
- return acc;
250
- }, []);
251
- return extractPolygonFromCollection(featureCollection(municipalityPolygonFeatures));
252
- };
253
- const extractMunicipalityCodes = (municipalities) => {
254
- return municipalities.reduce((acc, municipality) => {
255
- municipality.cityCodes.forEach((cityCode) => acc.cityCodes.add(cityCode));
256
- municipality.districtCodes.forEach((districtCode) => acc.districtCodes.add(districtCode));
257
- return acc;
258
- }, { cityCodes: new Set(), districtCodes: new Set() });
259
- };
260
- const extractPolygonFromCollection = (collection) => collection.features.length > 1 ? union(collection) : collection.features[0];
261
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9seWdvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWV0LW1hcmtkb3duL3BvbHlnb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHdkMsT0FBTyxFQU1MLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLFNBQVMsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkQsT0FBTyxLQUFLLE1BQU0sYUFBYSxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEUsT0FBTyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEMsT0FBTyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFRMUMsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxFQUMzQyxjQUE4QixFQUNjLEVBQUU7SUFDOUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM5RSxNQUFNLFlBQVksR0FBRyxNQUFNLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0RCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sbUJBQW1CLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFbEUsSUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQ3RDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FB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QUNsRCxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FDcEMsQ0FBQztRQUNGLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxFQUNELEVBQUUsU0FBUyxFQUFFLElBQUksR0FBRyxFQUFVLEVBQUUsYUFBYSxFQUFFLElBQUksR0FBRyxFQUFVLEVBQUUsQ0FDbkUsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGLE1BQU0sNEJBQTRCLEdBQUcsQ0FDbkMsVUFBcUQsRUFDcEIsRUFBRSxDQUNuQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlbGF1bmF5IH0gZnJvbSBcImQzLWRlbGF1bmF5XCI7XHJcbmltcG9ydCB7IEFyZWEsIEV4cG9ydEFkZHJlc3NQb2ludCwgTXVuaWNpcGFsaXR5IH0gZnJvbSBcIi4vdHlwZXNcIjtcclxuXHJcbmltcG9ydCB7XHJcbiAgRmVhdHVyZSxcclxuICBGZWF0dXJlQ29sbGVjdGlvbixcclxuICBNdWx0aVBvbHlnb24sXHJcbiAgUG9pbnQsXHJcbiAgUG9seWdvbixcclxuICBmZWF0dXJlQ29sbGVjdGlvbixcclxufSBmcm9tIFwiQHR1cmYvaGVscGVyc1wiO1xyXG5pbXBvcnQgaW50ZXJzZWN0IGZyb20gXCJAdHVyZi9pbnRlcnNlY3RcIjtcclxuaW1wb3J0IHsgYm9vbGVhbkludGVyc2VjdHMgfSBmcm9tIFwiQHR1cmYvYm9vbGVhbi1pbnRlcnNlY3RzXCI7XHJcbmltcG9ydCBHcmFwaCBmcm9tIFwiZ3JhcGhvbG9neVwiO1xyXG5pbXBvcnQgeyBjb2xvciB9IGZyb20gXCJncmFwaG9sb2d5LWNvbG9yXCI7XHJcbmltcG9ydCB7IHRvTWVyY2F0b3IsIHRvV2dzODQgfSBmcm9tIFwiQHR1cmYvcHJvamVjdGlvblwiO1xyXG5pbXBvcnQgdW5pb24gZnJvbSBcIkB0dXJmL3VuaW9uXCI7XHJcbmltcG9ydCB7IGdldENpdHlQb2x5Z29ucywgZ2V0RGlzdHJpY3RQb2x5Z29ucyB9IGZyb20gXCIuLi9kYi9jaXRpZXNcIjtcclxuaW1wb3J0IHRydW5jYXRlIGZyb20gXCJAdHVyZi90cnVuY2F0ZVwiO1xyXG5pbXBvcnQgeyBQb2x5Z29uc0J5Q29kZXMgfSBmcm9tIFwiLi4vZGIvdHlwZXNcIjtcclxuaW1wb3J0IGRpZmZlcmVuY2UgZnJvbSBcIkB0dXJmL2RpZmZlcmVuY2VcIjtcclxuXHJcbnR5cGUgUG9seWdvblByb3BzID0ge1xyXG4gIGFyZWFJbmRleGVzOiBudW1iZXJbXTtcclxuICBpbmRleDogbnVtYmVyO1xyXG4gIG5laWdoYm9yczogU2V0PG51bWJlcj47XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgbXVuaWNpcGFsaXRpZXNUb1BvbHlnb25zID0gYXN5bmMgKFxyXG4gIG11bmljaXBhbGl0aWVzOiBNdW5pY2lwYWxpdHlbXVxyXG4pOiBQcm9taXNlPFJlY29yZDxudW1iZXIsIEZlYXR1cmVDb2xsZWN0aW9uPj4gPT4ge1xyXG4gIGNvbnN0IHsgY2l0eUNvZGVzLCBkaXN0cmljdENvZGVzIH0gPSBleHRyYWN0TXVuaWNpcGFsaXR5Q29kZXMobXVuaWNpcGFsaXRpZXMpO1xyXG4gIGNvbnN0IGNpdHlQb2x5Z29ucyA9IGF3YWl0IGdldENpdHlQb2x5Z29ucyhjaXR5Q29kZXMpO1xyXG4gIGNvbnN0IGRpc3RyaWN0UG9seWdvbnMgPSBhd2FpdCBnZXREaXN0cmljdFBvbHlnb25zKGRpc3RyaWN0Q29kZXMpO1xyXG5cclxuICBpZiAoXHJcbiAgICBPYmplY3Qua2V5cyhjaXR5UG9seWdvbnMpLmxlbmd0aCA9PT0gMCAmJlxyXG4gICAgT2JqZWN0LmtleXMoZGlzdHJpY3RQb2x5Z29ucykubGVuZ3RoID09PSAwXHJcbiAgKSB7XHJcbiAgICBjb25zb2xlLmxvZyhcIk5vIHBvbHlnb25zIGZvdW5kIGZvciBnaXZlbiBtdW5pY2lwYWxpdGllcy5cIik7XHJcbiAgICByZXR1cm4ge307XHJcbiAgfVxyXG5cclxuICAvLyBtdW5pY2lwYWxpdHlDb2RlIC0+IGFyZWFzXHJcbiAgY29uc3QgZXh0cmFBcmVhcyA9IGdldEV4dHJhQXJlYXMobXVuaWNpcGFsaXRpZXMpO1xyXG5cclxuICBjb25zdCBjb2xsZWN0aW9uTWFwID0gbmV3IE1hcDxcclxuICAgIG51bWJlcixcclxuICAgIEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+XHJcbiAgPigpO1xyXG4gIC8vIGFyZWFJbmRleCAtPiBwb2x5Z29uXHJcbiAgY29uc3QgZXh0cmFQb2x5Z29uc01hcCA9IG5ldyBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+W10+KCk7XHJcblxyXG4gIGZvciAoY29uc3QgbXVuaWNpcGFsaXR5IG9mIG11bmljaXBhbGl0aWVzKSB7XHJcbiAgICBpZiAobXVuaWNpcGFsaXR5LmFyZWFzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuICAgIGNvbnN0IHsgZmVhdHVyZUNvbGxlY3Rpb24sIGV4dHJhUG9seWdvbnMgfSA9IGNyZWF0ZVBvbHlnb25zKFxyXG4gICAgICBtdW5pY2lwYWxpdHksXHJcbiAgICAgIGV4dHJhQXJlYXMuZ2V0KG11bmljaXBhbGl0eS5jb2RlKSA/PyBbXSxcclxuICAgICAgZ2V0TXVuaWNpcGFsaXR5UG9seWdvbnMobXVuaWNpcGFsaXR5LCBjaXR5UG9seWdvbnMsIGRpc3RyaWN0UG9seWdvbnMpXHJcbiAgICApO1xyXG4gICAgY29sbGVjdGlvbk1hcC5zZXQobXVuaWNpcGFsaXR5LmNvZGUsIGZlYXR1cmVDb2xsZWN0aW9uKTtcclxuICAgIGlmIChleHRyYUFyZWFzLmhhcyhtdW5pY2lwYWxpdHkuY29kZSkpIHtcclxuICAgICAgZm9yIChjb25zdCBbYXJlYUluZGV4LCBleHRyYVBvbHlnb25dIG9mIGV4dHJhUG9seWdvbnMpIHtcclxuICAgICAgICBpZiAoIWV4dHJhUG9seWdvbnNNYXAuaGFzKGFyZWFJbmRleCkpIHtcclxuICAgICAgICAgIGV4dHJhUG9seWdvbnNNYXAuc2V0KGFyZWFJbmRleCwgW10pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBleHRyYVBvbHlnb25zTWFwLmdldChhcmVhSW5kZXgpLnB1c2goZXh0cmFQb2x5Z29uKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYWRkRXh0cmFQb2x5Z29ucyhjb2xsZWN0aW9uTWFwLCBleHRyYVBvbHlnb25zTWFwKTtcclxuXHJcbiAgZmluZENvbG9yaW5nKGNvbGxlY3Rpb25NYXApO1xyXG5cclxuICBjb25zdCByZXN1bHQ6IFJlY29yZDxudW1iZXIsIEZlYXR1cmVDb2xsZWN0aW9uPiA9IHt9O1xyXG4gIGZvciAoY29uc3QgW211bmljaXBhbGl0eUNvZGUsIGNvbGxlY3Rpb25dIG9mIGNvbGxlY3Rpb25NYXApIHtcclxuICAgIHJlc3VsdFttdW5pY2lwYWxpdHlDb2RlXSA9IGNvbGxlY3Rpb247XHJcbiAgfVxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn07XHJcblxyXG5jb25zdCBmaW5kQ29sb3JpbmcgPSAoY29sbGVjdGlvbk1hcDogTWFwPG51bWJlciwgRmVhdHVyZUNvbGxlY3Rpb24+KSA9PiB7XHJcbiAgLy8gcHV0IGFsbCB0aGUgZmVhdHVyZXMgaW4gb25lIGFycmF5XHJcbiAgY29uc3QgYWxsRmVhdHVyZXMgPSBBcnJheS5mcm9tKGNvbGxlY3Rpb25NYXAudmFsdWVzKCkpLnJlZHVjZShcclxuICAgIChhY2MsIGNvbGxlY3Rpb24pID0+IHtcclxuICAgICAgYWNjLnB1c2goLi4uY29sbGVjdGlvbi5mZWF0dXJlcyk7XHJcbiAgICAgIHJldHVybiBhY2M7XHJcbiAgICB9LFxyXG4gICAgW11cclxuICApO1xyXG5cclxuICBpZiAoYWxsRmVhdHVyZXMubGVuZ3RoIDw9IDUpIHtcclxuICAgIGFsbEZlYXR1cmVzLmZvckVhY2goKGZlYXR1cmUsIGluZGV4KSA9PiB7XHJcbiAgICAgIGZlYXR1cmUucHJvcGVydGllcy5jb2xvckluZGV4ID0gaW5kZXg7XHJcbiAgICB9KTtcclxuICAgIHJldHVybjtcclxuICB9XHJcblxyXG4gIGNvbnN0IGdyYXBoID0gbmV3IEdyYXBoKCk7XHJcbiAgYWxsRmVhdHVyZXMuZm9yRWFjaCgoZmVhdHVyZSkgPT4ge1xyXG4gICAgZ3JhcGguYWRkTm9kZShmZWF0dXJlLnByb3BlcnRpZXMuYXJlYUluZGV4KTtcclxuICB9KTtcclxuXHJcbiAgZm9yIChjb25zdCBmZWF0dXJlMSBvZiBhbGxGZWF0dXJlcykge1xyXG4gICAgZm9yIChjb25zdCBmZWF0dXJlMiBvZiBhbGxGZWF0dXJlcykge1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgZmVhdHVyZTEucHJvcGVydGllcy5hcmVhSW5kZXggIT09IGZlYXR1cmUyLnByb3BlcnRpZXMuYXJlYUluZGV4ICYmXHJcbiAgICAgICAgYm9vbGVhbkludGVyc2VjdHMoZmVhdHVyZTEsIGZlYXR1cmUyKVxyXG4gICAgICApIHtcclxuICAgICAgICBncmFwaC5hZGRFZGdlKFxyXG4gICAgICAgICAgZmVhdHVyZTEucHJvcGVydGllcy5hcmVhSW5kZXgsXHJcbiAgICAgICAgICBmZWF0dXJlMi5wcm9wZXJ0aWVzLmFyZWFJbmRleFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbG9yKGdyYXBoKTtcclxuXHJcbiAgYWxsRmVhdHVyZXMuZm9yRWFjaCgoZmVhdHVyZSkgPT4ge1xyXG4gICAgZmVhdHVyZS5wcm9wZXJ0aWVzLmNvbG9ySW5kZXggPSBncmFwaC5nZXROb2RlQXR0cmlidXRlKFxyXG4gICAgICBmZWF0dXJlLnByb3BlcnRpZXMuYXJlYUluZGV4LFxyXG4gICAgICBcImNvbG9yXCJcclxuICAgICk7XHJcbiAgfSk7XHJcbn07XHJcblxyXG5jb25zdCBnZXRFeHRyYUFyZWFzID0gKG11bmljaXBhbGl0aWVzOiBNdW5pY2lwYWxpdHlbXSk6IE1hcDxudW1iZXIsIEFyZWFbXT4gPT4ge1xyXG4gIC8vIG11bmljaXBhbGl0eUNvZGUgLT4gYXJlYXNcclxuICBjb25zdCBleHRyYUFyZWFzID0gbmV3IE1hcDxudW1iZXIsIEFyZWFbXT4oKTtcclxuXHJcbiAgZm9yIChjb25zdCBtdW5pY2lwYWxpdHkgb2YgbXVuaWNpcGFsaXRpZXMpIHtcclxuICAgIGZvciAoY29uc3QgYXJlYSBvZiBtdW5pY2lwYWxpdHkuYXJlYXMpIHtcclxuICAgICAgLy8gbXVuaWNpcGFsaXR5Q29kZSAtPiBwb2ludHNcclxuICAgICAgY29uc3QgZXh0cmFQb2ludHMgPSBuZXcgTWFwPG51bWJlciwgRXhwb3J0QWRkcmVzc1BvaW50W10+KCk7XHJcbiAgICAgIGZvciAoY29uc3QgcG9pbnQgb2YgYXJlYS5hZGRyZXNzZXMpIHtcclxuICAgICAgICBpZiAocG9pbnQubXVuaWNpcGFsaXR5Q29kZSkge1xyXG4gICAgICAgICAgaWYgKCFleHRyYVBvaW50cy5oYXMocG9pbnQubXVuaWNpcGFsaXR5Q29kZSkpIHtcclxuICAgICAgICAgICAgZXh0cmFQb2ludHMuc2V0KHBvaW50Lm11bmljaXBhbGl0eUNvZGUsIFtdKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBleHRyYVBvaW50cy5nZXQocG9pbnQubXVuaWNpcGFsaXR5Q29kZSkucHVzaChwb2ludCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBmb3IgKGNvbnN0IFttdW5pY2lwYWxpdHlDb2RlLCBwb2ludHNdIG9mIGV4dHJhUG9pbnRzKSB7XHJcbiAgICAgICAgaWYgKCFleHRyYUFyZWFzLmhhcyhtdW5pY2lwYWxpdHlDb2RlKSkge1xyXG4gICAgICAgICAgZXh0cmFBcmVhcy5zZXQobXVuaWNpcGFsaXR5Q29kZSwgW10pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZXh0cmFBcmVhcy5nZXQobXVuaWNpcGFsaXR5Q29kZSkucHVzaCh7XHJcbiAgICAgICAgICAuLi5hcmVhLFxyXG4gICAgICAgICAgYWRkcmVzc2VzOiBwb2ludHMsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIGV4dHJhQXJlYXM7XHJcbn07XHJcblxyXG5jb25zdCBhZGRFeHRyYVBvbHlnb25zID0gKFxyXG4gIGNvbGxlY3Rpb25NYXA6IE1hcDxudW1iZXIsIEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+PixcclxuICBleHRyYVBvbHlnb25zTWFwOiBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+W10+XHJcbikgPT4ge1xyXG4gIGZvciAoY29uc3QgY29sbGVjdGlvbiBvZiBjb2xsZWN0aW9uTWFwLnZhbHVlcygpKSB7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbGxlY3Rpb24uZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgY29uc3QgZmVhdHVyZSA9IGNvbGxlY3Rpb24uZmVhdHVyZXNbaV07XHJcbiAgICAgIGlmIChleHRyYVBvbHlnb25zTWFwLmhhcyhmZWF0dXJlLnByb3BlcnRpZXMuYXJlYUluZGV4KSkge1xyXG4gICAgICAgIGNvbnN0IHBvbHlnb25zID0gZXh0cmFQb2x5Z29uc01hcC5nZXQoZmVhdHVyZS5wcm9wZXJ0aWVzLmFyZWFJbmRleCk7XHJcbiAgICAgICAgY29uc3QgbmV3UG9seWdvbiA9IHVuaW9uKGZlYXR1cmVDb2xsZWN0aW9uKFsuLi5wb2x5Z29ucywgZmVhdHVyZV0pKTtcclxuICAgICAgICBjb25zdCBuZXdGZWF0dXJlID0ge1xyXG4gICAgICAgICAgLi4ubmV3UG9seWdvbixcclxuICAgICAgICAgIHByb3BlcnRpZXM6IHsgLi4uZmVhdHVyZS5wcm9wZXJ0aWVzIH0sXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb2xsZWN0aW9uLmZlYXR1cmVzW2ldID0gbmV3RmVhdHVyZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufTtcclxuXHJcbmNvbnN0IGdldE11bmljaXBhbGl0eVBvbHlnb25zID0gKFxyXG4gIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5LFxyXG4gIGNpdHlQb2x5Z29uczogUG9seWdvbnNCeUNvZGVzLFxyXG4gIGRpc3RyaWN0UG9seWdvbnM6IFBvbHlnb25zQnlDb2Rlc1xyXG4pOiBQb2x5Z29uc0J5Q29kZXMgPT4ge1xyXG4gIGNvbnN0IHBvbHlnb25zOiBQb2x5Z29uc0J5Q29kZXMgPSB7fTtcclxuXHJcbiAgZm9yIChjb25zdCBjaXR5Q29kZSBvZiBtdW5pY2lwYWxpdHkuY2l0eUNvZGVzKSB7XHJcbiAgICBpZiAoY2l0eVBvbHlnb25zW2NpdHlDb2RlXSkge1xyXG4gICAgICBwb2x5Z29uc1tjaXR5Q29kZV0gPSBjaXR5UG9seWdvbnNbY2l0eUNvZGVdO1xyXG5cclxuICAgICAgaWYgKFxyXG4gICAgICAgIG11bmljaXBhbGl0eS5tdW5pY2lwYWxpdHlUeXBlID09PSBcImNpdHlcIiAmJlxyXG4gICAgICAgIE9iamVjdC5rZXlzKGRpc3RyaWN0UG9seWdvbnMpLmxlbmd0aCA+IDAgJiZcclxuICAgICAgICBtdW5pY2lwYWxpdHkubXVuaWNpcGFsaXR5TmFtZSAhPT0gXCJCcm5vXCJcclxuICAgICAgKSB7XHJcbiAgICAgICAgbGV0IGNpdHlQb2x5Z29uID0gZXh0cmFjdFBvbHlnb25Gcm9tQ29sbGVjdGlvbihjaXR5UG9seWdvbnNbY2l0eUNvZGVdKTtcclxuICAgICAgICAvLyBzdWJ0cmFjdCBhbGwgZGlzdHJpY3QgcG9seWdvbnMgZnJvbSBjaXR5IHBvbHlnb25cclxuICAgICAgICBmb3IgKGNvbnN0IFtkaXN0cmljdENvZGUsIGRpc3RyaWN0UG9seWdvbl0gb2YgT2JqZWN0LmVudHJpZXMoXHJcbiAgICAgICAgICBkaXN0cmljdFBvbHlnb25zXHJcbiAgICAgICAgKSkge1xyXG4gICAgICAgICAgaWYgKG11bmljaXBhbGl0eS5kaXN0cmljdENvZGVzLmluY2x1ZGVzKHBhcnNlSW50KGRpc3RyaWN0Q29kZSkpKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgY2l0eVBvbHlnb24gPSBkaWZmZXJlbmNlKFxyXG4gICAgICAgICAgICBmZWF0dXJlQ29sbGVjdGlvbihbXHJcbiAgICAgICAgICAgICAgY2l0eVBvbHlnb24sXHJcbiAgICAgICAgICAgICAgZXh0cmFjdFBvbHlnb25Gcm9tQ29sbGVjdGlvbihkaXN0cmljdFBvbHlnb24pLFxyXG4gICAgICAgICAgICBdKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcG9seWdvbnNbY2l0eUNvZGVdID0gZmVhdHVyZUNvbGxlY3Rpb24oW2NpdHlQb2x5Z29uXSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZvciAoY29uc3QgZGlzdHJpY3RDb2RlIG9mIG11bmljaXBhbGl0eS5kaXN0cmljdENvZGVzKSB7XHJcbiAgICBpZiAoZGlzdHJpY3RQb2x5Z29uc1tkaXN0cmljdENvZGVdKSB7XHJcbiAgICAgIHBvbHlnb25zW2Rpc3RyaWN0Q29kZV0gPSBkaXN0cmljdFBvbHlnb25zW2Rpc3RyaWN0Q29kZV07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcG9seWdvbnM7XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgY3JlYXRlUG9seWdvbnMgPSAoXHJcbiAgbXVuaWNpcGFsaXR5OiBNdW5pY2lwYWxpdHksXHJcbiAgZXh0cmFBcmVhczogQXJlYVtdLFxyXG4gIG11bmljaXBhbGl0eVBvbHlnb25zOiBSZWNvcmQ8XHJcbiAgICBudW1iZXIsXHJcbiAgICBGZWF0dXJlQ29sbGVjdGlvbjxQb2x5Z29uIHwgTXVsdGlQb2x5Z29uPlxyXG4gID5cclxuKToge1xyXG4gIGZlYXR1cmVDb2xsZWN0aW9uOiBGZWF0dXJlQ29sbGVjdGlvbjxQb2x5Z29uIHwgTXVsdGlQb2x5Z29uPjtcclxuICBleHRyYVBvbHlnb25zOiBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+PjtcclxufSA9PiB7XHJcbiAgY29uc3QgbXVuaWNpcGFsaXRpZXNNdWx0aXBvbHlnb24gPSBjcmVhdGVNdW5pY2lwYWxpdGllc011bHRpcG9seWdvbihcclxuICAgIE9iamVjdC52YWx1ZXMobXVuaWNpcGFsaXR5UG9seWdvbnMpXHJcbiAgKTtcclxuICBjb25zdCB1bmlxdWVQb2ludHMgPSBuZXcgTWFwPHN0cmluZywgRmVhdHVyZT4oKTtcclxuICBjb25zdCBhbGxBcmVhcyA9IFsuLi5tdW5pY2lwYWxpdHkuYXJlYXMsIC4uLmV4dHJhQXJlYXNdO1xyXG4gIGNvbnN0IGV4dHJhQXJlYXNJbmRleGVzID0gbmV3IFNldChleHRyYUFyZWFzLm1hcCgoYXJlYSkgPT4gYXJlYS5pbmRleCkpO1xyXG5cclxuICBmb3IgKGNvbnN0IGFyZWEgb2YgYWxsQXJlYXMpIHtcclxuICAgIGNvbnN0IHBvaW50cyA9IFsuLi5hcmVhLmFkZHJlc3Nlc107XHJcblxyXG4gICAgZm9yIChjb25zdCBwb2ludCBvZiBwb2ludHMpIHtcclxuICAgICAgaWYgKCF1bmlxdWVQb2ludHMuaGFzKHBvaW50LmFkZHJlc3MpKSB7XHJcbiAgICAgICAgYWRkUG9pbnQodW5pcXVlUG9pbnRzLCBwb2ludCwgYXJlYS5pbmRleCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdW5pcXVlUG9pbnRzLmdldChwb2ludC5hZGRyZXNzKS5wcm9wZXJ0aWVzLmFyZWFJbmRleGVzLnB1c2goYXJlYS5pbmRleCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IHBvaW50cyA9IHtcclxuICAgIHR5cGU6IFwiRmVhdHVyZUNvbGxlY3Rpb25cIixcclxuICAgIGZlYXR1cmVzOiBBcnJheS5mcm9tKHVuaXF1ZVBvaW50cy52YWx1ZXMoKSksXHJcbiAgfSBhcyBGZWF0dXJlQ29sbGVjdGlvbjxQb2ludD47XHJcblxyXG4gIGNvbnN0IHBvbHlnb25zID0gZDNEZWxhdW5heVZvcm9ub2kocG9pbnRzKTtcclxuXHJcbiAgY29uc3QgdW5pdGVkUG9seWdvbnM6IEZlYXR1cmU8UG9seWdvbiB8IE11bHRpUG9seWdvbj5bXSA9IFtdO1xyXG4gIGNvbnN0IGV4dHJhUG9seWdvbnMgPSBuZXcgTWFwPG51bWJlciwgRmVhdHVyZTxQb2x5Z29uIHwgTXVsdGlQb2x5Z29uPj4oKTtcclxuICBsZXQgY29sb3JJbmRleCA9IDA7XHJcblxyXG4gIGZvciAoY29uc3QgYXJlYSBvZiBhbGxBcmVhcykge1xyXG4gICAgY29uc3Qgc2Nob29sUG9seWdvbnM6IEZlYXR1cmU8UG9seWdvbiB8IE11bHRpUG9seWdvbj5bXSA9XHJcbiAgICAgIHBvbHlnb25zLmZlYXR1cmVzLmZpbHRlcigocG9seWdvbikgPT5cclxuICAgICAgICBwb2x5Z29uLnByb3BlcnRpZXMuYXJlYUluZGV4ZXMuaW5jbHVkZXMoYXJlYS5pbmRleClcclxuICAgICAgKTtcclxuXHJcbiAgICBpZiAoc2Nob29sUG9seWdvbnMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHNjaG9vbFBvbHlnb24gPSBpbnRlcnNlY3QoXHJcbiAgICAgIHNjaG9vbFBvbHlnb25zLmxlbmd0aCA+IDFcclxuICAgICAgICA/IHVuaW9uKGZlYXR1cmVDb2xsZWN0aW9uKHNjaG9vbFBvbHlnb25zKSlcclxuICAgICAgICA6IHNjaG9vbFBvbHlnb25zWzBdLFxyXG4gICAgICBtdW5pY2lwYWxpdGllc011bHRpcG9seWdvblxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBmZWF0dXJlID0ge1xyXG4gICAgICAuLi5zY2hvb2xQb2x5Z29uLFxyXG4gICAgICBwcm9wZXJ0aWVzOiB7XHJcbiAgICAgICAgYXJlYUluZGV4OiBhcmVhLmluZGV4LFxyXG4gICAgICAgIHNjaG9vbEl6b3M6IGFyZWEuc2Nob29scy5tYXAoKHNjaG9vbCkgPT4gc2Nob29sLml6byksXHJcbiAgICAgICAgY29sb3JJbmRleCxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgICBpZiAoZXh0cmFBcmVhc0luZGV4ZXMuaGFzKGFyZWEuaW5kZXgpKSB7XHJcbiAgICAgIGV4dHJhUG9seWdvbnMuc2V0KGFyZWEuaW5kZXgsIGZlYXR1cmUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdW5pdGVkUG9seWdvbnMucHVzaChmZWF0dXJlKTtcclxuICAgIH1cclxuICAgIGNvbG9ySW5kZXgrKztcclxuICB9XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBmZWF0dXJlQ29sbGVjdGlvbjogdHJ1bmNhdGUoe1xyXG4gICAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXHJcbiAgICAgIGZlYXR1cmVzOiBbLi4udW5pdGVkUG9seWdvbnNdLFxyXG4gICAgfSksXHJcbiAgICBleHRyYVBvbHlnb25zLFxyXG4gIH07XHJcbn07XHJcblxyXG5jb25zdCBhZGRQb2ludCA9IChcclxuICB1bmlxdWVQb2ludHM6IE1hcDxzdHJpbmcsIEZlYXR1cmU+LFxyXG4gIHBvaW50OiBFeHBvcnRBZGRyZXNzUG9pbnQsXHJcbiAgYXJlYUluZGV4OiBudW1iZXJcclxuKSA9PiB7XHJcbiAgaWYgKHBvaW50LmxhdCA9PT0gbnVsbCB8fCBwb2ludC5sbmcgPT09IG51bGwpIHtcclxuICAgIHJldHVybjtcclxuICB9XHJcbiAgdW5pcXVlUG9pbnRzLnNldChwb2ludC5hZGRyZXNzLCB7XHJcbiAgICB0eXBlOiBcIkZlYXR1cmVcIixcclxuICAgIGdlb21ldHJ5OiB7XHJcbiAgICAgIHR5cGU6IFwiUG9pbnRcIixcclxuICAgICAgY29vcmRpbmF0ZXM6IFtwb2ludC5sbmcsIHBvaW50LmxhdF0sXHJcbiAgICB9LFxyXG4gICAgcHJvcGVydGllczoge1xyXG4gICAgICBhcmVhSW5kZXhlczogW2FyZWFJbmRleF0sXHJcbiAgICB9LFxyXG4gIH0pO1xyXG59O1xyXG5cclxuY29uc3QgZDNEZWxhdW5heVZvcm9ub2kgPSAoXHJcbiAgcG9pbnRzOiBGZWF0dXJlQ29sbGVjdGlvbjxQb2ludD5cclxuKTogRmVhdHVyZUNvbGxlY3Rpb248UG9seWdvbiwgUG9seWdvblByb3BzPiA9PiB7XHJcbiAgY29uc3QgY29udmVydGVkID0gcG9pbnRzLmZlYXR1cmVzLm1hcCgocCkgPT4ge1xyXG4gICAgcmV0dXJuIHRvTWVyY2F0b3IoW3AuZ2VvbWV0cnkuY29vcmRpbmF0ZXNbMF0sIHAuZ2VvbWV0cnkuY29vcmRpbmF0ZXNbMV1dKTtcclxuICB9KTtcclxuXHJcbiAgY29uc3QgYmJveCA9IFsuLi50b01lcmNhdG9yKFstMTgwLCAtODVdKSwgLi4udG9NZXJjYXRvcihbMTgwLCA4NV0pXSBhcyBbXHJcbiAgICBudW1iZXIsXHJcbiAgICBudW1iZXIsXHJcbiAgICBudW1iZXIsXHJcbiAgICBudW1iZXJcclxuICBdO1xyXG5cclxuICBjb25zdCBkZWxhdW5heSA9IG5ldyBEZWxhdW5heShGbG9hdDY0QXJyYXkub2YoLi4uY29udmVydGVkLmZsYXQoKSkpO1xyXG4gIGNvbnN0IHZvcm9ub2kgPSBkZWxhdW5heS52b3Jvbm9pKGJib3gpO1xyXG4gIHJldHVybiB7XHJcbiAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXHJcbiAgICBmZWF0dXJlczogQXJyYXkuZnJvbSh2b3Jvbm9pLmNlbGxQb2x5Z29ucygpKS5tYXAoKHBvbHlnb24pID0+ICh7XHJcbiAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxyXG4gICAgICBnZW9tZXRyeToge1xyXG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxyXG4gICAgICAgIGNvb3JkaW5hdGVzOiBbcG9seWdvbi5tYXAoKHApID0+IHRvV2dzODQocCkpXSxcclxuICAgICAgfSxcclxuICAgICAgcHJvcGVydGllczoge1xyXG4gICAgICAgIGFyZWFJbmRleGVzOiBwb2ludHMuZmVhdHVyZXNbcG9seWdvbi5pbmRleF0ucHJvcGVydGllcy5hcmVhSW5kZXhlcyxcclxuICAgICAgICBpbmRleDogcG9seWdvbi5pbmRleCxcclxuICAgICAgICBuZWlnaGJvcnM6IG5ldyBTZXQodm9yb25vaS5uZWlnaGJvcnMocG9seWdvbi5pbmRleCkpLFxyXG4gICAgICB9LFxyXG4gICAgfSkpLFxyXG4gIH07XHJcbn07XHJcblxyXG5jb25zdCBjcmVhdGVNdW5pY2lwYWxpdGllc011bHRpcG9seWdvbiA9IChcclxuICBtdW5pY2lwYWxpdHlQb2x5Z29uczogRmVhdHVyZUNvbGxlY3Rpb25bXVxyXG4pOiBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+ID0+IHtcclxuICBjb25zdCBtdW5pY2lwYWxpdHlQb2x5Z29uRmVhdHVyZXMgPSBtdW5pY2lwYWxpdHlQb2x5Z29ucy5yZWR1Y2UoXHJcbiAgICAoYWNjLCBtdW5pY2lwYWxpdHlQb2x5Z29uKSA9PiB7XHJcbiAgICAgIGFjYy5wdXNoKFxyXG4gICAgICAgIC4uLm11bmljaXBhbGl0eVBvbHlnb24uZmVhdHVyZXMuZmlsdGVyKFxyXG4gICAgICAgICAgKGYpID0+XHJcbiAgICAgICAgICAgIGYuZ2VvbWV0cnkudHlwZSA9PT0gXCJQb2x5Z29uXCIgfHwgZi5nZW9tZXRyeS50eXBlID09PSBcIk11bHRpUG9seWdvblwiXHJcbiAgICAgICAgKVxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gYWNjO1xyXG4gICAgfSxcclxuICAgIFtdXHJcbiAgKTtcclxuXHJcbiAgcmV0dXJuIGV4dHJhY3RQb2x5Z29uRnJvbUNvbGxlY3Rpb24oXHJcbiAgICBmZWF0dXJlQ29sbGVjdGlvbihtdW5pY2lwYWxpdHlQb2x5Z29uRmVhdHVyZXMpXHJcbiAgKTtcclxufTtcclxuXHJcbmNvbnN0IGV4dHJhY3RNdW5pY2lwYWxpdHlDb2RlcyA9IChtdW5pY2lwYWxpdGllczogTXVuaWNpcGFsaXR5W10pID0+IHtcclxuICByZXR1cm4gbXVuaWNpcGFsaXRpZXMucmVkdWNlKFxyXG4gICAgKGFjYywgbXVuaWNpcGFsaXR5KSA9PiB7XHJcbiAgICAgIG11bmljaXBhbGl0eS5jaXR5Q29kZXMuZm9yRWFjaCgoY2l0eUNvZGUpID0+IGFjYy5jaXR5Q29kZXMuYWRkKGNpdHlDb2RlKSk7XHJcbiAgICAgIG11bmljaXBhbGl0eS5kaXN0cmljdENvZGVzLmZvckVhY2goKGRpc3RyaWN0Q29kZSkgPT5cclxuICAgICAgICBhY2MuZGlzdHJpY3RDb2Rlcy5hZGQoZGlzdHJpY3RDb2RlKVxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gYWNjO1xyXG4gICAgfSxcclxuICAgIHsgY2l0eUNvZGVzOiBuZXcgU2V0PG51bWJlcj4oKSwgZGlzdHJpY3RDb2RlczogbmV3IFNldDxudW1iZXI+KCkgfVxyXG4gICk7XHJcbn07XHJcblxyXG5jb25zdCBleHRyYWN0UG9seWdvbkZyb21Db2xsZWN0aW9uID0gKFxyXG4gIGNvbGxlY3Rpb246IEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+XHJcbik6IEZlYXR1cmU8UG9seWdvbiB8IE11bHRpUG9seWdvbj4gPT5cclxuICBjb2xsZWN0aW9uLmZlYXR1cmVzLmxlbmd0aCA+IDEgPyB1bmlvbihjb2xsZWN0aW9uKSA6IGNvbGxlY3Rpb24uZmVhdHVyZXNbMF07XHJcbiJdfQ==
1
+ import { Delaunay } from "d3-delaunay";
2
+ import { featureCollection, } from "@turf/helpers";
3
+ import intersect from "@turf/intersect";
4
+ import { booleanIntersects } from "@turf/boolean-intersects";
5
+ import Graph from "graphology";
6
+ import { color } from "graphology-color";
7
+ import { toMercator, toWgs84 } from "@turf/projection";
8
+ import union from "@turf/union";
9
+ import { getCityPolygons, getDistrictPolygons } from "../db/cities";
10
+ import truncate from "@turf/truncate";
11
+ import difference from "@turf/difference";
12
+ export const municipalitiesToPolygons = async (municipalities) => {
13
+ const { cityCodes, districtCodes } = extractMunicipalityCodes(municipalities);
14
+ const cityPolygons = await getCityPolygons(cityCodes);
15
+ const districtPolygons = await getDistrictPolygons(districtCodes);
16
+ if (Object.keys(cityPolygons).length === 0 &&
17
+ Object.keys(districtPolygons).length === 0) {
18
+ console.log("No polygons found for given municipalities.");
19
+ return {};
20
+ }
21
+ // municipalityCode -> areas
22
+ const extraAreas = getExtraAreas(municipalities);
23
+ const collectionMap = new Map();
24
+ // areaIndex -> polygon
25
+ const extraPolygonsMap = new Map();
26
+ for (const municipality of municipalities) {
27
+ if (municipality.areas.length === 0) {
28
+ continue;
29
+ }
30
+ const { featureCollection, extraPolygons } = createPolygons(municipality, extraAreas.get(municipality.code) ?? [], getMunicipalityPolygons(municipality, cityPolygons, districtPolygons));
31
+ collectionMap.set(municipality.code, featureCollection);
32
+ if (extraAreas.has(municipality.code)) {
33
+ for (const [areaIndex, extraPolygon] of extraPolygons) {
34
+ if (!extraPolygonsMap.has(areaIndex)) {
35
+ extraPolygonsMap.set(areaIndex, []);
36
+ }
37
+ extraPolygonsMap.get(areaIndex).push(extraPolygon);
38
+ }
39
+ }
40
+ }
41
+ addExtraPolygons(collectionMap, extraPolygonsMap);
42
+ findColoring(collectionMap);
43
+ const result = {};
44
+ for (const [municipalityCode, collection] of collectionMap) {
45
+ result[municipalityCode] = collection;
46
+ }
47
+ return result;
48
+ };
49
+ const findColoring = (collectionMap) => {
50
+ // put all the features in one array
51
+ const allFeatures = Array.from(collectionMap.values()).reduce((acc, collection) => {
52
+ acc.push(...collection.features);
53
+ return acc;
54
+ }, []);
55
+ if (allFeatures.length <= 5) {
56
+ allFeatures.forEach((feature, index) => {
57
+ feature.properties.colorIndex = index;
58
+ });
59
+ return;
60
+ }
61
+ const graph = new Graph();
62
+ allFeatures.forEach((feature) => {
63
+ graph.addNode(feature.properties.areaIndex);
64
+ });
65
+ for (const feature1 of allFeatures) {
66
+ for (const feature2 of allFeatures) {
67
+ if (feature1.properties.areaIndex !== feature2.properties.areaIndex &&
68
+ booleanIntersects(feature1, feature2)) {
69
+ graph.addEdge(feature1.properties.areaIndex, feature2.properties.areaIndex);
70
+ }
71
+ }
72
+ }
73
+ color(graph);
74
+ allFeatures.forEach((feature) => {
75
+ feature.properties.colorIndex = graph.getNodeAttribute(feature.properties.areaIndex, "color");
76
+ });
77
+ };
78
+ const getExtraAreas = (municipalities) => {
79
+ // municipalityCode -> areas
80
+ const extraAreas = new Map();
81
+ for (const municipality of municipalities) {
82
+ for (const area of municipality.areas) {
83
+ // municipalityCode -> points
84
+ const extraPoints = new Map();
85
+ for (const point of area.addresses) {
86
+ if (point.municipalityCode) {
87
+ if (!extraPoints.has(point.municipalityCode)) {
88
+ extraPoints.set(point.municipalityCode, []);
89
+ }
90
+ extraPoints.get(point.municipalityCode).push(point);
91
+ }
92
+ }
93
+ for (const [municipalityCode, points] of extraPoints) {
94
+ if (!extraAreas.has(municipalityCode)) {
95
+ extraAreas.set(municipalityCode, []);
96
+ }
97
+ extraAreas.get(municipalityCode).push({
98
+ ...area,
99
+ addresses: points,
100
+ });
101
+ }
102
+ }
103
+ }
104
+ return extraAreas;
105
+ };
106
+ const addExtraPolygons = (collectionMap, extraPolygonsMap) => {
107
+ for (const collection of collectionMap.values()) {
108
+ for (let i = 0; i < collection.features.length; i++) {
109
+ const feature = collection.features[i];
110
+ if (extraPolygonsMap.has(feature.properties.areaIndex)) {
111
+ const polygons = extraPolygonsMap.get(feature.properties.areaIndex);
112
+ const newPolygon = union(featureCollection([...polygons, feature]));
113
+ const newFeature = {
114
+ ...newPolygon,
115
+ properties: { ...feature.properties },
116
+ };
117
+ collection.features[i] = newFeature;
118
+ }
119
+ }
120
+ }
121
+ };
122
+ const getMunicipalityPolygons = (municipality, cityPolygons, districtPolygons) => {
123
+ const polygons = {};
124
+ for (const cityCode of municipality.cityCodes) {
125
+ if (cityPolygons[cityCode]) {
126
+ polygons[cityCode] = cityPolygons[cityCode];
127
+ if (municipality.municipalityType === "city" &&
128
+ Object.keys(districtPolygons).length > 0 &&
129
+ municipality.municipalityName !== "Brno") {
130
+ let cityPolygon = extractPolygonFromCollection(cityPolygons[cityCode]);
131
+ // subtract all district polygons from city polygon
132
+ for (const [districtCode, districtPolygon] of Object.entries(districtPolygons)) {
133
+ if (municipality.districtCodes.includes(parseInt(districtCode))) {
134
+ continue;
135
+ }
136
+ cityPolygon = difference(featureCollection([
137
+ cityPolygon,
138
+ extractPolygonFromCollection(districtPolygon),
139
+ ]));
140
+ }
141
+ polygons[cityCode] = featureCollection([cityPolygon]);
142
+ }
143
+ }
144
+ }
145
+ for (const districtCode of municipality.districtCodes) {
146
+ if (districtPolygons[districtCode]) {
147
+ polygons[districtCode] = districtPolygons[districtCode];
148
+ }
149
+ }
150
+ return polygons;
151
+ };
152
+ export const createPolygons = (municipality, extraAreas, municipalityPolygons) => {
153
+ const municipalitiesMultipolygon = createMunicipalitiesMultipolygon(Object.values(municipalityPolygons));
154
+ const uniquePoints = new Map();
155
+ const allAreas = [...municipality.areas, ...extraAreas];
156
+ const extraAreasIndexes = new Set(extraAreas.map((area) => area.index));
157
+ for (const area of allAreas) {
158
+ const points = [...area.addresses];
159
+ for (const point of points) {
160
+ if (!uniquePoints.has(point.address)) {
161
+ addPoint(uniquePoints, point, area.index);
162
+ }
163
+ else {
164
+ uniquePoints.get(point.address).properties.areaIndexes.push(area.index);
165
+ }
166
+ }
167
+ }
168
+ const points = {
169
+ type: "FeatureCollection",
170
+ features: Array.from(uniquePoints.values()),
171
+ };
172
+ const polygons = d3DelaunayVoronoi(points);
173
+ const unitedPolygons = [];
174
+ const extraPolygons = new Map();
175
+ let colorIndex = 0;
176
+ for (const area of allAreas) {
177
+ const schoolPolygons = polygons.features.filter((polygon) => polygon.properties.areaIndexes.includes(area.index));
178
+ if (schoolPolygons.length === 0) {
179
+ continue;
180
+ }
181
+ const schoolPolygon = intersect(schoolPolygons.length > 1
182
+ ? union(featureCollection(schoolPolygons))
183
+ : schoolPolygons[0], municipalitiesMultipolygon);
184
+ const feature = {
185
+ ...schoolPolygon,
186
+ properties: {
187
+ areaIndex: area.index,
188
+ schoolIzos: area.schools.map((school) => school.izo),
189
+ colorIndex,
190
+ },
191
+ };
192
+ if (extraAreasIndexes.has(area.index)) {
193
+ extraPolygons.set(area.index, feature);
194
+ }
195
+ else {
196
+ unitedPolygons.push(feature);
197
+ }
198
+ colorIndex++;
199
+ }
200
+ return {
201
+ featureCollection: truncate({
202
+ type: "FeatureCollection",
203
+ features: [...unitedPolygons],
204
+ }),
205
+ extraPolygons,
206
+ };
207
+ };
208
+ const addPoint = (uniquePoints, point, areaIndex) => {
209
+ if (point.lat === null || point.lng === null) {
210
+ return;
211
+ }
212
+ uniquePoints.set(point.address, {
213
+ type: "Feature",
214
+ geometry: {
215
+ type: "Point",
216
+ coordinates: [point.lng, point.lat],
217
+ },
218
+ properties: {
219
+ areaIndexes: [areaIndex],
220
+ },
221
+ });
222
+ };
223
+ const d3DelaunayVoronoi = (points) => {
224
+ const converted = points.features.map((p) => {
225
+ return toMercator([p.geometry.coordinates[0], p.geometry.coordinates[1]]);
226
+ });
227
+ const bbox = [...toMercator([-180, -85]), ...toMercator([180, 85])];
228
+ const delaunay = new Delaunay(Float64Array.of(...converted.flat()));
229
+ const voronoi = delaunay.voronoi(bbox);
230
+ return {
231
+ type: "FeatureCollection",
232
+ features: Array.from(voronoi.cellPolygons()).map((polygon) => ({
233
+ type: "Feature",
234
+ geometry: {
235
+ type: "Polygon",
236
+ coordinates: [polygon.map((p) => toWgs84(p))],
237
+ },
238
+ properties: {
239
+ areaIndexes: points.features[polygon.index].properties.areaIndexes,
240
+ index: polygon.index,
241
+ neighbors: new Set(voronoi.neighbors(polygon.index)),
242
+ },
243
+ })),
244
+ };
245
+ };
246
+ const createMunicipalitiesMultipolygon = (municipalityPolygons) => {
247
+ const municipalityPolygonFeatures = municipalityPolygons.reduce((acc, municipalityPolygon) => {
248
+ acc.push(...municipalityPolygon.features.filter((f) => f.geometry.type === "Polygon" || f.geometry.type === "MultiPolygon"));
249
+ return acc;
250
+ }, []);
251
+ return extractPolygonFromCollection(featureCollection(municipalityPolygonFeatures));
252
+ };
253
+ const extractMunicipalityCodes = (municipalities) => {
254
+ return municipalities.reduce((acc, municipality) => {
255
+ municipality.cityCodes.forEach((cityCode) => acc.cityCodes.add(cityCode));
256
+ municipality.districtCodes.forEach((districtCode) => acc.districtCodes.add(districtCode));
257
+ return acc;
258
+ }, { cityCodes: new Set(), districtCodes: new Set() });
259
+ };
260
+ const extractPolygonFromCollection = (collection) => collection.features.length > 1 ? union(collection) : collection.features[0];
261
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9seWdvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWV0LW1hcmtkb3duL3BvbHlnb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHdkMsT0FBTyxFQU1MLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLFNBQVMsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkQsT0FBTyxLQUFLLE1BQU0sYUFBYSxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEUsT0FBTyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEMsT0FBTyxVQUFVLE1BQU0sa0JBQWtCLENBQUM7QUFRMUMsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxFQUMzQyxjQUE4QixFQUNjLEVBQUU7SUFDOUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM5RSxNQUFNLFlBQVksR0FBRyxNQUFNLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0RCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sbUJBQW1CLENBQUMsYUFBYSxDQUFDLENBQUM7SUFFbEUsSUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQ3RDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FB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QUNsRCxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FDcEMsQ0FBQztRQUNGLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxFQUNELEVBQUUsU0FBUyxFQUFFLElBQUksR0FBRyxFQUFVLEVBQUUsYUFBYSxFQUFFLElBQUksR0FBRyxFQUFVLEVBQUUsQ0FDbkUsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGLE1BQU0sNEJBQTRCLEdBQUcsQ0FDbkMsVUFBcUQsRUFDcEIsRUFBRSxDQUNuQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlbGF1bmF5IH0gZnJvbSBcImQzLWRlbGF1bmF5XCI7XG5pbXBvcnQgeyBBcmVhLCBFeHBvcnRBZGRyZXNzUG9pbnQsIE11bmljaXBhbGl0eSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmltcG9ydCB7XG4gIEZlYXR1cmUsXG4gIEZlYXR1cmVDb2xsZWN0aW9uLFxuICBNdWx0aVBvbHlnb24sXG4gIFBvaW50LFxuICBQb2x5Z29uLFxuICBmZWF0dXJlQ29sbGVjdGlvbixcbn0gZnJvbSBcIkB0dXJmL2hlbHBlcnNcIjtcbmltcG9ydCBpbnRlcnNlY3QgZnJvbSBcIkB0dXJmL2ludGVyc2VjdFwiO1xuaW1wb3J0IHsgYm9vbGVhbkludGVyc2VjdHMgfSBmcm9tIFwiQHR1cmYvYm9vbGVhbi1pbnRlcnNlY3RzXCI7XG5pbXBvcnQgR3JhcGggZnJvbSBcImdyYXBob2xvZ3lcIjtcbmltcG9ydCB7IGNvbG9yIH0gZnJvbSBcImdyYXBob2xvZ3ktY29sb3JcIjtcbmltcG9ydCB7IHRvTWVyY2F0b3IsIHRvV2dzODQgfSBmcm9tIFwiQHR1cmYvcHJvamVjdGlvblwiO1xuaW1wb3J0IHVuaW9uIGZyb20gXCJAdHVyZi91bmlvblwiO1xuaW1wb3J0IHsgZ2V0Q2l0eVBvbHlnb25zLCBnZXREaXN0cmljdFBvbHlnb25zIH0gZnJvbSBcIi4uL2RiL2NpdGllc1wiO1xuaW1wb3J0IHRydW5jYXRlIGZyb20gXCJAdHVyZi90cnVuY2F0ZVwiO1xuaW1wb3J0IHsgUG9seWdvbnNCeUNvZGVzIH0gZnJvbSBcIi4uL2RiL3R5cGVzXCI7XG5pbXBvcnQgZGlmZmVyZW5jZSBmcm9tIFwiQHR1cmYvZGlmZmVyZW5jZVwiO1xuXG50eXBlIFBvbHlnb25Qcm9wcyA9IHtcbiAgYXJlYUluZGV4ZXM6IG51bWJlcltdO1xuICBpbmRleDogbnVtYmVyO1xuICBuZWlnaGJvcnM6IFNldDxudW1iZXI+O1xufTtcblxuZXhwb3J0IGNvbnN0IG11bmljaXBhbGl0aWVzVG9Qb2x5Z29ucyA9IGFzeW5jIChcbiAgbXVuaWNpcGFsaXRpZXM6IE11bmljaXBhbGl0eVtdXG4pOiBQcm9taXNlPFJlY29yZDxudW1iZXIsIEZlYXR1cmVDb2xsZWN0aW9uPj4gPT4ge1xuICBjb25zdCB7IGNpdHlDb2RlcywgZGlzdHJpY3RDb2RlcyB9ID0gZXh0cmFjdE11bmljaXBhbGl0eUNvZGVzKG11bmljaXBhbGl0aWVzKTtcbiAgY29uc3QgY2l0eVBvbHlnb25zID0gYXdhaXQgZ2V0Q2l0eVBvbHlnb25zKGNpdHlDb2Rlcyk7XG4gIGNvbnN0IGRpc3RyaWN0UG9seWdvbnMgPSBhd2FpdCBnZXREaXN0cmljdFBvbHlnb25zKGRpc3RyaWN0Q29kZXMpO1xuXG4gIGlmIChcbiAgICBPYmplY3Qua2V5cyhjaXR5UG9seWdvbnMpLmxlbmd0aCA9PT0gMCAmJlxuICAgIE9iamVjdC5rZXlzKGRpc3RyaWN0UG9seWdvbnMpLmxlbmd0aCA9PT0gMFxuICApIHtcbiAgICBjb25zb2xlLmxvZyhcIk5vIHBvbHlnb25zIGZvdW5kIGZvciBnaXZlbiBtdW5pY2lwYWxpdGllcy5cIik7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgLy8gbXVuaWNpcGFsaXR5Q29kZSAtPiBhcmVhc1xuICBjb25zdCBleHRyYUFyZWFzID0gZ2V0RXh0cmFBcmVhcyhtdW5pY2lwYWxpdGllcyk7XG5cbiAgY29uc3QgY29sbGVjdGlvbk1hcCA9IG5ldyBNYXA8XG4gICAgbnVtYmVyLFxuICAgIEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+XG4gID4oKTtcbiAgLy8gYXJlYUluZGV4IC0+IHBvbHlnb25cbiAgY29uc3QgZXh0cmFQb2x5Z29uc01hcCA9IG5ldyBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+W10+KCk7XG5cbiAgZm9yIChjb25zdCBtdW5pY2lwYWxpdHkgb2YgbXVuaWNpcGFsaXRpZXMpIHtcbiAgICBpZiAobXVuaWNpcGFsaXR5LmFyZWFzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IHsgZmVhdHVyZUNvbGxlY3Rpb24sIGV4dHJhUG9seWdvbnMgfSA9IGNyZWF0ZVBvbHlnb25zKFxuICAgICAgbXVuaWNpcGFsaXR5LFxuICAgICAgZXh0cmFBcmVhcy5nZXQobXVuaWNpcGFsaXR5LmNvZGUpID8/IFtdLFxuICAgICAgZ2V0TXVuaWNpcGFsaXR5UG9seWdvbnMobXVuaWNpcGFsaXR5LCBjaXR5UG9seWdvbnMsIGRpc3RyaWN0UG9seWdvbnMpXG4gICAgKTtcbiAgICBjb2xsZWN0aW9uTWFwLnNldChtdW5pY2lwYWxpdHkuY29kZSwgZmVhdHVyZUNvbGxlY3Rpb24pO1xuICAgIGlmIChleHRyYUFyZWFzLmhhcyhtdW5pY2lwYWxpdHkuY29kZSkpIHtcbiAgICAgIGZvciAoY29uc3QgW2FyZWFJbmRleCwgZXh0cmFQb2x5Z29uXSBvZiBleHRyYVBvbHlnb25zKSB7XG4gICAgICAgIGlmICghZXh0cmFQb2x5Z29uc01hcC5oYXMoYXJlYUluZGV4KSkge1xuICAgICAgICAgIGV4dHJhUG9seWdvbnNNYXAuc2V0KGFyZWFJbmRleCwgW10pO1xuICAgICAgICB9XG4gICAgICAgIGV4dHJhUG9seWdvbnNNYXAuZ2V0KGFyZWFJbmRleCkucHVzaChleHRyYVBvbHlnb24pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFkZEV4dHJhUG9seWdvbnMoY29sbGVjdGlvbk1hcCwgZXh0cmFQb2x5Z29uc01hcCk7XG5cbiAgZmluZENvbG9yaW5nKGNvbGxlY3Rpb25NYXApO1xuXG4gIGNvbnN0IHJlc3VsdDogUmVjb3JkPG51bWJlciwgRmVhdHVyZUNvbGxlY3Rpb24+ID0ge307XG4gIGZvciAoY29uc3QgW211bmljaXBhbGl0eUNvZGUsIGNvbGxlY3Rpb25dIG9mIGNvbGxlY3Rpb25NYXApIHtcbiAgICByZXN1bHRbbXVuaWNpcGFsaXR5Q29kZV0gPSBjb2xsZWN0aW9uO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5jb25zdCBmaW5kQ29sb3JpbmcgPSAoY29sbGVjdGlvbk1hcDogTWFwPG51bWJlciwgRmVhdHVyZUNvbGxlY3Rpb24+KSA9PiB7XG4gIC8vIHB1dCBhbGwgdGhlIGZlYXR1cmVzIGluIG9uZSBhcnJheVxuICBjb25zdCBhbGxGZWF0dXJlcyA9IEFycmF5LmZyb20oY29sbGVjdGlvbk1hcC52YWx1ZXMoKSkucmVkdWNlKFxuICAgIChhY2MsIGNvbGxlY3Rpb24pID0+IHtcbiAgICAgIGFjYy5wdXNoKC4uLmNvbGxlY3Rpb24uZmVhdHVyZXMpO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LFxuICAgIFtdXG4gICk7XG5cbiAgaWYgKGFsbEZlYXR1cmVzLmxlbmd0aCA8PSA1KSB7XG4gICAgYWxsRmVhdHVyZXMuZm9yRWFjaCgoZmVhdHVyZSwgaW5kZXgpID0+IHtcbiAgICAgIGZlYXR1cmUucHJvcGVydGllcy5jb2xvckluZGV4ID0gaW5kZXg7XG4gICAgfSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgZ3JhcGggPSBuZXcgR3JhcGgoKTtcbiAgYWxsRmVhdHVyZXMuZm9yRWFjaCgoZmVhdHVyZSkgPT4ge1xuICAgIGdyYXBoLmFkZE5vZGUoZmVhdHVyZS5wcm9wZXJ0aWVzLmFyZWFJbmRleCk7XG4gIH0pO1xuXG4gIGZvciAoY29uc3QgZmVhdHVyZTEgb2YgYWxsRmVhdHVyZXMpIHtcbiAgICBmb3IgKGNvbnN0IGZlYXR1cmUyIG9mIGFsbEZlYXR1cmVzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGZlYXR1cmUxLnByb3BlcnRpZXMuYXJlYUluZGV4ICE9PSBmZWF0dXJlMi5wcm9wZXJ0aWVzLmFyZWFJbmRleCAmJlxuICAgICAgICBib29sZWFuSW50ZXJzZWN0cyhmZWF0dXJlMSwgZmVhdHVyZTIpXG4gICAgICApIHtcbiAgICAgICAgZ3JhcGguYWRkRWRnZShcbiAgICAgICAgICBmZWF0dXJlMS5wcm9wZXJ0aWVzLmFyZWFJbmRleCxcbiAgICAgICAgICBmZWF0dXJlMi5wcm9wZXJ0aWVzLmFyZWFJbmRleFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbG9yKGdyYXBoKTtcblxuICBhbGxGZWF0dXJlcy5mb3JFYWNoKChmZWF0dXJlKSA9PiB7XG4gICAgZmVhdHVyZS5wcm9wZXJ0aWVzLmNvbG9ySW5kZXggPSBncmFwaC5nZXROb2RlQXR0cmlidXRlKFxuICAgICAgZmVhdHVyZS5wcm9wZXJ0aWVzLmFyZWFJbmRleCxcbiAgICAgIFwiY29sb3JcIlxuICAgICk7XG4gIH0pO1xufTtcblxuY29uc3QgZ2V0RXh0cmFBcmVhcyA9IChtdW5pY2lwYWxpdGllczogTXVuaWNpcGFsaXR5W10pOiBNYXA8bnVtYmVyLCBBcmVhW10+ID0+IHtcbiAgLy8gbXVuaWNpcGFsaXR5Q29kZSAtPiBhcmVhc1xuICBjb25zdCBleHRyYUFyZWFzID0gbmV3IE1hcDxudW1iZXIsIEFyZWFbXT4oKTtcblxuICBmb3IgKGNvbnN0IG11bmljaXBhbGl0eSBvZiBtdW5pY2lwYWxpdGllcykge1xuICAgIGZvciAoY29uc3QgYXJlYSBvZiBtdW5pY2lwYWxpdHkuYXJlYXMpIHtcbiAgICAgIC8vIG11bmljaXBhbGl0eUNvZGUgLT4gcG9pbnRzXG4gICAgICBjb25zdCBleHRyYVBvaW50cyA9IG5ldyBNYXA8bnVtYmVyLCBFeHBvcnRBZGRyZXNzUG9pbnRbXT4oKTtcbiAgICAgIGZvciAoY29uc3QgcG9pbnQgb2YgYXJlYS5hZGRyZXNzZXMpIHtcbiAgICAgICAgaWYgKHBvaW50Lm11bmljaXBhbGl0eUNvZGUpIHtcbiAgICAgICAgICBpZiAoIWV4dHJhUG9pbnRzLmhhcyhwb2ludC5tdW5pY2lwYWxpdHlDb2RlKSkge1xuICAgICAgICAgICAgZXh0cmFQb2ludHMuc2V0KHBvaW50Lm11bmljaXBhbGl0eUNvZGUsIFtdKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBleHRyYVBvaW50cy5nZXQocG9pbnQubXVuaWNpcGFsaXR5Q29kZSkucHVzaChwb2ludCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBbbXVuaWNpcGFsaXR5Q29kZSwgcG9pbnRzXSBvZiBleHRyYVBvaW50cykge1xuICAgICAgICBpZiAoIWV4dHJhQXJlYXMuaGFzKG11bmljaXBhbGl0eUNvZGUpKSB7XG4gICAgICAgICAgZXh0cmFBcmVhcy5zZXQobXVuaWNpcGFsaXR5Q29kZSwgW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgZXh0cmFBcmVhcy5nZXQobXVuaWNpcGFsaXR5Q29kZSkucHVzaCh7XG4gICAgICAgICAgLi4uYXJlYSxcbiAgICAgICAgICBhZGRyZXNzZXM6IHBvaW50cyxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBleHRyYUFyZWFzO1xufTtcblxuY29uc3QgYWRkRXh0cmFQb2x5Z29ucyA9IChcbiAgY29sbGVjdGlvbk1hcDogTWFwPG51bWJlciwgRmVhdHVyZUNvbGxlY3Rpb248UG9seWdvbiB8IE11bHRpUG9seWdvbj4+LFxuICBleHRyYVBvbHlnb25zTWFwOiBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+W10+XG4pID0+IHtcbiAgZm9yIChjb25zdCBjb2xsZWN0aW9uIG9mIGNvbGxlY3Rpb25NYXAudmFsdWVzKCkpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbGxlY3Rpb24uZmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGZlYXR1cmUgPSBjb2xsZWN0aW9uLmZlYXR1cmVzW2ldO1xuICAgICAgaWYgKGV4dHJhUG9seWdvbnNNYXAuaGFzKGZlYXR1cmUucHJvcGVydGllcy5hcmVhSW5kZXgpKSB7XG4gICAgICAgIGNvbnN0IHBvbHlnb25zID0gZXh0cmFQb2x5Z29uc01hcC5nZXQoZmVhdHVyZS5wcm9wZXJ0aWVzLmFyZWFJbmRleCk7XG4gICAgICAgIGNvbnN0IG5ld1BvbHlnb24gPSB1bmlvbihmZWF0dXJlQ29sbGVjdGlvbihbLi4ucG9seWdvbnMsIGZlYXR1cmVdKSk7XG4gICAgICAgIGNvbnN0IG5ld0ZlYXR1cmUgPSB7XG4gICAgICAgICAgLi4ubmV3UG9seWdvbixcbiAgICAgICAgICBwcm9wZXJ0aWVzOiB7IC4uLmZlYXR1cmUucHJvcGVydGllcyB9LFxuICAgICAgICB9O1xuICAgICAgICBjb2xsZWN0aW9uLmZlYXR1cmVzW2ldID0gbmV3RmVhdHVyZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IGdldE11bmljaXBhbGl0eVBvbHlnb25zID0gKFxuICBtdW5pY2lwYWxpdHk6IE11bmljaXBhbGl0eSxcbiAgY2l0eVBvbHlnb25zOiBQb2x5Z29uc0J5Q29kZXMsXG4gIGRpc3RyaWN0UG9seWdvbnM6IFBvbHlnb25zQnlDb2Rlc1xuKTogUG9seWdvbnNCeUNvZGVzID0+IHtcbiAgY29uc3QgcG9seWdvbnM6IFBvbHlnb25zQnlDb2RlcyA9IHt9O1xuXG4gIGZvciAoY29uc3QgY2l0eUNvZGUgb2YgbXVuaWNpcGFsaXR5LmNpdHlDb2Rlcykge1xuICAgIGlmIChjaXR5UG9seWdvbnNbY2l0eUNvZGVdKSB7XG4gICAgICBwb2x5Z29uc1tjaXR5Q29kZV0gPSBjaXR5UG9seWdvbnNbY2l0eUNvZGVdO1xuXG4gICAgICBpZiAoXG4gICAgICAgIG11bmljaXBhbGl0eS5tdW5pY2lwYWxpdHlUeXBlID09PSBcImNpdHlcIiAmJlxuICAgICAgICBPYmplY3Qua2V5cyhkaXN0cmljdFBvbHlnb25zKS5sZW5ndGggPiAwICYmXG4gICAgICAgIG11bmljaXBhbGl0eS5tdW5pY2lwYWxpdHlOYW1lICE9PSBcIkJybm9cIlxuICAgICAgKSB7XG4gICAgICAgIGxldCBjaXR5UG9seWdvbiA9IGV4dHJhY3RQb2x5Z29uRnJvbUNvbGxlY3Rpb24oY2l0eVBvbHlnb25zW2NpdHlDb2RlXSk7XG4gICAgICAgIC8vIHN1YnRyYWN0IGFsbCBkaXN0cmljdCBwb2x5Z29ucyBmcm9tIGNpdHkgcG9seWdvblxuICAgICAgICBmb3IgKGNvbnN0IFtkaXN0cmljdENvZGUsIGRpc3RyaWN0UG9seWdvbl0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgZGlzdHJpY3RQb2x5Z29uc1xuICAgICAgICApKSB7XG4gICAgICAgICAgaWYgKG11bmljaXBhbGl0eS5kaXN0cmljdENvZGVzLmluY2x1ZGVzKHBhcnNlSW50KGRpc3RyaWN0Q29kZSkpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY2l0eVBvbHlnb24gPSBkaWZmZXJlbmNlKFxuICAgICAgICAgICAgZmVhdHVyZUNvbGxlY3Rpb24oW1xuICAgICAgICAgICAgICBjaXR5UG9seWdvbixcbiAgICAgICAgICAgICAgZXh0cmFjdFBvbHlnb25Gcm9tQ29sbGVjdGlvbihkaXN0cmljdFBvbHlnb24pLFxuICAgICAgICAgICAgXSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHBvbHlnb25zW2NpdHlDb2RlXSA9IGZlYXR1cmVDb2xsZWN0aW9uKFtjaXR5UG9seWdvbl0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgZGlzdHJpY3RDb2RlIG9mIG11bmljaXBhbGl0eS5kaXN0cmljdENvZGVzKSB7XG4gICAgaWYgKGRpc3RyaWN0UG9seWdvbnNbZGlzdHJpY3RDb2RlXSkge1xuICAgICAgcG9seWdvbnNbZGlzdHJpY3RDb2RlXSA9IGRpc3RyaWN0UG9seWdvbnNbZGlzdHJpY3RDb2RlXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcG9seWdvbnM7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUG9seWdvbnMgPSAoXG4gIG11bmljaXBhbGl0eTogTXVuaWNpcGFsaXR5LFxuICBleHRyYUFyZWFzOiBBcmVhW10sXG4gIG11bmljaXBhbGl0eVBvbHlnb25zOiBSZWNvcmQ8XG4gICAgbnVtYmVyLFxuICAgIEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+XG4gID5cbik6IHtcbiAgZmVhdHVyZUNvbGxlY3Rpb246IEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+O1xuICBleHRyYVBvbHlnb25zOiBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+Pjtcbn0gPT4ge1xuICBjb25zdCBtdW5pY2lwYWxpdGllc011bHRpcG9seWdvbiA9IGNyZWF0ZU11bmljaXBhbGl0aWVzTXVsdGlwb2x5Z29uKFxuICAgIE9iamVjdC52YWx1ZXMobXVuaWNpcGFsaXR5UG9seWdvbnMpXG4gICk7XG4gIGNvbnN0IHVuaXF1ZVBvaW50cyA9IG5ldyBNYXA8c3RyaW5nLCBGZWF0dXJlPigpO1xuICBjb25zdCBhbGxBcmVhcyA9IFsuLi5tdW5pY2lwYWxpdHkuYXJlYXMsIC4uLmV4dHJhQXJlYXNdO1xuICBjb25zdCBleHRyYUFyZWFzSW5kZXhlcyA9IG5ldyBTZXQoZXh0cmFBcmVhcy5tYXAoKGFyZWEpID0+IGFyZWEuaW5kZXgpKTtcblxuICBmb3IgKGNvbnN0IGFyZWEgb2YgYWxsQXJlYXMpIHtcbiAgICBjb25zdCBwb2ludHMgPSBbLi4uYXJlYS5hZGRyZXNzZXNdO1xuXG4gICAgZm9yIChjb25zdCBwb2ludCBvZiBwb2ludHMpIHtcbiAgICAgIGlmICghdW5pcXVlUG9pbnRzLmhhcyhwb2ludC5hZGRyZXNzKSkge1xuICAgICAgICBhZGRQb2ludCh1bmlxdWVQb2ludHMsIHBvaW50LCBhcmVhLmluZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaXF1ZVBvaW50cy5nZXQocG9pbnQuYWRkcmVzcykucHJvcGVydGllcy5hcmVhSW5kZXhlcy5wdXNoKGFyZWEuaW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHBvaW50cyA9IHtcbiAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXG4gICAgZmVhdHVyZXM6IEFycmF5LmZyb20odW5pcXVlUG9pbnRzLnZhbHVlcygpKSxcbiAgfSBhcyBGZWF0dXJlQ29sbGVjdGlvbjxQb2ludD47XG5cbiAgY29uc3QgcG9seWdvbnMgPSBkM0RlbGF1bmF5Vm9yb25vaShwb2ludHMpO1xuXG4gIGNvbnN0IHVuaXRlZFBvbHlnb25zOiBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+W10gPSBbXTtcbiAgY29uc3QgZXh0cmFQb2x5Z29ucyA9IG5ldyBNYXA8bnVtYmVyLCBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+PigpO1xuICBsZXQgY29sb3JJbmRleCA9IDA7XG5cbiAgZm9yIChjb25zdCBhcmVhIG9mIGFsbEFyZWFzKSB7XG4gICAgY29uc3Qgc2Nob29sUG9seWdvbnM6IEZlYXR1cmU8UG9seWdvbiB8IE11bHRpUG9seWdvbj5bXSA9XG4gICAgICBwb2x5Z29ucy5mZWF0dXJlcy5maWx0ZXIoKHBvbHlnb24pID0+XG4gICAgICAgIHBvbHlnb24ucHJvcGVydGllcy5hcmVhSW5kZXhlcy5pbmNsdWRlcyhhcmVhLmluZGV4KVxuICAgICAgKTtcblxuICAgIGlmIChzY2hvb2xQb2x5Z29ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGNvbnN0IHNjaG9vbFBvbHlnb24gPSBpbnRlcnNlY3QoXG4gICAgICBzY2hvb2xQb2x5Z29ucy5sZW5ndGggPiAxXG4gICAgICAgID8gdW5pb24oZmVhdHVyZUNvbGxlY3Rpb24oc2Nob29sUG9seWdvbnMpKVxuICAgICAgICA6IHNjaG9vbFBvbHlnb25zWzBdLFxuICAgICAgbXVuaWNpcGFsaXRpZXNNdWx0aXBvbHlnb25cbiAgICApO1xuXG4gICAgY29uc3QgZmVhdHVyZSA9IHtcbiAgICAgIC4uLnNjaG9vbFBvbHlnb24sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGFyZWFJbmRleDogYXJlYS5pbmRleCxcbiAgICAgICAgc2Nob29sSXpvczogYXJlYS5zY2hvb2xzLm1hcCgoc2Nob29sKSA9PiBzY2hvb2wuaXpvKSxcbiAgICAgICAgY29sb3JJbmRleCxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBpZiAoZXh0cmFBcmVhc0luZGV4ZXMuaGFzKGFyZWEuaW5kZXgpKSB7XG4gICAgICBleHRyYVBvbHlnb25zLnNldChhcmVhLmluZGV4LCBmZWF0dXJlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdW5pdGVkUG9seWdvbnMucHVzaChmZWF0dXJlKTtcbiAgICB9XG4gICAgY29sb3JJbmRleCsrO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBmZWF0dXJlQ29sbGVjdGlvbjogdHJ1bmNhdGUoe1xuICAgICAgdHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICAgICAgZmVhdHVyZXM6IFsuLi51bml0ZWRQb2x5Z29uc10sXG4gICAgfSksXG4gICAgZXh0cmFQb2x5Z29ucyxcbiAgfTtcbn07XG5cbmNvbnN0IGFkZFBvaW50ID0gKFxuICB1bmlxdWVQb2ludHM6IE1hcDxzdHJpbmcsIEZlYXR1cmU+LFxuICBwb2ludDogRXhwb3J0QWRkcmVzc1BvaW50LFxuICBhcmVhSW5kZXg6IG51bWJlclxuKSA9PiB7XG4gIGlmIChwb2ludC5sYXQgPT09IG51bGwgfHwgcG9pbnQubG5nID09PSBudWxsKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHVuaXF1ZVBvaW50cy5zZXQocG9pbnQuYWRkcmVzcywge1xuICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgIGdlb21ldHJ5OiB7XG4gICAgICB0eXBlOiBcIlBvaW50XCIsXG4gICAgICBjb29yZGluYXRlczogW3BvaW50LmxuZywgcG9pbnQubGF0XSxcbiAgICB9LFxuICAgIHByb3BlcnRpZXM6IHtcbiAgICAgIGFyZWFJbmRleGVzOiBbYXJlYUluZGV4XSxcbiAgICB9LFxuICB9KTtcbn07XG5cbmNvbnN0IGQzRGVsYXVuYXlWb3Jvbm9pID0gKFxuICBwb2ludHM6IEZlYXR1cmVDb2xsZWN0aW9uPFBvaW50PlxuKTogRmVhdHVyZUNvbGxlY3Rpb248UG9seWdvbiwgUG9seWdvblByb3BzPiA9PiB7XG4gIGNvbnN0IGNvbnZlcnRlZCA9IHBvaW50cy5mZWF0dXJlcy5tYXAoKHApID0+IHtcbiAgICByZXR1cm4gdG9NZXJjYXRvcihbcC5nZW9tZXRyeS5jb29yZGluYXRlc1swXSwgcC5nZW9tZXRyeS5jb29yZGluYXRlc1sxXV0pO1xuICB9KTtcblxuICBjb25zdCBiYm94ID0gWy4uLnRvTWVyY2F0b3IoWy0xODAsIC04NV0pLCAuLi50b01lcmNhdG9yKFsxODAsIDg1XSldIGFzIFtcbiAgICBudW1iZXIsXG4gICAgbnVtYmVyLFxuICAgIG51bWJlcixcbiAgICBudW1iZXJcbiAgXTtcblxuICBjb25zdCBkZWxhdW5heSA9IG5ldyBEZWxhdW5heShGbG9hdDY0QXJyYXkub2YoLi4uY29udmVydGVkLmZsYXQoKSkpO1xuICBjb25zdCB2b3Jvbm9pID0gZGVsYXVuYXkudm9yb25vaShiYm94KTtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBcIkZlYXR1cmVDb2xsZWN0aW9uXCIsXG4gICAgZmVhdHVyZXM6IEFycmF5LmZyb20odm9yb25vaS5jZWxsUG9seWdvbnMoKSkubWFwKChwb2x5Z29uKSA9PiAoe1xuICAgICAgdHlwZTogXCJGZWF0dXJlXCIsXG4gICAgICBnZW9tZXRyeToge1xuICAgICAgICB0eXBlOiBcIlBvbHlnb25cIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IFtwb2x5Z29uLm1hcCgocCkgPT4gdG9XZ3M4NChwKSldLFxuICAgICAgfSxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgYXJlYUluZGV4ZXM6IHBvaW50cy5mZWF0dXJlc1twb2x5Z29uLmluZGV4XS5wcm9wZXJ0aWVzLmFyZWFJbmRleGVzLFxuICAgICAgICBpbmRleDogcG9seWdvbi5pbmRleCxcbiAgICAgICAgbmVpZ2hib3JzOiBuZXcgU2V0KHZvcm9ub2kubmVpZ2hib3JzKHBvbHlnb24uaW5kZXgpKSxcbiAgICAgIH0sXG4gICAgfSkpLFxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlTXVuaWNpcGFsaXRpZXNNdWx0aXBvbHlnb24gPSAoXG4gIG11bmljaXBhbGl0eVBvbHlnb25zOiBGZWF0dXJlQ29sbGVjdGlvbltdXG4pOiBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+ID0+IHtcbiAgY29uc3QgbXVuaWNpcGFsaXR5UG9seWdvbkZlYXR1cmVzID0gbXVuaWNpcGFsaXR5UG9seWdvbnMucmVkdWNlKFxuICAgIChhY2MsIG11bmljaXBhbGl0eVBvbHlnb24pID0+IHtcbiAgICAgIGFjYy5wdXNoKFxuICAgICAgICAuLi5tdW5pY2lwYWxpdHlQb2x5Z29uLmZlYXR1cmVzLmZpbHRlcihcbiAgICAgICAgICAoZikgPT5cbiAgICAgICAgICAgIGYuZ2VvbWV0cnkudHlwZSA9PT0gXCJQb2x5Z29uXCIgfHwgZi5nZW9tZXRyeS50eXBlID09PSBcIk11bHRpUG9seWdvblwiXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAgW11cbiAgKTtcblxuICByZXR1cm4gZXh0cmFjdFBvbHlnb25Gcm9tQ29sbGVjdGlvbihcbiAgICBmZWF0dXJlQ29sbGVjdGlvbihtdW5pY2lwYWxpdHlQb2x5Z29uRmVhdHVyZXMpXG4gICk7XG59O1xuXG5jb25zdCBleHRyYWN0TXVuaWNpcGFsaXR5Q29kZXMgPSAobXVuaWNpcGFsaXRpZXM6IE11bmljaXBhbGl0eVtdKSA9PiB7XG4gIHJldHVybiBtdW5pY2lwYWxpdGllcy5yZWR1Y2UoXG4gICAgKGFjYywgbXVuaWNpcGFsaXR5KSA9PiB7XG4gICAgICBtdW5pY2lwYWxpdHkuY2l0eUNvZGVzLmZvckVhY2goKGNpdHlDb2RlKSA9PiBhY2MuY2l0eUNvZGVzLmFkZChjaXR5Q29kZSkpO1xuICAgICAgbXVuaWNpcGFsaXR5LmRpc3RyaWN0Q29kZXMuZm9yRWFjaCgoZGlzdHJpY3RDb2RlKSA9PlxuICAgICAgICBhY2MuZGlzdHJpY3RDb2Rlcy5hZGQoZGlzdHJpY3RDb2RlKVxuICAgICAgKTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSxcbiAgICB7IGNpdHlDb2RlczogbmV3IFNldDxudW1iZXI+KCksIGRpc3RyaWN0Q29kZXM6IG5ldyBTZXQ8bnVtYmVyPigpIH1cbiAgKTtcbn07XG5cbmNvbnN0IGV4dHJhY3RQb2x5Z29uRnJvbUNvbGxlY3Rpb24gPSAoXG4gIGNvbGxlY3Rpb246IEZlYXR1cmVDb2xsZWN0aW9uPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+XG4pOiBGZWF0dXJlPFBvbHlnb24gfCBNdWx0aVBvbHlnb24+ID0+XG4gIGNvbGxlY3Rpb24uZmVhdHVyZXMubGVuZ3RoID4gMSA/IHVuaW9uKGNvbGxlY3Rpb24pIDogY29sbGVjdGlvbi5mZWF0dXJlc1swXTtcbiJdfQ==