@kepler.gl/mcp 0.0.0-stage → 3.3.0-alpha.19

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 (73) hide show
  1. package/dist/cjs/commands/add-column-command.js +192 -0
  2. package/dist/cjs/commands/basemap-command.js +80 -0
  3. package/dist/cjs/commands/boundary-command.js +81 -0
  4. package/dist/cjs/commands/command-wrappers.js +122 -0
  5. package/dist/cjs/commands/dataset-context-command.js +87 -0
  6. package/dist/cjs/commands/index.js +230 -0
  7. package/dist/cjs/commands/layer-creation-command.js +534 -0
  8. package/dist/cjs/commands/layer-style-command.js +136 -0
  9. package/dist/cjs/commands/load-data-command.js +270 -0
  10. package/dist/cjs/commands/save-data-command.js +118 -0
  11. package/dist/cjs/commands/split-view-command.js +261 -0
  12. package/dist/cjs/commands/table-command.js +199 -0
  13. package/dist/cjs/commands/time-filter-command.js +289 -0
  14. package/dist/cjs/commands/toggle-time-filter-command.js +155 -0
  15. package/dist/cjs/commands/types.js +6 -0
  16. package/dist/cjs/commands/utils.js +536 -0
  17. package/dist/cjs/commands/view-mode-command.js +94 -0
  18. package/dist/cjs/index.js +39 -0
  19. package/dist/cjs/map-contract.js +6 -0
  20. package/dist/cjs/server/bridge-server.js +435 -0
  21. package/dist/cjs/server/index.js +31 -0
  22. package/dist/cjs/server/stdio.js +201 -0
  23. package/dist/cjs/types.js +30 -0
  24. package/dist/commands/add-column-command.d.ts +4 -0
  25. package/dist/commands/basemap-command.d.ts +4 -0
  26. package/dist/commands/boundary-command.d.ts +4 -0
  27. package/dist/commands/command-wrappers.d.ts +52 -0
  28. package/dist/commands/dataset-context-command.d.ts +4 -0
  29. package/dist/commands/index.d.ts +31 -0
  30. package/dist/commands/layer-creation-command.d.ts +8 -0
  31. package/dist/commands/layer-style-command.d.ts +4 -0
  32. package/dist/commands/load-data-command.d.ts +4 -0
  33. package/dist/commands/save-data-command.d.ts +4 -0
  34. package/dist/commands/split-view-command.d.ts +4 -0
  35. package/dist/commands/table-command.d.ts +4 -0
  36. package/dist/commands/time-filter-command.d.ts +13 -0
  37. package/dist/commands/toggle-time-filter-command.d.ts +4 -0
  38. package/dist/commands/types.d.ts +132 -0
  39. package/dist/commands/utils.d.ts +138 -0
  40. package/dist/commands/view-mode-command.d.ts +4 -0
  41. package/dist/esm/commands/add-column-command.js +185 -0
  42. package/dist/esm/commands/basemap-command.js +72 -0
  43. package/dist/esm/commands/boundary-command.js +73 -0
  44. package/dist/esm/commands/command-wrappers.js +114 -0
  45. package/dist/esm/commands/dataset-context-command.js +79 -0
  46. package/dist/esm/commands/index.js +51 -0
  47. package/dist/esm/commands/layer-creation-command.js +527 -0
  48. package/dist/esm/commands/layer-style-command.js +130 -0
  49. package/dist/esm/commands/load-data-command.js +264 -0
  50. package/dist/esm/commands/save-data-command.js +112 -0
  51. package/dist/esm/commands/split-view-command.js +255 -0
  52. package/dist/esm/commands/table-command.js +194 -0
  53. package/dist/esm/commands/time-filter-command.js +280 -0
  54. package/dist/esm/commands/toggle-time-filter-command.js +147 -0
  55. package/dist/esm/commands/types.js +3 -0
  56. package/dist/esm/commands/utils.js +521 -0
  57. package/dist/esm/commands/view-mode-command.js +86 -0
  58. package/dist/esm/index.js +20 -0
  59. package/dist/esm/map-contract.js +3 -0
  60. package/dist/esm/server/bridge-server.js +428 -0
  61. package/dist/esm/server/index.js +13 -0
  62. package/dist/esm/server/stdio.js +198 -0
  63. package/dist/esm/types.js +24 -0
  64. package/dist/index.d.ts +15 -0
  65. package/dist/map-contract.d.ts +31 -0
  66. package/dist/server/bridge-server.d.ts +53 -0
  67. package/dist/server/index.d.ts +9 -0
  68. package/dist/server/stdio.d.ts +2 -0
  69. package/dist/types.d.ts +24 -0
  70. package/package.json +84 -4
  71. package/skill/kepler/SKILL.md +438 -0
  72. package/skill/kepler/skill.yaml +4 -0
  73. package/README.md +0 -3
@@ -0,0 +1,527 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
4
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
5
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
+ // SPDX-License-Identifier: MIT
8
+ // Copyright contributors to the kepler.gl project
9
+
10
+ import { z } from 'zod';
11
+ import { GEOJSON_FIELDS } from '@kepler.gl/constants';
12
+ import { LayerClasses } from '@kepler.gl/layers';
13
+ import { findDefaultLayer, findMapBounds } from '@kepler.gl/reducers';
14
+ import { addLayer as addLayerAction, fitBounds } from '@kepler.gl/actions';
15
+ /**
16
+ * Unique layer id. Date.now()-based ids can collide when multiple layers are
17
+ * created within the same millisecond (rapid successive tool calls), producing
18
+ * duplicate layer ids and unpredictable reducer behavior. Append a random
19
+ * suffix — the same Math.random().toString(36) trick kepler's generateHashId
20
+ * uses — so ids stay unique.
21
+ */
22
+ function uniqueLayerId() {
23
+ var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'layer';
24
+ return "".concat(prefix, "_").concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 8));
25
+ }
26
+ export function guessDefaultLayer(dataset, layerType, options) {
27
+ if (layerType === 'heatmap') {
28
+ if (dataset.fieldPairs && dataset.fieldPairs.length > 0) {
29
+ var props = dataset.fieldPairs.map(function (fieldPair) {
30
+ return {
31
+ isVisible: true,
32
+ label: 'Heatmap',
33
+ columns: fieldPair.pair
34
+ };
35
+ });
36
+ var _layer = new LayerClasses.heatmap(props[0]);
37
+ return _layer;
38
+ }
39
+ } else if (layerType === 'hexagon') {
40
+ if (dataset.fieldPairs && dataset.fieldPairs.length > 0) {
41
+ var _props = dataset.fieldPairs.map(function (fieldPair) {
42
+ return {
43
+ isVisible: true,
44
+ label: 'Hexbin',
45
+ columns: fieldPair.pair
46
+ };
47
+ });
48
+ var _layer2 = new LayerClasses.hexagon(_props[0]);
49
+ return _layer2;
50
+ }
51
+ } else if (layerType === 'cluster') {
52
+ if (dataset.fieldPairs && dataset.fieldPairs.length > 0) {
53
+ var _props2 = dataset.fieldPairs.map(function (fieldPair) {
54
+ return {
55
+ isVisible: true,
56
+ label: 'Cluster',
57
+ columns: fieldPair.pair
58
+ };
59
+ });
60
+ var _layer3 = new LayerClasses.cluster(_props2[0]);
61
+ return _layer3;
62
+ }
63
+ } else if (layerType === 'trip') {
64
+ var layers = findDefaultLayer(dataset, [LayerClasses.trip]);
65
+ var _layer4 = layers.find(function (l) {
66
+ return l.type === layerType;
67
+ });
68
+ if (_layer4) return _layer4;
69
+ throw new Error("Failed to create a trip layer. Trip layer requires id, lat, lng, and timestamp columns.");
70
+ } else if (layerType === 'flow') {
71
+ // Flow layers are never auto-detected (findDefaultLayerProps returns
72
+ // {props: []}), so build one explicitly from the first two point lat/lng
73
+ // field pairs — the same source/target pair logic the default arc layer
74
+ // uses: pair[0] = origin (lat0/lng0), pair[1] = destination (lat1/lng1).
75
+ // The count column (flow magnitude) is optional; without it every flow
76
+ // renders at weight 1.
77
+ var pairs = dataset.fieldPairs || [];
78
+ if (pairs.length < 2) {
79
+ throw new Error("Failed to create a flow layer. Flow layer requires two point lat/lng pairs " + "(origin + destination), e.g. origin_lat/origin_lng and dest_lat/dest_lng.");
80
+ }
81
+ var columns = {
82
+ lat0: pairs[0].pair.lat,
83
+ lng0: pairs[0].pair.lng,
84
+ lat1: pairs[1].pair.lat,
85
+ lng1: pairs[1].pair.lng
86
+ };
87
+ if (options !== null && options !== void 0 && options.countColumn && dataset.getColumnFieldIdx(options.countColumn) >= 0) {
88
+ columns.count = {
89
+ value: options.countColumn,
90
+ fieldIdx: dataset.getColumnFieldIdx(options.countColumn)
91
+ };
92
+ }
93
+ // LayerClasses' computed keys (keyMirror) aren't statically named, so
94
+ // access flow like the trip branch accesses trip: through an `as any` cast.
95
+ var _layer5 = new LayerClasses.flow({
96
+ isVisible: true,
97
+ label: "".concat(pairs[0].defaultName, " -> ").concat(pairs[1].defaultName, " flow"),
98
+ columns: columns
99
+ });
100
+ return _layer5;
101
+ }
102
+ var defaultLayers = findDefaultLayer(dataset, LayerClasses);
103
+ var layer = defaultLayers.find(function (l) {
104
+ return l.type === layerType;
105
+ });
106
+ // Return null (not a fallback to the first default layer) when the requested
107
+ // type can't be created — silently substituting a different layer type (e.g.
108
+ // requesting "h3" and getting a point layer) violates the command contract
109
+ // and makes failures hard to diagnose. The caller errors clearly on null.
110
+ return layer || null;
111
+ }
112
+
113
+ /** Column names the flow field layer resolves when the caller doesn't name them. */
114
+ var FLOW_FIELD_ALTITUDE_COLUMNS = ['altitude', 'alt', 'elevation', 'elev', 'elv', 'height', 'z'];
115
+ var FLOW_FIELD_MODES = ['UV', 'SPEED_DIR', 'ELEVATION'];
116
+ /**
117
+ * Flow Field is a vector/streamline layer: each row is a sample point carrying
118
+ * a position plus a direction — u/v components, speed/direction, or an altitude
119
+ * whose downhill gradient supplies the direction. Unlike the origin→destination
120
+ * `flow` layer it needs no second point pair, and unlike `trip` it animates
121
+ * itself, so no time filter belongs on it.
122
+ */
123
+ function buildFlowFieldLayer(dataset, position) {
124
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
125
+ var hasColumn = function hasColumn(name) {
126
+ return !!name && dataset.getColumnFieldIdx(name) >= 0;
127
+ };
128
+ var columnRef = function columnRef(name) {
129
+ var fieldIdx = dataset.getColumnFieldIdx(name);
130
+ if (fieldIdx < 0) {
131
+ var _dataset$fields$map$j, _dataset$fields;
132
+ var available = (_dataset$fields$map$j = (_dataset$fields = dataset.fields) === null || _dataset$fields === void 0 ? void 0 : _dataset$fields.map(function (f) {
133
+ return f.name;
134
+ }).join(', ')) !== null && _dataset$fields$map$j !== void 0 ? _dataset$fields$map$j : '';
135
+ throw new Error("Column \"".concat(name, "\" not found in dataset \"").concat(dataset.label, "\". Available columns: ").concat(available));
136
+ }
137
+ return {
138
+ value: name,
139
+ fieldIdx: fieldIdx
140
+ };
141
+ };
142
+
143
+ // Position: explicit lat/lng, else the dataset's first detected point pair,
144
+ // else a GeoJSON geometry column (one position per feature).
145
+ var positionColumns = null;
146
+ if (position.latitudeColumn && position.longitudeColumn) {
147
+ positionColumns = {
148
+ lat: columnRef(position.latitudeColumn),
149
+ lng: columnRef(position.longitudeColumn)
150
+ };
151
+ } else {
152
+ var _dataset$fieldPairs;
153
+ var pair = (_dataset$fieldPairs = dataset.fieldPairs) === null || _dataset$fieldPairs === void 0 || (_dataset$fieldPairs = _dataset$fieldPairs[0]) === null || _dataset$fieldPairs === void 0 ? void 0 : _dataset$fieldPairs.pair;
154
+ if (pair !== null && pair !== void 0 && pair.lat && pair !== null && pair !== void 0 && pair.lng) {
155
+ positionColumns = {
156
+ lat: pair.lat,
157
+ lng: pair.lng
158
+ };
159
+ } else {
160
+ var _dataset$fields2;
161
+ var geoField = (_dataset$fields2 = dataset.fields) === null || _dataset$fields2 === void 0 ? void 0 : _dataset$fields2.find(function (f) {
162
+ return f.type === 'geojson' || GEOJSON_FIELDS.geojson.includes(f.name);
163
+ });
164
+ if (geoField) {
165
+ positionColumns = {
166
+ geojson: {
167
+ value: geoField.name,
168
+ fieldIdx: geoField.fieldIdx
169
+ }
170
+ };
171
+ }
172
+ }
173
+ }
174
+ if (!positionColumns) {
175
+ throw new Error('A flow field layer needs a position: lat/lng columns (auto-detected, or pass ' + 'latitudeColumn/longitudeColumn) or a GeoJSON geometry column.');
176
+ }
177
+ var altitudeName = options.altitudeColumn || FLOW_FIELD_ALTITUDE_COLUMNS.find(function (name) {
178
+ return hasColumn(name);
179
+ }) || null;
180
+ var mode = options.mode || (options.uColumn || options.vColumn || hasColumn('u') && hasColumn('v') ? 'UV' : options.speedColumn || options.directionColumn || hasColumn('speed') && hasColumn('direction') ? 'SPEED_DIR' : altitudeName ? 'ELEVATION' : null);
181
+ if (!mode) {
182
+ throw new Error('A flow field layer needs a vector: u/v columns, speed/direction columns, or an ' + 'altitude column (pass flowField.uColumn/vColumn/speedColumn/directionColumn/' + 'altitudeColumn when the names differ).');
183
+ }
184
+ var flowColumns;
185
+ if (mode === 'UV') {
186
+ flowColumns = {
187
+ u: columnRef(options.uColumn || 'u'),
188
+ v: columnRef(options.vColumn || 'v')
189
+ };
190
+ } else if (mode === 'SPEED_DIR') {
191
+ flowColumns = {
192
+ speed: columnRef(options.speedColumn || 'speed'),
193
+ direction: columnRef(options.directionColumn || 'direction')
194
+ };
195
+ } else {
196
+ if (!altitudeName) {
197
+ throw new Error('A flow field layer in ELEVATION mode needs an altitude column (pass flowField.altitudeColumn).');
198
+ }
199
+ flowColumns = {
200
+ altitude: columnRef(altitudeName)
201
+ };
202
+ }
203
+
204
+ // UV and SPEED_DIR may also carry an altitude, which lifts the streamlines.
205
+ var altitudeColumn = mode === 'ELEVATION' || !altitudeName ? {} : {
206
+ altitude: columnRef(altitudeName)
207
+ };
208
+ var layer = new LayerClasses.flowField({
209
+ isVisible: true,
210
+ label: 'Flow Field',
211
+ color: [255, 255, 255],
212
+ columnMode: mode,
213
+ columns: _objectSpread(_objectSpread(_objectSpread({}, positionColumns), flowColumns), altitudeColumn)
214
+ });
215
+ if (options.colorBySpeed) {
216
+ layer.config.visConfig = _objectSpread(_objectSpread({}, layer.config.visConfig), {}, {
217
+ colorBySpeed: true
218
+ });
219
+ }
220
+ return layer;
221
+ }
222
+ function buildLayerConfig(layer, datasetId, layerName, sourceName, layerType) {
223
+ var _layer$config, _layer$config2;
224
+ var layerId = layer.id || uniqueLayerId();
225
+ var columns = ((_layer$config = layer.config) === null || _layer$config === void 0 ? void 0 : _layer$config.columns) || {};
226
+ return {
227
+ id: layerId,
228
+ type: layer.type,
229
+ config: _objectSpread(_objectSpread({}, layer.config), {}, {
230
+ dataId: datasetId,
231
+ isVisible: true,
232
+ label: layerName || "".concat(sourceName, "-").concat(layerType),
233
+ columns: Object.keys(columns).reduce(function (acc, key) {
234
+ var column = columns[key];
235
+ if (column) {
236
+ acc[key] = column.value;
237
+ }
238
+ return acc;
239
+ }, {}),
240
+ visConfig: _objectSpread({}, (_layer$config2 = layer.config) === null || _layer$config2 === void 0 ? void 0 : _layer$config2.visConfig)
241
+ })
242
+ };
243
+ }
244
+ function applyColorConfig(newLayer, dataset, args) {
245
+ if (args.simpleColor) {
246
+ var color = args.simpleColor.replace(/[^\d,]/g, '').split(',').map(Number);
247
+ if (color.length === 3) {
248
+ newLayer.config.color = color;
249
+ }
250
+ }
251
+ var colorBy = args.colorBy,
252
+ colorType = args.colorType,
253
+ providedColorMap = args.colorMap;
254
+ if (colorBy) {
255
+ var colorField = dataset.fields.find(function (f) {
256
+ return f.name === colorBy;
257
+ });
258
+ if (!colorField) {
259
+ throw new Error("Field ".concat(colorBy, " not found."));
260
+ }
261
+
262
+ // For categorical (customOrdinal) color maps, every value becomes the scale
263
+ // domain, so it must be a real value present in the data. The agent must not
264
+ // invent category labels — get them via geoda.analysis (analysis: 'classify',
265
+ // method: 'unique values'). Rejecting here turns a silent wrong render into a
266
+ // recoverable error. Only run this when colorType is explicitly 'unique':
267
+ // an omitted colorType defaults to a continuous (breaks) scale, whose
268
+ // colorMap values are break boundaries, not data values.
269
+ if (colorType === 'unique' && providedColorMap) {
270
+ // Validate without materializing the whole column: scan rows, deleting
271
+ // matches from a small `wanted` set (early-exit when all are found),
272
+ // while collecting a small sample of actual values for the error message.
273
+ // Scan ALL rows — a bounded sample (prefix OR fixed-stride) can
274
+ // systematically miss a category that exists later in the data and
275
+ // falsely report it as "not found". The early-exit keeps the common case
276
+ // (all categories found early) fast; only a genuinely missing category
277
+ // costs a full scan, which is the price of an accurate error.
278
+ var wanted = new Set(providedColorMap.map(function (c) {
279
+ return c.value;
280
+ }));
281
+ var sample = [];
282
+ var seen = new Set();
283
+ for (var i = 0; i < dataset.length && wanted.size > 0; i++) {
284
+ var v = dataset.getValue(colorBy, i);
285
+ if (wanted.has(v)) {
286
+ wanted["delete"](v);
287
+ } else if (!seen.has(v) && sample.length < 20) {
288
+ seen.add(v);
289
+ sample.push(v);
290
+ }
291
+ }
292
+ if (wanted.size > 0) {
293
+ var missing = _toConsumableArray(wanted);
294
+ throw new Error("colorMap value(s) ".concat(missing.map(function (v) {
295
+ return JSON.stringify(v);
296
+ }).join(', '), " not found in field \"").concat(colorBy, "\". ") + "Actual unique values: ".concat(sample.map(function (v) {
297
+ return JSON.stringify(v);
298
+ }).join(', ')).concat(sample.length >= 20 ? ', …' : '', ". ") + "Call geoda.analysis (analysis: 'classify', method: 'unique values') to get the real values.");
299
+ }
300
+ }
301
+
302
+ // colorType is optional; when omitted, default to a continuous (breaks)
303
+ // scale so numeric fields colored via colorBy aren't mis-colored as
304
+ // categorical. Only an explicit 'unique' selects the categorical scale.
305
+ var colorScale = colorType === 'unique' ? 'customOrdinal' : 'custom';
306
+
307
+ // Only force a custom palette when the caller provided an explicit
308
+ // colorMap. A synthetic single-entry colorMap ({value: null, color:
309
+ // '#333333'}) would route through kepler's custom colorMap scale path and
310
+ // render everything as the no-value/unknown color; without an explicit
311
+ // colorMap, bind the color field and let kepler.gl's default color range
312
+ // apply.
313
+ var colorRange = providedColorMap ? {
314
+ name: 'color.customPalette',
315
+ type: 'custom',
316
+ category: 'Custom',
317
+ colors: providedColorMap.map(function (c) {
318
+ return c.color;
319
+ }),
320
+ colorMap: providedColorMap.map(function (c) {
321
+ return [c.value, c.color];
322
+ })
323
+ } : null;
324
+ if (newLayer.type === 'heatmap') {
325
+ if (colorRange && providedColorMap && providedColorMap.length > 1) {
326
+ newLayer.config.visConfig['colorRange'] = _objectSpread({}, colorRange);
327
+ }
328
+ } else {
329
+ newLayer.config['colorScale'] = colorScale;
330
+ newLayer.config['colorField'] = colorField;
331
+ newLayer.config['strokeColorScale'] = colorScale;
332
+ newLayer.config['strokeColorField'] = colorField;
333
+ newLayer.config.visConfig['filled'] = true;
334
+ if (colorRange) {
335
+ newLayer.config.visConfig['colorRange'] = colorRange;
336
+ newLayer.config.visConfig['strokeColorRange'] = colorRange;
337
+ }
338
+ }
339
+ }
340
+ }
341
+ export var addLayerCommandId = 'map.add-layer';
342
+ export function getAddLayerCommand(ctx) {
343
+ return {
344
+ id: addLayerCommandId,
345
+ name: 'Add map layer',
346
+ group: 'Map',
347
+ description: "Add a kepler.gl map layer from a dataset.\nIMPORTANT: generated layer names must be unique.\n\nLAYER TYPES:\n- point: Point markers (requires lat/lng columns)\n- flow: Origin->destination flow map (requires two point lat/lng pairs, auto-detected)\n- flowField: Animated streamlines over a vector field (u/v, speed/direction, or altitude)\n- h3: H3 hexagon cells (requires hexId column)\n- geojson: Polygon/geometry features (uses geometry column, usually auto-detected)\n- hexagon: Hexagonal binning of points\n- heatmap: Heat map visualization\n- cluster: Clustered point visualization\n- arc/line: Arc or line connections between points\n- grid: Grid binning\n- trip: Animated trip (flights, deliveries, vessels)\n- s2: S2 geometry cells\n\nFLOW MAPS (layerType 'flow'):\nFor origin->destination flows use layerType 'flow' \u2014 a dedicated flow layer that draws\nlocations and weighted flows between them. It needs TWO point lat/lng pairs in the\ndataset (source pair + destination pair), which are auto-detected. Prefer 'flow' over\n'arc' for O-D flows; 'arc' draws straight great-circle lines without location clustering\nor flow aggregation. To weight the flows by a value column (flow magnitude), pass\ncountColumn with the column name \u2014 omit it to render all flows at weight 1.\n\nFLOW FIELD (layerType 'flowField'):\nAnimated streamlines over a vector field \u2014 wind, currents, or downhill flow. It is NOT\nthe origin->destination 'flow' layer: 'flow' joins two point pairs, 'flowField' draws\nmany short lines through a field of vectors, one row per sample point.\nThe direction comes from one of three column sets, auto-detected in this order:\n- u/v components (default mode 'UV'), optionally with an altitude column\n- speed + direction (mode 'SPEED_DIR')\n- altitude only (mode 'ELEVATION'): the downhill gradient gives the direction\nPosition is lat/lng (auto-detected, or latitudeColumn/longitudeColumn) or a GeoJSON\ngeometry column. When the dataset names the columns differently, pass flowField.mode\nplus flowField.uColumn/vColumn/speedColumn/directionColumn/altitudeColumn.\nSet flowField.colorBySpeed true to color lines by local speed; otherwise simpleColor\napplies. colorBy/colorMap do not apply to this layer. Do NOT add a time filter \u2014 the\nflow field animates itself.\n\nBASIC MAP:\n- Use datasetName, latitudeColumn/longitudeColumn (for point maps), and layerType\n- Omit color-related parameters for simple visualization, use simpleColor instead.\n\nCOLOR MAPPING:\n- If user requests color visualization, use available columns in the dataset\n- Use geoda.analysis (analysis: 'classify') to classify data into bins or unique values when needed\n- For continuous data (colorType 'breaks'):\n [{value: 0, color: '#fee5d9'}, {value: 50, color: '#fcae91'}, {value: 100, color: '#fb6a4a'}, {value: null, color: '#de2d26'}]\n The last entry with value: null represents the color for the highest values\n- For categorical data (colorType 'unique'):\n [{value: 'category1', color: '#1f77b4'}, {value: 'category2', color: '#ff7f0e'}]\n HARD RULE: the colorMap values MUST be the actual unique values present in the data.\n Call geoda.analysis (analysis: 'classify', method: 'unique values') first and use the\n returned uniqueValues verbatim. NEVER invent category labels from the field name \u2014\n the command rejects values that do not exist in the data.\n- If the user doesn't specify colors, omit colorBy/colorMap \u2014 kepler.gl applies its default color range automatically\n\nFor geojson datasets:\n- Use geometryColumn: '_geojson' and layerType: 'geojson' even for point collections\n",
348
+ metadata: {
349
+ readOnly: false,
350
+ riskLevel: 'medium',
351
+ idempotent: false
352
+ },
353
+ inputSchema: z.object({
354
+ datasetName: z.string().describe('The name (label) or id of the dataset. Prefer the label when known.'),
355
+ latitudeColumn: z.string().optional(),
356
+ longitudeColumn: z.string().optional(),
357
+ layerName: z.string().optional().describe('Generate a unique name for the layer based on the context.'),
358
+ layerType: z["enum"](['point', 'flow', 'flowField', 'arc', 'line', 'grid', 'hexagon', 'geojson', 'cluster', 'heatmap', 'h3', 'trip', 's2']),
359
+ flowField: z.object({
360
+ mode: z["enum"](FLOW_FIELD_MODES).optional(),
361
+ uColumn: z.string().optional(),
362
+ vColumn: z.string().optional(),
363
+ speedColumn: z.string().optional(),
364
+ directionColumn: z.string().optional(),
365
+ altitudeColumn: z.string().optional(),
366
+ colorBySpeed: z["boolean"]().optional()
367
+ }).optional().describe('For layerType "flowField" only: how the vector field is encoded. The mode is ' + 'inferred from the columns (u/v, speed/direction, otherwise altitude); the ' + '*Column fields name the columns when they differ from those defaults.'),
368
+ simpleColor: z.string().optional().describe('The color of the layer e.g. [255, 0, 0]. Only used for simple map visualization (no colorBy, colorType, colorMap).'),
369
+ colorBy: z.string().optional(),
370
+ colorType: z["enum"](['breaks', 'unique']).optional(),
371
+ countColumn: z.string().optional().describe('For layerType "flow" (and only flow): a numeric column whose value weights each flow (flow magnitude). Omit to render all flows at weight 1.'),
372
+ colorMap: z.array(z.object({
373
+ value: z.union([z.string(), z.number(), z["null"]()]),
374
+ color: z.string()
375
+ })).optional()
376
+ }),
377
+ execute: function () {
378
+ var _execute = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(_execCtx, input) {
379
+ var args, datasetName, layerName, latitudeColumn, longitudeColumn, layerType, simpleColor, colorBy, colorType, colorMap, countColumn, flowField, _dataset$fields4, VALID_LAYER_TYPES, visState, datasets, datasetId, dataset, layer, latIdx, lngIdx, _dataset$fields$map$j2, _dataset$fields3, missing, available, newLayer, addedLayer, bounds, temporalFields, hasTemporalFields;
380
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
381
+ while (1) switch (_context.prev = _context.next) {
382
+ case 0:
383
+ args = input !== null && input !== void 0 ? input : {};
384
+ datasetName = args.datasetName, layerName = args.layerName, latitudeColumn = args.latitudeColumn, longitudeColumn = args.longitudeColumn, layerType = args.layerType, simpleColor = args.simpleColor, colorBy = args.colorBy, colorType = args.colorType, colorMap = args.colorMap, countColumn = args.countColumn, flowField = args.flowField;
385
+ _context.prev = 2;
386
+ // Runtime guard: the bridge/webMCP call execute without zod parsing, so
387
+ // a missing/invalid layerType must not fall through to
388
+ // guessDefaultLayer's first-default-layer fallback (layerType is
389
+ // required by the command contract).
390
+ VALID_LAYER_TYPES = ['point', 'flow', 'flowField', 'arc', 'line', 'grid', 'hexagon', 'geojson', 'cluster', 'heatmap', 'h3', 'trip', 's2'];
391
+ if (!(!layerType || !VALID_LAYER_TYPES.includes(layerType))) {
392
+ _context.next = 6;
393
+ break;
394
+ }
395
+ throw new Error("Invalid layerType \"".concat(String(layerType), "\". Must be one of: ").concat(VALID_LAYER_TYPES.join(', '), "."));
396
+ case 6:
397
+ visState = ctx.getVisState();
398
+ datasets = visState.datasets;
399
+ datasetId = Object.keys(datasets).find(function (dataId) {
400
+ return datasets[dataId].label === datasetName || dataId === datasetName;
401
+ });
402
+ if (datasetId) {
403
+ _context.next = 11;
404
+ break;
405
+ }
406
+ throw new Error("Dataset ".concat(datasetName, " not found."));
407
+ case 11:
408
+ dataset = datasets[datasetId]; // The flow field layer resolves its own columns (position + vector, in
409
+ // one of three modes), so it does not go through guessDefaultLayer —
410
+ // that path only auto-detects the u/v case and would ignore explicit
411
+ // column names.
412
+ layer = layerType === 'flowField' ? buildFlowFieldLayer(dataset, {
413
+ latitudeColumn: latitudeColumn,
414
+ longitudeColumn: longitudeColumn
415
+ }, flowField) : guessDefaultLayer(dataset, layerType, {
416
+ countColumn: countColumn
417
+ });
418
+ if (layer) {
419
+ _context.next = 22;
420
+ break;
421
+ }
422
+ if (!(layerType === 'point' && latitudeColumn && longitudeColumn)) {
423
+ _context.next = 22;
424
+ break;
425
+ }
426
+ // Validate both columns exist before building the config —
427
+ // getColumnFieldIdx returns -1 for a missing column, and an
428
+ // invalid fieldIdx would dispatch a broken layer config (empty
429
+ // render / confusing runtime errors).
430
+ latIdx = dataset.getColumnFieldIdx(latitudeColumn);
431
+ lngIdx = dataset.getColumnFieldIdx(longitudeColumn);
432
+ if (!(latIdx < 0 || lngIdx < 0)) {
433
+ _context.next = 21;
434
+ break;
435
+ }
436
+ missing = latIdx < 0 ? latitudeColumn : longitudeColumn;
437
+ available = (_dataset$fields$map$j2 = (_dataset$fields3 = dataset.fields) === null || _dataset$fields3 === void 0 ? void 0 : _dataset$fields3.map(function (f) {
438
+ return f.name;
439
+ }).join(', ')) !== null && _dataset$fields$map$j2 !== void 0 ? _dataset$fields$map$j2 : '';
440
+ throw new Error("Column \"".concat(missing, "\" not found in dataset \"").concat(datasetName, "\". Available columns: ").concat(available));
441
+ case 21:
442
+ layer = {
443
+ id: uniqueLayerId(),
444
+ type: 'point',
445
+ config: {
446
+ dataId: datasetId,
447
+ label: layerName || "".concat(datasetName, "-").concat(layerType),
448
+ columns: {
449
+ lat: {
450
+ value: latitudeColumn,
451
+ fieldIdx: latIdx
452
+ },
453
+ lng: {
454
+ value: longitudeColumn,
455
+ fieldIdx: lngIdx
456
+ }
457
+ },
458
+ visConfig: {}
459
+ }
460
+ };
461
+ case 22:
462
+ if (layer) {
463
+ _context.next = 24;
464
+ break;
465
+ }
466
+ throw new Error("Could not create ".concat(layerType, " layer. Check that the dataset has the required columns."));
467
+ case 24:
468
+ newLayer = buildLayerConfig(layer, datasetId, layerName, datasetName, layerType);
469
+ applyColorConfig(newLayer, dataset, {
470
+ simpleColor: simpleColor,
471
+ colorBy: colorBy,
472
+ colorType: colorType,
473
+ colorMap: colorMap
474
+ });
475
+ ctx.dispatch(addLayerAction(newLayer, datasetId));
476
+
477
+ // Center the map on the new layer's data bounds. `addDataToMap` with
478
+ // `autoCreateLayers: false` (used by `map.load-data`) never fits bounds
479
+ // because no layer exists at load time, and `addLayerUpdater` does not
480
+ // center either — so fit here explicitly.
481
+ addedLayer = ctx.getVisState().layers.find(function (l) {
482
+ return l.id === newLayer.id;
483
+ });
484
+ bounds = addedLayer ? findMapBounds([addedLayer]) : null;
485
+ if (bounds) {
486
+ ctx.dispatch(fitBounds(bounds));
487
+ }
488
+ temporalFields = (_dataset$fields4 = dataset.fields) === null || _dataset$fields4 === void 0 ? void 0 : _dataset$fields4.filter(function (f) {
489
+ return f.type === 'timestamp' || f.type === 'date';
490
+ }).map(function (f) {
491
+ return f.name;
492
+ });
493
+ hasTemporalFields = temporalFields && temporalFields.length > 0;
494
+ return _context.abrupt("return", {
495
+ success: true,
496
+ commandId: addLayerCommandId,
497
+ data: {
498
+ details: "Map layer ".concat(newLayer.id, " has been added to the map."),
499
+ dateTimeColumns: hasTemporalFields ? temporalFields : undefined,
500
+ dateTimeHint: hasTemporalFields ? "DateTime columns detected: ".concat(temporalFields.join(', '), ". You can call addTimeFilter with one of these columns to enable time-range animation on the map.") : undefined
501
+ }
502
+ });
503
+ case 35:
504
+ _context.prev = 35;
505
+ _context.t0 = _context["catch"](2);
506
+ return _context.abrupt("return", {
507
+ success: false,
508
+ commandId: addLayerCommandId,
509
+ error: _context.t0 instanceof Error ? _context.t0.message : 'Unknown error',
510
+ data: {
511
+ instruction: 'Try to fix the error. If the error persists, ask the user to try with different parameters.'
512
+ }
513
+ });
514
+ case 38:
515
+ case "end":
516
+ return _context.stop();
517
+ }
518
+ }, _callee, null, [[2, 35]]);
519
+ }));
520
+ function execute(_x, _x2) {
521
+ return _execute.apply(this, arguments);
522
+ }
523
+ return execute;
524
+ }()
525
+ };
526
+ }
527
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ6IiwiR0VPSlNPTl9GSUVMRFMiLCJMYXllckNsYXNzZXMiLCJmaW5kRGVmYXVsdExheWVyIiwiZmluZE1hcEJvdW5kcyIsImFkZExheWVyIiwiYWRkTGF5ZXJBY3Rpb24iLCJmaXRCb3VuZHMiLCJ1bmlxdWVMYXllcklkIiwicHJlZml4IiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidW5kZWZpbmVkIiwiY29uY2F0IiwiRGF0ZSIsIm5vdyIsIk1hdGgiLCJyYW5kb20iLCJ0b1N0cmluZyIsInNsaWNlIiwiZ3Vlc3NEZWZhdWx0TGF5ZXIiLCJkYXRhc2V0IiwibGF5ZXJUeXBlIiwib3B0aW9ucyIsImZpZWxkUGFpcnMiLCJwcm9wcyIsIm1hcCIsImZpZWxkUGFpciIsImlzVmlzaWJsZSIsImxhYmVsIiwiY29sdW1ucyIsInBhaXIiLCJsYXllciIsImhlYXRtYXAiLCJoZXhhZ29uIiwiY2x1c3RlciIsImxheWVycyIsInRyaXAiLCJmaW5kIiwibCIsInR5cGUiLCJFcnJvciIsInBhaXJzIiwibGF0MCIsImxhdCIsImxuZzAiLCJsbmciLCJsYXQxIiwibG5nMSIsImNvdW50Q29sdW1uIiwiZ2V0Q29sdW1uRmllbGRJZHgiLCJjb3VudCIsInZhbHVlIiwiZmllbGRJZHgiLCJmbG93IiwiZGVmYXVsdE5hbWUiLCJkZWZhdWx0TGF5ZXJzIiwiRkxPV19GSUVMRF9BTFRJVFVERV9DT0xVTU5TIiwiRkxPV19GSUVMRF9NT0RFUyIsImJ1aWxkRmxvd0ZpZWxkTGF5ZXIiLCJwb3NpdGlvbiIsImhhc0NvbHVtbiIsIm5hbWUiLCJjb2x1bW5SZWYiLCJfZGF0YXNldCRmaWVsZHMkbWFwJGoiLCJfZGF0YXNldCRmaWVsZHMiLCJhdmFpbGFibGUiLCJmaWVsZHMiLCJmIiwiam9pbiIsInBvc2l0aW9uQ29sdW1ucyIsImxhdGl0dWRlQ29sdW1uIiwibG9uZ2l0dWRlQ29sdW1uIiwiX2RhdGFzZXQkZmllbGRQYWlycyIsIl9kYXRhc2V0JGZpZWxkczIiLCJnZW9GaWVsZCIsImdlb2pzb24iLCJpbmNsdWRlcyIsImFsdGl0dWRlTmFtZSIsImFsdGl0dWRlQ29sdW1uIiwibW9kZSIsInVDb2x1bW4iLCJ2Q29sdW1uIiwic3BlZWRDb2x1bW4iLCJkaXJlY3Rpb25Db2x1bW4iLCJmbG93Q29sdW1ucyIsInUiLCJ2Iiwic3BlZWQiLCJkaXJlY3Rpb24iLCJhbHRpdHVkZSIsImZsb3dGaWVsZCIsImNvbG9yIiwiY29sdW1uTW9kZSIsIl9vYmplY3RTcHJlYWQiLCJjb2xvckJ5U3BlZWQiLCJjb25maWciLCJ2aXNDb25maWciLCJidWlsZExheWVyQ29uZmlnIiwiZGF0YXNldElkIiwibGF5ZXJOYW1lIiwic291cmNlTmFtZSIsIl9sYXllciRjb25maWciLCJfbGF5ZXIkY29uZmlnMiIsImxheWVySWQiLCJpZCIsImRhdGFJZCIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJhY2MiLCJrZXkiLCJjb2x1bW4iLCJhcHBseUNvbG9yQ29uZmlnIiwibmV3TGF5ZXIiLCJhcmdzIiwic2ltcGxlQ29sb3IiLCJyZXBsYWNlIiwic3BsaXQiLCJOdW1iZXIiLCJjb2xvckJ5IiwiY29sb3JUeXBlIiwicHJvdmlkZWRDb2xvck1hcCIsImNvbG9yTWFwIiwiY29sb3JGaWVsZCIsIndhbnRlZCIsIlNldCIsImMiLCJzYW1wbGUiLCJzZWVuIiwiaSIsInNpemUiLCJnZXRWYWx1ZSIsImhhcyIsImFkZCIsInB1c2giLCJtaXNzaW5nIiwiX3RvQ29uc3VtYWJsZUFycmF5IiwiSlNPTiIsInN0cmluZ2lmeSIsImNvbG9yU2NhbGUiLCJjb2xvclJhbmdlIiwiY2F0ZWdvcnkiLCJjb2xvcnMiLCJhZGRMYXllckNvbW1hbmRJZCIsImdldEFkZExheWVyQ29tbWFuZCIsImN0eCIsImdyb3VwIiwiZGVzY3JpcHRpb24iLCJtZXRhZGF0YSIsInJlYWRPbmx5Iiwicmlza0xldmVsIiwiaWRlbXBvdGVudCIsImlucHV0U2NoZW1hIiwib2JqZWN0IiwiZGF0YXNldE5hbWUiLCJzdHJpbmciLCJkZXNjcmliZSIsIm9wdGlvbmFsIiwiYXJyYXkiLCJ1bmlvbiIsIm51bWJlciIsImV4ZWN1dGUiLCJfZXhlY3V0ZSIsIl9hc3luY1RvR2VuZXJhdG9yIiwiX3JlZ2VuZXJhdG9yUnVudGltZSIsIm1hcmsiLCJfY2FsbGVlIiwiX2V4ZWNDdHgiLCJpbnB1dCIsIl9kYXRhc2V0JGZpZWxkczQiLCJWQUxJRF9MQVlFUl9UWVBFUyIsInZpc1N0YXRlIiwiZGF0YXNldHMiLCJsYXRJZHgiLCJsbmdJZHgiLCJfZGF0YXNldCRmaWVsZHMkbWFwJGoyIiwiX2RhdGFzZXQkZmllbGRzMyIsImFkZGVkTGF5ZXIiLCJib3VuZHMiLCJ0ZW1wb3JhbEZpZWxkcyIsImhhc1RlbXBvcmFsRmllbGRzIiwid3JhcCIsIl9jYWxsZWUkIiwiX2NvbnRleHQiLCJwcmV2IiwibmV4dCIsIlN0cmluZyIsImdldFZpc1N0YXRlIiwiZGlzcGF0Y2giLCJmaWx0ZXIiLCJhYnJ1cHQiLCJzdWNjZXNzIiwiY29tbWFuZElkIiwiZGF0YSIsImRldGFpbHMiLCJkYXRlVGltZUNvbHVtbnMiLCJkYXRlVGltZUhpbnQiLCJ0MCIsImVycm9yIiwibWVzc2FnZSIsImluc3RydWN0aW9uIiwic3RvcCIsIl94IiwiX3gyIiwiYXBwbHkiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tbWFuZHMvbGF5ZXItY3JlYXRpb24tY29tbWFuZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgdHlwZSB7Um9vbUNvbW1hbmR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHt6fSBmcm9tICd6b2QnO1xuaW1wb3J0IHtHRU9KU09OX0ZJRUxEU30gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtMYXllckNsYXNzZXN9IGZyb20gJ0BrZXBsZXIuZ2wvbGF5ZXJzJztcbmltcG9ydCB0eXBlIEtlcGxlclRhYmxlIGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuaW1wb3J0IHR5cGUge0RhdGFzZXRzfSBmcm9tICdAa2VwbGVyLmdsL3RhYmxlJztcbmltcG9ydCB7ZmluZERlZmF1bHRMYXllciwgZmluZE1hcEJvdW5kc30gZnJvbSAnQGtlcGxlci5nbC9yZWR1Y2Vycyc7XG5pbXBvcnQge2FkZExheWVyIGFzIGFkZExheWVyQWN0aW9uLCBmaXRCb3VuZHN9IGZyb20gJ0BrZXBsZXIuZ2wvYWN0aW9ucyc7XG5pbXBvcnQgdHlwZSB7S2VwbGVyQ29udGV4dH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogVW5pcXVlIGxheWVyIGlkLiBEYXRlLm5vdygpLWJhc2VkIGlkcyBjYW4gY29sbGlkZSB3aGVuIG11bHRpcGxlIGxheWVycyBhcmVcbiAqIGNyZWF0ZWQgd2l0aGluIHRoZSBzYW1lIG1pbGxpc2Vjb25kIChyYXBpZCBzdWNjZXNzaXZlIHRvb2wgY2FsbHMpLCBwcm9kdWNpbmdcbiAqIGR1cGxpY2F0ZSBsYXllciBpZHMgYW5kIHVucHJlZGljdGFibGUgcmVkdWNlciBiZWhhdmlvci4gQXBwZW5kIGEgcmFuZG9tXG4gKiBzdWZmaXgg4oCUIHRoZSBzYW1lIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpIHRyaWNrIGtlcGxlcidzIGdlbmVyYXRlSGFzaElkXG4gKiB1c2VzIOKAlCBzbyBpZHMgc3RheSB1bmlxdWUuXG4gKi9cbmZ1bmN0aW9uIHVuaXF1ZUxheWVySWQocHJlZml4ID0gJ2xheWVyJyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtwcmVmaXh9XyR7RGF0ZS5ub3coKX1fJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCA4KX1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ3Vlc3NEZWZhdWx0TGF5ZXIoXG4gIGRhdGFzZXQ6IEtlcGxlclRhYmxlLFxuICBsYXllclR5cGU6IHN0cmluZyxcbiAgb3B0aW9ucz86IHtjb3VudENvbHVtbj86IHN0cmluZ31cbikge1xuICBpZiAobGF5ZXJUeXBlID09PSAnaGVhdG1hcCcpIHtcbiAgICBpZiAoZGF0YXNldC5maWVsZFBhaXJzICYmIGRhdGFzZXQuZmllbGRQYWlycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBwcm9wcyA9IGRhdGFzZXQuZmllbGRQYWlycy5tYXAoZmllbGRQYWlyID0+ICh7XG4gICAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgbGFiZWw6ICdIZWF0bWFwJyxcbiAgICAgICAgY29sdW1uczogZmllbGRQYWlyLnBhaXJcbiAgICAgIH0pKTtcbiAgICAgIGNvbnN0IGxheWVyID0gbmV3IExheWVyQ2xhc3Nlcy5oZWF0bWFwKHByb3BzWzBdKTtcbiAgICAgIHJldHVybiBsYXllcjtcbiAgICB9XG4gIH0gZWxzZSBpZiAobGF5ZXJUeXBlID09PSAnaGV4YWdvbicpIHtcbiAgICBpZiAoZGF0YXNldC5maWVsZFBhaXJzICYmIGRhdGFzZXQuZmllbGRQYWlycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBwcm9wcyA9IGRhdGFzZXQuZmllbGRQYWlycy5tYXAoZmllbGRQYWlyID0+ICh7XG4gICAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgbGFiZWw6ICdIZXhiaW4nLFxuICAgICAgICBjb2x1bW5zOiBmaWVsZFBhaXIucGFpclxuICAgICAgfSkpO1xuICAgICAgY29uc3QgbGF5ZXIgPSBuZXcgTGF5ZXJDbGFzc2VzLmhleGFnb24ocHJvcHNbMF0pO1xuICAgICAgcmV0dXJuIGxheWVyO1xuICAgIH1cbiAgfSBlbHNlIGlmIChsYXllclR5cGUgPT09ICdjbHVzdGVyJykge1xuICAgIGlmIChkYXRhc2V0LmZpZWxkUGFpcnMgJiYgZGF0YXNldC5maWVsZFBhaXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHByb3BzID0gZGF0YXNldC5maWVsZFBhaXJzLm1hcChmaWVsZFBhaXIgPT4gKHtcbiAgICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICBsYWJlbDogJ0NsdXN0ZXInLFxuICAgICAgICBjb2x1bW5zOiBmaWVsZFBhaXIucGFpclxuICAgICAgfSkpO1xuICAgICAgY29uc3QgbGF5ZXIgPSBuZXcgTGF5ZXJDbGFzc2VzLmNsdXN0ZXIocHJvcHNbMF0pO1xuICAgICAgcmV0dXJuIGxheWVyO1xuICAgIH1cbiAgfSBlbHNlIGlmIChsYXllclR5cGUgPT09ICd0cmlwJykge1xuICAgIGNvbnN0IGxheWVycyA9IGZpbmREZWZhdWx0TGF5ZXIoZGF0YXNldCwgW0xheWVyQ2xhc3Nlcy50cmlwXSBhcyBhbnkpO1xuICAgIGNvbnN0IGxheWVyID0gbGF5ZXJzLmZpbmQobCA9PiBsLnR5cGUgPT09IGxheWVyVHlwZSk7XG4gICAgaWYgKGxheWVyKSByZXR1cm4gbGF5ZXI7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEZhaWxlZCB0byBjcmVhdGUgYSB0cmlwIGxheWVyLiBUcmlwIGxheWVyIHJlcXVpcmVzIGlkLCBsYXQsIGxuZywgYW5kIHRpbWVzdGFtcCBjb2x1bW5zLmBcbiAgICApO1xuICB9IGVsc2UgaWYgKGxheWVyVHlwZSA9PT0gJ2Zsb3cnKSB7XG4gICAgLy8gRmxvdyBsYXllcnMgYXJlIG5ldmVyIGF1dG8tZGV0ZWN0ZWQgKGZpbmREZWZhdWx0TGF5ZXJQcm9wcyByZXR1cm5zXG4gICAgLy8ge3Byb3BzOiBbXX0pLCBzbyBidWlsZCBvbmUgZXhwbGljaXRseSBmcm9tIHRoZSBmaXJzdCB0d28gcG9pbnQgbGF0L2xuZ1xuICAgIC8vIGZpZWxkIHBhaXJzIOKAlCB0aGUgc2FtZSBzb3VyY2UvdGFyZ2V0IHBhaXIgbG9naWMgdGhlIGRlZmF1bHQgYXJjIGxheWVyXG4gICAgLy8gdXNlczogcGFpclswXSA9IG9yaWdpbiAobGF0MC9sbmcwKSwgcGFpclsxXSA9IGRlc3RpbmF0aW9uIChsYXQxL2xuZzEpLlxuICAgIC8vIFRoZSBjb3VudCBjb2x1bW4gKGZsb3cgbWFnbml0dWRlKSBpcyBvcHRpb25hbDsgd2l0aG91dCBpdCBldmVyeSBmbG93XG4gICAgLy8gcmVuZGVycyBhdCB3ZWlnaHQgMS5cbiAgICBjb25zdCBwYWlycyA9IGRhdGFzZXQuZmllbGRQYWlycyB8fCBbXTtcbiAgICBpZiAocGFpcnMubGVuZ3RoIDwgMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBhIGZsb3cgbGF5ZXIuIEZsb3cgbGF5ZXIgcmVxdWlyZXMgdHdvIHBvaW50IGxhdC9sbmcgcGFpcnMgYCArXG4gICAgICAgICAgYChvcmlnaW4gKyBkZXN0aW5hdGlvbiksIGUuZy4gb3JpZ2luX2xhdC9vcmlnaW5fbG5nIGFuZCBkZXN0X2xhdC9kZXN0X2xuZy5gXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBjb2x1bW5zOiBhbnkgPSB7XG4gICAgICBsYXQwOiBwYWlyc1swXS5wYWlyLmxhdCxcbiAgICAgIGxuZzA6IHBhaXJzWzBdLnBhaXIubG5nLFxuICAgICAgbGF0MTogcGFpcnNbMV0ucGFpci5sYXQsXG4gICAgICBsbmcxOiBwYWlyc1sxXS5wYWlyLmxuZ1xuICAgIH07XG4gICAgaWYgKG9wdGlvbnM/LmNvdW50Q29sdW1uICYmIGRhdGFzZXQuZ2V0Q29sdW1uRmllbGRJZHgob3B0aW9ucy5jb3VudENvbHVtbikgPj0gMCkge1xuICAgICAgY29sdW1ucy5jb3VudCA9IHtcbiAgICAgICAgdmFsdWU6IG9wdGlvbnMuY291bnRDb2x1bW4sXG4gICAgICAgIGZpZWxkSWR4OiBkYXRhc2V0LmdldENvbHVtbkZpZWxkSWR4KG9wdGlvbnMuY291bnRDb2x1bW4pXG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBMYXllckNsYXNzZXMnIGNvbXB1dGVkIGtleXMgKGtleU1pcnJvcikgYXJlbid0IHN0YXRpY2FsbHkgbmFtZWQsIHNvXG4gICAgLy8gYWNjZXNzIGZsb3cgbGlrZSB0aGUgdHJpcCBicmFuY2ggYWNjZXNzZXMgdHJpcDogdGhyb3VnaCBhbiBgYXMgYW55YCBjYXN0LlxuICAgIGNvbnN0IGxheWVyID0gbmV3IChMYXllckNsYXNzZXMgYXMgYW55KS5mbG93KHtcbiAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgIGxhYmVsOiBgJHtwYWlyc1swXS5kZWZhdWx0TmFtZX0gLT4gJHtwYWlyc1sxXS5kZWZhdWx0TmFtZX0gZmxvd2AsXG4gICAgICBjb2x1bW5zXG4gICAgfSk7XG4gICAgcmV0dXJuIGxheWVyO1xuICB9XG4gIGNvbnN0IGRlZmF1bHRMYXllcnMgPSBmaW5kRGVmYXVsdExheWVyKGRhdGFzZXQsIExheWVyQ2xhc3NlcyBhcyBhbnkpO1xuICBjb25zdCBsYXllciA9IGRlZmF1bHRMYXllcnMuZmluZChsID0+IGwudHlwZSA9PT0gbGF5ZXJUeXBlKTtcbiAgLy8gUmV0dXJuIG51bGwgKG5vdCBhIGZhbGxiYWNrIHRvIHRoZSBmaXJzdCBkZWZhdWx0IGxheWVyKSB3aGVuIHRoZSByZXF1ZXN0ZWRcbiAgLy8gdHlwZSBjYW4ndCBiZSBjcmVhdGVkIOKAlCBzaWxlbnRseSBzdWJzdGl0dXRpbmcgYSBkaWZmZXJlbnQgbGF5ZXIgdHlwZSAoZS5nLlxuICAvLyByZXF1ZXN0aW5nIFwiaDNcIiBhbmQgZ2V0dGluZyBhIHBvaW50IGxheWVyKSB2aW9sYXRlcyB0aGUgY29tbWFuZCBjb250cmFjdFxuICAvLyBhbmQgbWFrZXMgZmFpbHVyZXMgaGFyZCB0byBkaWFnbm9zZS4gVGhlIGNhbGxlciBlcnJvcnMgY2xlYXJseSBvbiBudWxsLlxuICByZXR1cm4gbGF5ZXIgfHwgbnVsbDtcbn1cblxuLyoqIENvbHVtbiBuYW1lcyB0aGUgZmxvdyBmaWVsZCBsYXllciByZXNvbHZlcyB3aGVuIHRoZSBjYWxsZXIgZG9lc24ndCBuYW1lIHRoZW0uICovXG5jb25zdCBGTE9XX0ZJRUxEX0FMVElUVURFX0NPTFVNTlMgPSBbJ2FsdGl0dWRlJywgJ2FsdCcsICdlbGV2YXRpb24nLCAnZWxldicsICdlbHYnLCAnaGVpZ2h0JywgJ3onXTtcbmNvbnN0IEZMT1dfRklFTERfTU9ERVMgPSBbJ1VWJywgJ1NQRUVEX0RJUicsICdFTEVWQVRJT04nXSBhcyBjb25zdDtcbnR5cGUgRmxvd0ZpZWxkTW9kZSA9ICh0eXBlb2YgRkxPV19GSUVMRF9NT0RFUylbbnVtYmVyXTtcblxudHlwZSBGbG93RmllbGRPcHRpb25zID0ge1xuICBtb2RlPzogRmxvd0ZpZWxkTW9kZTtcbiAgdUNvbHVtbj86IHN0cmluZztcbiAgdkNvbHVtbj86IHN0cmluZztcbiAgc3BlZWRDb2x1bW4/OiBzdHJpbmc7XG4gIGRpcmVjdGlvbkNvbHVtbj86IHN0cmluZztcbiAgYWx0aXR1ZGVDb2x1bW4/OiBzdHJpbmc7XG4gIGNvbG9yQnlTcGVlZD86IGJvb2xlYW47XG59O1xuXG4vKipcbiAqIEZsb3cgRmllbGQgaXMgYSB2ZWN0b3Ivc3RyZWFtbGluZSBsYXllcjogZWFjaCByb3cgaXMgYSBzYW1wbGUgcG9pbnQgY2FycnlpbmdcbiAqIGEgcG9zaXRpb24gcGx1cyBhIGRpcmVjdGlvbiDigJQgdS92IGNvbXBvbmVudHMsIHNwZWVkL2RpcmVjdGlvbiwgb3IgYW4gYWx0aXR1ZGVcbiAqIHdob3NlIGRvd25oaWxsIGdyYWRpZW50IHN1cHBsaWVzIHRoZSBkaXJlY3Rpb24uIFVubGlrZSB0aGUgb3JpZ2lu4oaSZGVzdGluYXRpb25cbiAqIGBmbG93YCBsYXllciBpdCBuZWVkcyBubyBzZWNvbmQgcG9pbnQgcGFpciwgYW5kIHVubGlrZSBgdHJpcGAgaXQgYW5pbWF0ZXNcbiAqIGl0c2VsZiwgc28gbm8gdGltZSBmaWx0ZXIgYmVsb25ncyBvbiBpdC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRGbG93RmllbGRMYXllcihcbiAgZGF0YXNldDogS2VwbGVyVGFibGUsXG4gIHBvc2l0aW9uOiB7bGF0aXR1ZGVDb2x1bW4/OiBzdHJpbmc7IGxvbmdpdHVkZUNvbHVtbj86IHN0cmluZ30sXG4gIG9wdGlvbnM6IEZsb3dGaWVsZE9wdGlvbnMgPSB7fVxuKSB7XG4gIGNvbnN0IGhhc0NvbHVtbiA9IChuYW1lPzogc3RyaW5nKSA9PiAhIW5hbWUgJiYgZGF0YXNldC5nZXRDb2x1bW5GaWVsZElkeChuYW1lKSA+PSAwO1xuICBjb25zdCBjb2x1bW5SZWYgPSAobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgZmllbGRJZHggPSBkYXRhc2V0LmdldENvbHVtbkZpZWxkSWR4KG5hbWUpO1xuICAgIGlmIChmaWVsZElkeCA8IDApIHtcbiAgICAgIGNvbnN0IGF2YWlsYWJsZSA9IGRhdGFzZXQuZmllbGRzPy5tYXAoKGY6IGFueSkgPT4gZi5uYW1lKS5qb2luKCcsICcpID8/ICcnO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29sdW1uIFwiJHtuYW1lfVwiIG5vdCBmb3VuZCBpbiBkYXRhc2V0IFwiJHtkYXRhc2V0LmxhYmVsfVwiLiBBdmFpbGFibGUgY29sdW1uczogJHthdmFpbGFibGV9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHt2YWx1ZTogbmFtZSwgZmllbGRJZHh9O1xuICB9O1xuXG4gIC8vIFBvc2l0aW9uOiBleHBsaWNpdCBsYXQvbG5nLCBlbHNlIHRoZSBkYXRhc2V0J3MgZmlyc3QgZGV0ZWN0ZWQgcG9pbnQgcGFpcixcbiAgLy8gZWxzZSBhIEdlb0pTT04gZ2VvbWV0cnkgY29sdW1uIChvbmUgcG9zaXRpb24gcGVyIGZlYXR1cmUpLlxuICBsZXQgcG9zaXRpb25Db2x1bW5zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgbnVsbCA9IG51bGw7XG4gIGlmIChwb3NpdGlvbi5sYXRpdHVkZUNvbHVtbiAmJiBwb3NpdGlvbi5sb25naXR1ZGVDb2x1bW4pIHtcbiAgICBwb3NpdGlvbkNvbHVtbnMgPSB7XG4gICAgICBsYXQ6IGNvbHVtblJlZihwb3NpdGlvbi5sYXRpdHVkZUNvbHVtbiksXG4gICAgICBsbmc6IGNvbHVtblJlZihwb3NpdGlvbi5sb25naXR1ZGVDb2x1bW4pXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBwYWlyID0gZGF0YXNldC5maWVsZFBhaXJzPy5bMF0/LnBhaXI7XG4gICAgaWYgKHBhaXI/LmxhdCAmJiBwYWlyPy5sbmcpIHtcbiAgICAgIHBvc2l0aW9uQ29sdW1ucyA9IHtsYXQ6IHBhaXIubGF0LCBsbmc6IHBhaXIubG5nfTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZ2VvRmllbGQgPSBkYXRhc2V0LmZpZWxkcz8uZmluZChcbiAgICAgICAgKGY6IGFueSkgPT4gZi50eXBlID09PSAnZ2VvanNvbicgfHwgR0VPSlNPTl9GSUVMRFMuZ2VvanNvbi5pbmNsdWRlcyhmLm5hbWUpXG4gICAgICApO1xuICAgICAgaWYgKGdlb0ZpZWxkKSB7XG4gICAgICAgIHBvc2l0aW9uQ29sdW1ucyA9IHtnZW9qc29uOiB7dmFsdWU6IGdlb0ZpZWxkLm5hbWUsIGZpZWxkSWR4OiBnZW9GaWVsZC5maWVsZElkeH19O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoIXBvc2l0aW9uQ29sdW1ucykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdBIGZsb3cgZmllbGQgbGF5ZXIgbmVlZHMgYSBwb3NpdGlvbjogbGF0L2xuZyBjb2x1bW5zIChhdXRvLWRldGVjdGVkLCBvciBwYXNzICcgK1xuICAgICAgICAnbGF0aXR1ZGVDb2x1bW4vbG9uZ2l0dWRlQ29sdW1uKSBvciBhIEdlb0pTT04gZ2VvbWV0cnkgY29sdW1uLidcbiAgICApO1xuICB9XG5cbiAgY29uc3QgYWx0aXR1ZGVOYW1lID1cbiAgICBvcHRpb25zLmFsdGl0dWRlQ29sdW1uIHx8IEZMT1dfRklFTERfQUxUSVRVREVfQ09MVU1OUy5maW5kKG5hbWUgPT4gaGFzQ29sdW1uKG5hbWUpKSB8fCBudWxsO1xuXG4gIGNvbnN0IG1vZGU6IEZsb3dGaWVsZE1vZGUgfCBudWxsID1cbiAgICBvcHRpb25zLm1vZGUgfHxcbiAgICAob3B0aW9ucy51Q29sdW1uIHx8IG9wdGlvbnMudkNvbHVtbiB8fCAoaGFzQ29sdW1uKCd1JykgJiYgaGFzQ29sdW1uKCd2JykpXG4gICAgICA/ICdVVidcbiAgICAgIDogb3B0aW9ucy5zcGVlZENvbHVtbiB8fFxuICAgICAgICBvcHRpb25zLmRpcmVjdGlvbkNvbHVtbiB8fFxuICAgICAgICAoaGFzQ29sdW1uKCdzcGVlZCcpICYmIGhhc0NvbHVtbignZGlyZWN0aW9uJykpXG4gICAgICA/ICdTUEVFRF9ESVInXG4gICAgICA6IGFsdGl0dWRlTmFtZVxuICAgICAgPyAnRUxFVkFUSU9OJ1xuICAgICAgOiBudWxsKTtcbiAgaWYgKCFtb2RlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0EgZmxvdyBmaWVsZCBsYXllciBuZWVkcyBhIHZlY3RvcjogdS92IGNvbHVtbnMsIHNwZWVkL2RpcmVjdGlvbiBjb2x1bW5zLCBvciBhbiAnICtcbiAgICAgICAgJ2FsdGl0dWRlIGNvbHVtbiAocGFzcyBmbG93RmllbGQudUNvbHVtbi92Q29sdW1uL3NwZWVkQ29sdW1uL2RpcmVjdGlvbkNvbHVtbi8nICtcbiAgICAgICAgJ2FsdGl0dWRlQ29sdW1uIHdoZW4gdGhlIG5hbWVzIGRpZmZlcikuJ1xuICAgICk7XG4gIH1cblxuICBsZXQgZmxvd0NvbHVtbnM6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIGlmIChtb2RlID09PSAnVVYnKSB7XG4gICAgZmxvd0NvbHVtbnMgPSB7XG4gICAgICB1OiBjb2x1bW5SZWYob3B0aW9ucy51Q29sdW1uIHx8ICd1JyksXG4gICAgICB2OiBjb2x1bW5SZWYob3B0aW9ucy52Q29sdW1uIHx8ICd2JylcbiAgICB9O1xuICB9IGVsc2UgaWYgKG1vZGUgPT09ICdTUEVFRF9ESVInKSB7XG4gICAgZmxvd0NvbHVtbnMgPSB7XG4gICAgICBzcGVlZDogY29sdW1uUmVmKG9wdGlvbnMuc3BlZWRDb2x1bW4gfHwgJ3NwZWVkJyksXG4gICAgICBkaXJlY3Rpb246IGNvbHVtblJlZihvcHRpb25zLmRpcmVjdGlvbkNvbHVtbiB8fCAnZGlyZWN0aW9uJylcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIGlmICghYWx0aXR1ZGVOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdBIGZsb3cgZmllbGQgbGF5ZXIgaW4gRUxFVkFUSU9OIG1vZGUgbmVlZHMgYW4gYWx0aXR1ZGUgY29sdW1uIChwYXNzIGZsb3dGaWVsZC5hbHRpdHVkZUNvbHVtbikuJ1xuICAgICAgKTtcbiAgICB9XG4gICAgZmxvd0NvbHVtbnMgPSB7YWx0aXR1ZGU6IGNvbHVtblJlZihhbHRpdHVkZU5hbWUpfTtcbiAgfVxuXG4gIC8vIFVWIGFuZCBTUEVFRF9ESVIgbWF5IGFsc28gY2FycnkgYW4gYWx0aXR1ZGUsIHdoaWNoIGxpZnRzIHRoZSBzdHJlYW1saW5lcy5cbiAgY29uc3QgYWx0aXR1ZGVDb2x1bW4gPVxuICAgIG1vZGUgPT09ICdFTEVWQVRJT04nIHx8ICFhbHRpdHVkZU5hbWUgPyB7fSA6IHthbHRpdHVkZTogY29sdW1uUmVmKGFsdGl0dWRlTmFtZSl9O1xuXG4gIGNvbnN0IGxheWVyID0gbmV3IChMYXllckNsYXNzZXMgYXMgYW55KS5mbG93RmllbGQoe1xuICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICBsYWJlbDogJ0Zsb3cgRmllbGQnLFxuICAgIGNvbG9yOiBbMjU1LCAyNTUsIDI1NV0sXG4gICAgY29sdW1uTW9kZTogbW9kZSxcbiAgICBjb2x1bW5zOiB7Li4ucG9zaXRpb25Db2x1bW5zLCAuLi5mbG93Q29sdW1ucywgLi4uYWx0aXR1ZGVDb2x1bW59XG4gIH0pO1xuICBpZiAob3B0aW9ucy5jb2xvckJ5U3BlZWQpIHtcbiAgICBsYXllci5jb25maWcudmlzQ29uZmlnID0gey4uLmxheWVyLmNvbmZpZy52aXNDb25maWcsIGNvbG9yQnlTcGVlZDogdHJ1ZX07XG4gIH1cbiAgcmV0dXJuIGxheWVyO1xufVxuXG5mdW5jdGlvbiBidWlsZExheWVyQ29uZmlnKFxuICBsYXllcjogYW55LFxuICBkYXRhc2V0SWQ6IHN0cmluZyxcbiAgbGF5ZXJOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIHNvdXJjZU5hbWU6IHN0cmluZyxcbiAgbGF5ZXJUeXBlOiBzdHJpbmdcbikge1xuICBjb25zdCBsYXllcklkID0gbGF5ZXIuaWQgfHwgdW5pcXVlTGF5ZXJJZCgpO1xuICBjb25zdCBjb2x1bW5zID0gbGF5ZXIuY29uZmlnPy5jb2x1bW5zIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgaWQ6IGxheWVySWQsXG4gICAgdHlwZTogbGF5ZXIudHlwZSxcbiAgICBjb25maWc6IHtcbiAgICAgIC4uLmxheWVyLmNvbmZpZyxcbiAgICAgIGRhdGFJZDogZGF0YXNldElkLFxuICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgbGFiZWw6IGxheWVyTmFtZSB8fCBgJHtzb3VyY2VOYW1lfS0ke2xheWVyVHlwZX1gLFxuICAgICAgY29sdW1uczogT2JqZWN0LmtleXMoY29sdW1ucykucmVkdWNlPFJlY29yZDxzdHJpbmcsIGFueT4+KChhY2MsIGtleSkgPT4ge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBjb2x1bW5zW2tleV07XG4gICAgICAgIGlmIChjb2x1bW4pIHtcbiAgICAgICAgICBhY2Nba2V5XSA9IGNvbHVtbi52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwge30pLFxuICAgICAgdmlzQ29uZmlnOiB7XG4gICAgICAgIC4uLmxheWVyLmNvbmZpZz8udmlzQ29uZmlnXG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBhcHBseUNvbG9yQ29uZmlnKFxuICBuZXdMYXllcjogYW55LFxuICBkYXRhc2V0OiBLZXBsZXJUYWJsZSxcbiAgYXJnczoge1xuICAgIHNpbXBsZUNvbG9yPzogc3RyaW5nO1xuICAgIGNvbG9yQnk/OiBzdHJpbmc7XG4gICAgY29sb3JUeXBlPzogJ2JyZWFrcycgfCAndW5pcXVlJztcbiAgICBjb2xvck1hcD86IEFycmF5PHt2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgbnVsbDsgY29sb3I6IHN0cmluZ30+O1xuICB9XG4pIHtcbiAgaWYgKGFyZ3Muc2ltcGxlQ29sb3IpIHtcbiAgICBjb25zdCBjb2xvciA9IGFyZ3Muc2ltcGxlQ29sb3JcbiAgICAgIC5yZXBsYWNlKC9bXlxcZCxdL2csICcnKVxuICAgICAgLnNwbGl0KCcsJylcbiAgICAgIC5tYXAoTnVtYmVyKTtcbiAgICBpZiAoY29sb3IubGVuZ3RoID09PSAzKSB7XG4gICAgICBuZXdMYXllci5jb25maWcuY29sb3IgPSBjb2xvcjtcbiAgICB9XG4gIH1cblxuICBjb25zdCB7Y29sb3JCeSwgY29sb3JUeXBlLCBjb2xvck1hcDogcHJvdmlkZWRDb2xvck1hcH0gPSBhcmdzO1xuXG4gIGlmIChjb2xvckJ5KSB7XG4gICAgY29uc3QgY29sb3JGaWVsZCA9IGRhdGFzZXQuZmllbGRzLmZpbmQoZiA9PiBmLm5hbWUgPT09IGNvbG9yQnkpO1xuICAgIGlmICghY29sb3JGaWVsZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGaWVsZCAke2NvbG9yQnl9IG5vdCBmb3VuZC5gKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgY2F0ZWdvcmljYWwgKGN1c3RvbU9yZGluYWwpIGNvbG9yIG1hcHMsIGV2ZXJ5IHZhbHVlIGJlY29tZXMgdGhlIHNjYWxlXG4gICAgLy8gZG9tYWluLCBzbyBpdCBtdXN0IGJlIGEgcmVhbCB2YWx1ZSBwcmVzZW50IGluIHRoZSBkYXRhLiBUaGUgYWdlbnQgbXVzdCBub3RcbiAgICAvLyBpbnZlbnQgY2F0ZWdvcnkgbGFiZWxzIOKAlCBnZXQgdGhlbSB2aWEgZ2VvZGEuYW5hbHlzaXMgKGFuYWx5c2lzOiAnY2xhc3NpZnknLFxuICAgIC8vIG1ldGhvZDogJ3VuaXF1ZSB2YWx1ZXMnKS4gUmVqZWN0aW5nIGhlcmUgdHVybnMgYSBzaWxlbnQgd3JvbmcgcmVuZGVyIGludG8gYVxuICAgIC8vIHJlY292ZXJhYmxlIGVycm9yLiBPbmx5IHJ1biB0aGlzIHdoZW4gY29sb3JUeXBlIGlzIGV4cGxpY2l0bHkgJ3VuaXF1ZSc6XG4gICAgLy8gYW4gb21pdHRlZCBjb2xvclR5cGUgZGVmYXVsdHMgdG8gYSBjb250aW51b3VzIChicmVha3MpIHNjYWxlLCB3aG9zZVxuICAgIC8vIGNvbG9yTWFwIHZhbHVlcyBhcmUgYnJlYWsgYm91bmRhcmllcywgbm90IGRhdGEgdmFsdWVzLlxuICAgIGlmIChjb2xvclR5cGUgPT09ICd1bmlxdWUnICYmIHByb3ZpZGVkQ29sb3JNYXApIHtcbiAgICAgIC8vIFZhbGlkYXRlIHdpdGhvdXQgbWF0ZXJpYWxpemluZyB0aGUgd2hvbGUgY29sdW1uOiBzY2FuIHJvd3MsIGRlbGV0aW5nXG4gICAgICAvLyBtYXRjaGVzIGZyb20gYSBzbWFsbCBgd2FudGVkYCBzZXQgKGVhcmx5LWV4aXQgd2hlbiBhbGwgYXJlIGZvdW5kKSxcbiAgICAgIC8vIHdoaWxlIGNvbGxlY3RpbmcgYSBzbWFsbCBzYW1wbGUgb2YgYWN0dWFsIHZhbHVlcyBmb3IgdGhlIGVycm9yIG1lc3NhZ2UuXG4gICAgICAvLyBTY2FuIEFMTCByb3dzIOKAlCBhIGJvdW5kZWQgc2FtcGxlIChwcmVmaXggT1IgZml4ZWQtc3RyaWRlKSBjYW5cbiAgICAgIC8vIHN5c3RlbWF0aWNhbGx5IG1pc3MgYSBjYXRlZ29yeSB0aGF0IGV4aXN0cyBsYXRlciBpbiB0aGUgZGF0YSBhbmRcbiAgICAgIC8vIGZhbHNlbHkgcmVwb3J0IGl0IGFzIFwibm90IGZvdW5kXCIuIFRoZSBlYXJseS1leGl0IGtlZXBzIHRoZSBjb21tb24gY2FzZVxuICAgICAgLy8gKGFsbCBjYXRlZ29yaWVzIGZvdW5kIGVhcmx5KSBmYXN0OyBvbmx5IGEgZ2VudWluZWx5IG1pc3NpbmcgY2F0ZWdvcnlcbiAgICAgIC8vIGNvc3RzIGEgZnVsbCBzY2FuLCB3aGljaCBpcyB0aGUgcHJpY2Ugb2YgYW4gYWNjdXJhdGUgZXJyb3IuXG4gICAgICBjb25zdCB3YW50ZWQgPSBuZXcgU2V0KHByb3ZpZGVkQ29sb3JNYXAubWFwKGMgPT4gYy52YWx1ZSkpO1xuICAgICAgY29uc3Qgc2FtcGxlOiB1bmtub3duW10gPSBbXTtcbiAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHVua25vd24+KCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGFzZXQubGVuZ3RoICYmIHdhbnRlZC5zaXplID4gMDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHYgPSBkYXRhc2V0LmdldFZhbHVlKGNvbG9yQnksIGkpO1xuICAgICAgICBpZiAod2FudGVkLmhhcyh2KSkge1xuICAgICAgICAgIHdhbnRlZC5kZWxldGUodik7XG4gICAgICAgIH0gZWxzZSBpZiAoIXNlZW4uaGFzKHYpICYmIHNhbXBsZS5sZW5ndGggPCAyMCkge1xuICAgICAgICAgIHNlZW4uYWRkKHYpO1xuICAgICAgICAgIHNhbXBsZS5wdXNoKHYpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAod2FudGVkLnNpemUgPiAwKSB7XG4gICAgICAgIGNvbnN0IG1pc3NpbmcgPSBbLi4ud2FudGVkXTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBjb2xvck1hcCB2YWx1ZShzKSAke21pc3NpbmdcbiAgICAgICAgICAgIC5tYXAodiA9PiBKU09OLnN0cmluZ2lmeSh2KSlcbiAgICAgICAgICAgIC5qb2luKCcsICcpfSBub3QgZm91bmQgaW4gZmllbGQgXCIke2NvbG9yQnl9XCIuIGAgK1xuICAgICAgICAgICAgYEFjdHVhbCB1bmlxdWUgdmFsdWVzOiAke3NhbXBsZS5tYXAodiA9PiBKU09OLnN0cmluZ2lmeSh2KSkuam9pbignLCAnKX0ke1xuICAgICAgICAgICAgICBzYW1wbGUubGVuZ3RoID49IDIwID8gJywg4oCmJyA6ICcnXG4gICAgICAgICAgICB9LiBgICtcbiAgICAgICAgICAgIGBDYWxsIGdlb2RhLmFuYWx5c2lzIChhbmFseXNpczogJ2NsYXNzaWZ5JywgbWV0aG9kOiAndW5pcXVlIHZhbHVlcycpIHRvIGdldCB0aGUgcmVhbCB2YWx1ZXMuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvbG9yVHlwZSBpcyBvcHRpb25hbDsgd2hlbiBvbWl0dGVkLCBkZWZhdWx0IHRvIGEgY29udGludW91cyAoYnJlYWtzKVxuICAgIC8vIHNjYWxlIHNvIG51bWVyaWMgZmllbGRzIGNvbG9yZWQgdmlhIGNvbG9yQnkgYXJlbid0IG1pcy1jb2xvcmVkIGFzXG4gICAgLy8gY2F0ZWdvcmljYWwuIE9ubHkgYW4gZXhwbGljaXQgJ3VuaXF1ZScgc2VsZWN0cyB0aGUgY2F0ZWdvcmljYWwgc2NhbGUuXG4gICAgY29uc3QgY29sb3JTY2FsZSA9IGNvbG9yVHlwZSA9PT0gJ3VuaXF1ZScgPyAnY3VzdG9tT3JkaW5hbCcgOiAnY3VzdG9tJztcblxuICAgIC8vIE9ubHkgZm9yY2UgYSBjdXN0b20gcGFsZXR0ZSB3aGVuIHRoZSBjYWxsZXIgcHJvdmlkZWQgYW4gZXhwbGljaXRcbiAgICAvLyBjb2xvck1hcC4gQSBzeW50aGV0aWMgc2luZ2xlLWVudHJ5IGNvbG9yTWFwICh7dmFsdWU6IG51bGwsIGNvbG9yOlxuICAgIC8vICcjMzMzMzMzJ30pIHdvdWxkIHJvdXRlIHRocm91Z2gga2VwbGVyJ3MgY3VzdG9tIGNvbG9yTWFwIHNjYWxlIHBhdGggYW5kXG4gICAgLy8gcmVuZGVyIGV2ZXJ5dGhpbmcgYXMgdGhlIG5vLXZhbHVlL3Vua25vd24gY29sb3I7IHdpdGhvdXQgYW4gZXhwbGljaXRcbiAgICAvLyBjb2xvck1hcCwgYmluZCB0aGUgY29sb3IgZmllbGQgYW5kIGxldCBrZXBsZXIuZ2wncyBkZWZhdWx0IGNvbG9yIHJhbmdlXG4gICAgLy8gYXBwbHkuXG4gICAgY29uc3QgY29sb3JSYW5nZSA9IHByb3ZpZGVkQ29sb3JNYXBcbiAgICAgID8gKHtcbiAgICAgICAgICBuYW1lOiAnY29sb3IuY3VzdG9tUGFsZXR0ZScsXG4gICAgICAgICAgdHlwZTogJ2N1c3RvbScsXG4gICAgICAgICAgY2F0ZWdvcnk6ICdDdXN0b20nLFxuICAgICAgICAgIGNvbG9yczogcHJvdmlkZWRDb2xvck1hcC5tYXAoYyA9PiBjLmNvbG9yKSxcbiAgICAgICAgICBjb2xvck1hcDogcHJvdmlkZWRDb2xvck1hcC5tYXAoYyA9PiBbYy52YWx1ZSwgYy5jb2xvcl0pXG4gICAgICAgIH0gYXMgY29uc3QpXG4gICAgICA6IG51bGw7XG5cbiAgICBpZiAobmV3TGF5ZXIudHlwZSA9PT0gJ2hlYXRtYXAnKSB7XG4gICAgICBpZiAoY29sb3JSYW5nZSAmJiBwcm92aWRlZENvbG9yTWFwICYmIHByb3ZpZGVkQ29sb3JNYXAubGVuZ3RoID4gMSkge1xuICAgICAgICBuZXdMYXllci5jb25maWcudmlzQ29uZmlnWydjb2xvclJhbmdlJ10gPSB7Li4uY29sb3JSYW5nZX07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snY29sb3JTY2FsZSddID0gY29sb3JTY2FsZTtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snY29sb3JGaWVsZCddID0gY29sb3JGaWVsZDtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snc3Ryb2tlQ29sb3JTY2FsZSddID0gY29sb3JTY2FsZTtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snc3Ryb2tlQ29sb3JGaWVsZCddID0gY29sb3JGaWVsZDtcbiAgICAgIG5ld0xheWVyLmNvbmZpZy52aXNDb25maWdbJ2ZpbGxlZCddID0gdHJ1ZTtcbiAgICAgIGlmIChjb2xvclJhbmdlKSB7XG4gICAgICAgIG5ld0xheWVyLmNvbmZpZy52aXNDb25maWdbJ2NvbG9yUmFuZ2UnXSA9IGNvbG9yUmFuZ2U7XG4gICAgICAgIG5ld0xheWVyLmNvbmZpZy52aXNDb25maWdbJ3N0cm9rZUNvbG9yUmFuZ2UnXSA9IGNvbG9yUmFuZ2U7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBhZGRMYXllckNvbW1hbmRJZCA9ICdtYXAuYWRkLWxheWVyJyBhcyBjb25zdDtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFkZExheWVyQ29tbWFuZChjdHg6IEtlcGxlckNvbnRleHQpOiBSb29tQ29tbWFuZCB7XG4gIHJldHVybiB7XG4gICAgaWQ6IGFkZExheWVyQ29tbWFuZElkLFxuICAgIG5hbWU6ICdBZGQgbWFwIGxheWVyJyxcbiAgICBncm91cDogJ01hcCcsXG4gICAgZGVzY3JpcHRpb246IGBBZGQgYSBrZXBsZXIuZ2wgbWFwIGxheWVyIGZyb20gYSBkYXRhc2V0LlxuSU1QT1JUQU5UOiBnZW5lcmF0ZWQgbGF5ZXIgbmFtZXMgbXVzdCBiZSB1bmlxdWUuXG5cbkxBWUVSIFRZUEVTOlxuLSBwb2ludDogUG9pbnQgbWFya2VycyAocmVxdWlyZXMgbGF0L2xuZyBjb2x1bW5zKVxuLSBmbG93OiBPcmlnaW4tPmRlc3RpbmF0aW9uIGZsb3cgbWFwIChyZXF1aXJlcyB0d28gcG9pbnQgbGF0L2xuZyBwYWlycywgYXV0by1kZXRlY3RlZClcbi0gZmxvd0ZpZWxkOiBBbmltYXRlZCBzdHJlYW1saW5lcyBvdmVyIGEgdmVjdG9yIGZpZWxkICh1L3YsIHNwZWVkL2RpcmVjdGlvbiwgb3IgYWx0aXR1ZGUpXG4tIGgzOiBIMyBoZXhhZ29uIGNlbGxzIChyZXF1aXJlcyBoZXhJZCBjb2x1bW4pXG4tIGdlb2pzb246IFBvbHlnb24vZ2VvbWV0cnkgZmVhdHVyZXMgKHVzZXMgZ2VvbWV0cnkgY29sdW1uLCB1c3VhbGx5IGF1dG8tZGV0ZWN0ZWQpXG4tIGhleGFnb246IEhleGFnb25hbCBiaW5uaW5nIG9mIHBvaW50c1xuLSBoZWF0bWFwOiBIZWF0IG1hcCB2aXN1YWxpemF0aW9uXG4tIGNsdXN0ZXI6IENsdXN0ZXJlZCBwb2ludCB2aXN1YWxpemF0aW9uXG4tIGFyYy9saW5lOiBBcmMgb3IgbGluZSBjb25uZWN0aW9ucyBiZXR3ZWVuIHBvaW50c1xuLSBncmlkOiBHcmlkIGJpbm5pbmdcbi0gdHJpcDogQW5pbWF0ZWQgdHJpcCAoZmxpZ2h0cywgZGVsaXZlcmllcywgdmVzc2Vscylcbi0gczI6IFMyIGdlb21ldHJ5IGNlbGxzXG5cbkZMT1cgTUFQUyAobGF5ZXJUeXBlICdmbG93Jyk6XG5Gb3Igb3JpZ2luLT5kZXN0aW5hdGlvbiBmbG93cyB1c2UgbGF5ZXJUeXBlICdmbG93JyDigJQgYSBkZWRpY2F0ZWQgZmxvdyBsYXllciB0aGF0IGRyYXdzXG5sb2NhdGlvbnMgYW5kIHdlaWdodGVkIGZsb3dzIGJldHdlZW4gdGhlbS4gSXQgbmVlZHMgVFdPIHBvaW50IGxhdC9sbmcgcGFpcnMgaW4gdGhlXG5kYXRhc2V0IChzb3VyY2UgcGFpciArIGRlc3RpbmF0aW9uIHBhaXIpLCB3aGljaCBhcmUgYXV0by1kZXRlY3RlZC4gUHJlZmVyICdmbG93JyBvdmVyXG4nYXJjJyBmb3IgTy1EIGZsb3dzOyAnYXJjJyBkcmF3cyBzdHJhaWdodCBncmVhdC1jaXJjbGUgbGluZXMgd2l0aG91dCBsb2NhdGlvbiBjbHVzdGVyaW5nXG5vciBmbG93IGFnZ3JlZ2F0aW9uLiBUbyB3ZWlnaHQgdGhlIGZsb3dzIGJ5IGEgdmFsdWUgY29sdW1uIChmbG93IG1hZ25pdHVkZSksIHBhc3NcbmNvdW50Q29sdW1uIHdpdGggdGhlIGNvbHVtbiBuYW1lIOKAlCBvbWl0IGl0IHRvIHJlbmRlciBhbGwgZmxvd3MgYXQgd2VpZ2h0IDEuXG5cbkZMT1cgRklFTEQgKGxheWVyVHlwZSAnZmxvd0ZpZWxkJyk6XG5BbmltYXRlZCBzdHJlYW1saW5lcyBvdmVyIGEgdmVjdG9yIGZpZWxkIOKAlCB3aW5kLCBjdXJyZW50cywgb3IgZG93bmhpbGwgZmxvdy4gSXQgaXMgTk9UXG50aGUgb3JpZ2luLT5kZXN0aW5hdGlvbiAnZmxvdycgbGF5ZXI6ICdmbG93JyBqb2lucyB0d28gcG9pbnQgcGFpcnMsICdmbG93RmllbGQnIGRyYXdzXG5tYW55IHNob3J0IGxpbmVzIHRocm91Z2ggYSBmaWVsZCBvZiB2ZWN0b3JzLCBvbmUgcm93IHBlciBzYW1wbGUgcG9pbnQuXG5UaGUgZGlyZWN0aW9uIGNvbWVzIGZyb20gb25lIG9mIHRocmVlIGNvbHVtbiBzZXRzLCBhdXRvLWRldGVjdGVkIGluIHRoaXMgb3JkZXI6XG4tIHUvdiBjb21wb25lbnRzIChkZWZhdWx0IG1vZGUgJ1VWJyksIG9wdGlvbmFsbHkgd2l0aCBhbiBhbHRpdHVkZSBjb2x1bW5cbi0gc3BlZWQgKyBkaXJlY3Rpb24gKG1vZGUgJ1NQRUVEX0RJUicpXG4tIGFsdGl0dWRlIG9ubHkgKG1vZGUgJ0VMRVZBVElPTicpOiB0aGUgZG93bmhpbGwgZ3JhZGllbnQgZ2l2ZXMgdGhlIGRpcmVjdGlvblxuUG9zaXRpb24gaXMgbGF0L2xuZyAoYXV0by1kZXRlY3RlZCwgb3IgbGF0aXR1ZGVDb2x1bW4vbG9uZ2l0dWRlQ29sdW1uKSBvciBhIEdlb0pTT05cbmdlb21ldHJ5IGNvbHVtbi4gV2hlbiB0aGUgZGF0YXNldCBuYW1lcyB0aGUgY29sdW1ucyBkaWZmZXJlbnRseSwgcGFzcyBmbG93RmllbGQubW9kZVxucGx1cyBmbG93RmllbGQudUNvbHVtbi92Q29sdW1uL3NwZWVkQ29sdW1uL2RpcmVjdGlvbkNvbHVtbi9hbHRpdHVkZUNvbHVtbi5cblNldCBmbG93RmllbGQuY29sb3JCeVNwZWVkIHRydWUgdG8gY29sb3IgbGluZXMgYnkgbG9jYWwgc3BlZWQ7IG90aGVyd2lzZSBzaW1wbGVDb2xvclxuYXBwbGllcy4gY29sb3JCeS9jb2xvck1hcCBkbyBub3QgYXBwbHkgdG8gdGhpcyBsYXllci4gRG8gTk9UIGFkZCBhIHRpbWUgZmlsdGVyIOKAlCB0aGVcbmZsb3cgZmllbGQgYW5pbWF0ZXMgaXRzZWxmLlxuXG5CQVNJQyBNQVA6XG4tIFVzZSBkYXRhc2V0TmFtZSwgbGF0aXR1ZGVDb2x1bW4vbG9uZ2l0dWRlQ29sdW1uIChmb3IgcG9pbnQgbWFwcyksIGFuZCBsYXllclR5cGVcbi0gT21pdCBjb2xvci1yZWxhdGVkIHBhcmFtZXRlcnMgZm9yIHNpbXBsZSB2aXN1YWxpemF0aW9uLCB1c2Ugc2ltcGxlQ29sb3IgaW5zdGVhZC5cblxuQ09MT1IgTUFQUElORzpcbi0gSWYgdXNlciByZXF1ZXN0cyBjb2xvciB2aXN1YWxpemF0aW9uLCB1c2UgYXZhaWxhYmxlIGNvbHVtbnMgaW4gdGhlIGRhdGFzZXRcbi0gVXNlIGdlb2RhLmFuYWx5c2lzIChhbmFseXNpczogJ2NsYXNzaWZ5JykgdG8gY2xhc3NpZnkgZGF0YSBpbnRvIGJpbnMgb3IgdW5pcXVlIHZhbHVlcyB3aGVuIG5lZWRlZFxuLSBGb3IgY29udGludW91cyBkYXRhIChjb2xvclR5cGUgJ2JyZWFrcycpOlxuICBbe3ZhbHVlOiAwLCBjb2xvcjogJyNmZWU1ZDknfSwge3ZhbHVlOiA1MCwgY29sb3I6ICcjZmNhZTkxJ30sIHt2YWx1ZTogMTAwLCBjb2xvcjogJyNmYjZhNGEnfSwge3ZhbHVlOiBudWxsLCBjb2xvcjogJyNkZTJkMjYnfV1cbiAgVGhlIGxhc3QgZW50cnkgd2l0aCB2YWx1ZTogbnVsbCByZXByZXNlbnRzIHRoZSBjb2xvciBmb3IgdGhlIGhpZ2hlc3QgdmFsdWVzXG4tIEZvciBjYXRlZ29yaWNhbCBkYXRhIChjb2xvclR5cGUgJ3VuaXF1ZScpOlxuICBbe3ZhbHVlOiAnY2F0ZWdvcnkxJywgY29sb3I6ICcjMWY3N2I0J30sIHt2YWx1ZTogJ2NhdGVnb3J5MicsIGNvbG9yOiAnI2ZmN2YwZSd9XVxuICBIQVJEIFJVTEU6IHRoZSBjb2xvck1hcCB2YWx1ZXMgTVVTVCBiZSB0aGUgYWN0dWFsIHVuaXF1ZSB2YWx1ZXMgcHJlc2VudCBpbiB0aGUgZGF0YS5cbiAgQ2FsbCBnZW9kYS5hbmFseXNpcyAoYW5hbHlzaXM6ICdjbGFzc2lmeScsIG1ldGhvZDogJ3VuaXF1ZSB2YWx1ZXMnKSBmaXJzdCBhbmQgdXNlIHRoZVxuICByZXR1cm5lZCB1bmlxdWVWYWx1ZXMgdmVyYmF0aW0uIE5FVkVSIGludmVudCBjYXRlZ29yeSBsYWJlbHMgZnJvbSB0aGUgZmllbGQgbmFtZSDigJRcbiAgdGhlIGNvbW1hbmQgcmVqZWN0cyB2YWx1ZXMgdGhhdCBkbyBub3QgZXhpc3QgaW4gdGhlIGRhdGEuXG4tIElmIHRoZSB1c2VyIGRvZXNuJ3Qgc3BlY2lmeSBjb2xvcnMsIG9taXQgY29sb3JCeS9jb2xvck1hcCDigJQga2VwbGVyLmdsIGFwcGxpZXMgaXRzIGRlZmF1bHQgY29sb3IgcmFuZ2UgYXV0b21hdGljYWxseVxuXG5Gb3IgZ2VvanNvbiBkYXRhc2V0czpcbi0gVXNlIGdlb21ldHJ5Q29sdW1uOiAnX2dlb2pzb24nIGFuZCBsYXllclR5cGU6ICdnZW9qc29uJyBldmVuIGZvciBwb2ludCBjb2xsZWN0aW9uc1xuYCxcbiAgICBtZXRhZGF0YToge3JlYWRPbmx5OiBmYWxzZSwgcmlza0xldmVsOiAnbWVkaXVtJywgaWRlbXBvdGVudDogZmFsc2V9LFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBkYXRhc2V0TmFtZTogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKCdUaGUgbmFtZSAobGFiZWwpIG9yIGlkIG9mIHRoZSBkYXRhc2V0LiBQcmVmZXIgdGhlIGxhYmVsIHdoZW4ga25vd24uJyksXG4gICAgICBsYXRpdHVkZUNvbHVtbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbG9uZ2l0dWRlQ29sdW1uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsYXllck5hbWU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZSgnR2VuZXJhdGUgYSB1bmlxdWUgbmFtZSBmb3IgdGhlIGxheWVyIGJhc2VkIG9uIHRoZSBjb250ZXh0LicpLFxuICAgICAgbGF5ZXJUeXBlOiB6LmVudW0oW1xuICAgICAgICAncG9pbnQnLFxuICAgICAgICAnZmxvdycsXG4gICAgICAgICdmbG93RmllbGQnLFxuICAgICAgICAnYXJjJyxcbiAgICAgICAgJ2xpbmUnLFxuICAgICAgICAnZ3JpZCcsXG4gICAgICAgICdoZXhhZ29uJyxcbiAgICAgICAgJ2dlb2pzb24nLFxuICAgICAgICAnY2x1c3RlcicsXG4gICAgICAgICdoZWF0bWFwJyxcbiAgICAgICAgJ2gzJyxcbiAgICAgICAgJ3RyaXAnLFxuICAgICAgICAnczInXG4gICAgICBdKSxcbiAgICAgIGZsb3dGaWVsZDogelxuICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICBtb2RlOiB6LmVudW0oRkxPV19GSUVMRF9NT0RFUykub3B0aW9uYWwoKSxcbiAgICAgICAgICB1Q29sdW1uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICAgICAgdkNvbHVtbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgICAgIHNwZWVkQ29sdW1uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICAgICAgZGlyZWN0aW9uQ29sdW1uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICAgICAgYWx0aXR1ZGVDb2x1bW46IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICAgICAgICBjb2xvckJ5U3BlZWQ6IHouYm9vbGVhbigpLm9wdGlvbmFsKClcbiAgICAgICAgfSlcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICdGb3IgbGF5ZXJUeXBlIFwiZmxvd0ZpZWxkXCIgb25seTogaG93IHRoZSB2ZWN0b3IgZmllbGQgaXMgZW5jb2RlZC4gVGhlIG1vZGUgaXMgJyArXG4gICAgICAgICAgICAnaW5mZXJyZWQgZnJvbSB0aGUgY29sdW1ucyAodS92LCBzcGVlZC9kaXJlY3Rpb24sIG90aGVyd2lzZSBhbHRpdHVkZSk7IHRoZSAnICtcbiAgICAgICAgICAgICcqQ29sdW1uIGZpZWxkcyBuYW1lIHRoZSBjb2x1bW5zIHdoZW4gdGhleSBkaWZmZXIgZnJvbSB0aG9zZSBkZWZhdWx0cy4nXG4gICAgICAgICksXG4gICAgICBzaW1wbGVDb2xvcjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICdUaGUgY29sb3Igb2YgdGhlIGxheWVyIGUuZy4gWzI1NSwgMCwgMF0uIE9ubHkgdXNlZCBmb3Igc2ltcGxlIG1hcCB2aXN1YWxpemF0aW9uIChubyBjb2xvckJ5LCBjb2xvclR5cGUsIGNvbG9yTWFwKS4nXG4gICAgICAgICksXG4gICAgICBjb2xvckJ5OiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBjb2xvclR5cGU6IHouZW51bShbJ2JyZWFrcycsICd1bmlxdWUnXSkub3B0aW9uYWwoKSxcbiAgICAgIGNvdW50Q29sdW1uOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgJ0ZvciBsYXllclR5cGUgXCJmbG93XCIgKGFuZCBvbmx5IGZsb3cpOiBhIG51bWVyaWMgY29sdW1uIHdob3NlIHZhbHVlIHdlaWdodHMgZWFjaCBmbG93IChmbG93IG1hZ25pdHVkZSkuIE9taXQgdG8gcmVuZGVyIGFsbCBmbG93cyBhdCB3ZWlnaHQgMS4nXG4gICAgICAgICksXG4gICAgICBjb2xvck1hcDogelxuICAgICAgICAuYXJyYXkoXG4gICAgICAgICAgei5vYmplY3Qoe1xuICAgICAgICAgICAgdmFsdWU6IHoudW5pb24oW3ouc3RyaW5nKCksIHoubnVtYmVyKCksIHoubnVsbCgpXSksXG4gICAgICAgICAgICBjb2xvcjogei5zdHJpbmcoKVxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICB9KSBhcyBhbnksXG4gICAgZXhlY3V0ZTogYXN5bmMgKF9leGVjQ3R4LCBpbnB1dCkgPT4ge1xuICAgICAgY29uc3QgYXJncyA9IChpbnB1dCA/PyB7fSkgYXMge1xuICAgICAgICBkYXRhc2V0TmFtZTogc3RyaW5nO1xuICAgICAgICBsYXllck5hbWU/OiBzdHJpbmc7XG4gICAgICAgIGxhdGl0dWRlQ29sdW1uPzogc3RyaW5nO1xuICAgICAgICBsb25naXR1ZGVDb2x1bW4/OiBzdHJpbmc7XG4gICAgICAgIGxheWVyVHlwZTogc3RyaW5nO1xuICAgICAgICBzaW1wbGVDb2xvcj86IHN0cmluZztcbiAgICAgICAgY29sb3JCeT86IHN0cmluZztcbiAgICAgICAgY29sb3JUeXBlPzogJ2JyZWFrcycgfCAndW5pcXVlJztcbiAgICAgICAgY29sb3JNYXA/OiBBcnJheTx7dmFsdWU6IHN0cmluZyB8IG51bWJlciB8IG51bGw7IGNvbG9yOiBzdHJpbmd9PjtcbiAgICAgICAgY291bnRDb2x1bW4/OiBzdHJpbmc7XG4gICAgICAgIGZsb3dGaWVsZD86IEZsb3dGaWVsZE9wdGlvbnM7XG4gICAgICB9O1xuICAgICAgY29uc3Qge1xuICAgICAgICBkYXRhc2V0TmFtZSxcbiAgICAgICAgbGF5ZXJOYW1lLFxuICAgICAgICBsYXRpdHVkZUNvbHVtbixcbiAgICAgICAgbG9uZ2l0dWRlQ29sdW1uLFxuICAgICAgICBsYXllclR5cGUsXG4gICAgICAgIHNpbXBsZUNvbG9yLFxuICAgICAgICBjb2xvckJ5LFxuICAgICAgICBjb2xvclR5cGUsXG4gICAgICAgIGNvbG9yTWFwLFxuICAgICAgICBjb3VudENvbHVtbixcbiAgICAgICAgZmxvd0ZpZWxkXG4gICAgICB9ID0gYXJncztcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFJ1bnRpbWUgZ3VhcmQ6IHRoZSBicmlkZ2Uvd2ViTUNQIGNhbGwgZXhlY3V0ZSB3aXRob3V0IHpvZCBwYXJzaW5nLCBzb1xuICAgICAgICAvLyBhIG1pc3NpbmcvaW52YWxpZCBsYXllclR5cGUgbXVzdCBub3QgZmFsbCB0aHJvdWdoIHRvXG4gICAgICAgIC8vIGd1ZXNzRGVmYXVsdExheWVyJ3MgZmlyc3QtZGVmYXVsdC1sYXllciBmYWxsYmFjayAobGF5ZXJUeXBlIGlzXG4gICAgICAgIC8vIHJlcXVpcmVkIGJ5IHRoZSBjb21tYW5kIGNvbnRyYWN0KS5cbiAgICAgICAgY29uc3QgVkFMSURfTEFZRVJfVFlQRVMgPSBbXG4gICAgICAgICAgJ3BvaW50JyxcbiAgICAgICAgICAnZmxvdycsXG4gICAgICAgICAgJ2Zsb3dGaWVsZCcsXG4gICAgICAgICAgJ2FyYycsXG4gICAgICAgICAgJ2xpbmUnLFxuICAgICAgICAgICdncmlkJyxcbiAgICAgICAgICAnaGV4YWdvbicsXG4gICAgICAgICAgJ2dlb2pzb24nLFxuICAgICAgICAgICdjbHVzdGVyJyxcbiAgICAgICAgICAnaGVhdG1hcCcsXG4gICAgICAgICAgJ2gzJyxcbiAgICAgICAgICAndHJpcCcsXG4gICAgICAgICAgJ3MyJ1xuICAgICAgICBdO1xuICAgICAgICBpZiAoIWxheWVyVHlwZSB8fCAhVkFMSURfTEFZRVJfVFlQRVMuaW5jbHVkZXMobGF5ZXJUeXBlKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBJbnZhbGlkIGxheWVyVHlwZSBcIiR7U3RyaW5nKGxheWVyVHlwZSl9XCIuIE11c3QgYmUgb25lIG9mOiAke1ZBTElEX0xBWUVSX1RZUEVTLmpvaW4oXG4gICAgICAgICAgICAgICcsICdcbiAgICAgICAgICAgICl9LmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmlzU3RhdGUgPSBjdHguZ2V0VmlzU3RhdGUoKTtcbiAgICAgICAgY29uc3QgZGF0YXNldHM6IERhdGFzZXRzID0gdmlzU3RhdGUuZGF0YXNldHM7XG5cbiAgICAgICAgY29uc3QgZGF0YXNldElkID0gT2JqZWN0LmtleXMoZGF0YXNldHMpLmZpbmQoXG4gICAgICAgICAgZGF0YUlkID0+IGRhdGFzZXRzW2RhdGFJZF0ubGFiZWwgPT09IGRhdGFzZXROYW1lIHx8IGRhdGFJZCA9PT0gZGF0YXNldE5hbWVcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFkYXRhc2V0SWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERhdGFzZXQgJHtkYXRhc2V0TmFtZX0gbm90IGZvdW5kLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGF0YXNldCA9IGRhdGFzZXRzW2RhdGFzZXRJZF07XG4gICAgICAgIC8vIFRoZSBmbG93IGZpZWxkIGxheWVyIHJlc29sdmVzIGl0cyBvd24gY29sdW1ucyAocG9zaXRpb24gKyB2ZWN0b3IsIGluXG4gICAgICAgIC8vIG9uZSBvZiB0aHJlZSBtb2RlcyksIHNvIGl0IGRvZXMgbm90IGdvIHRocm91Z2ggZ3Vlc3NEZWZhdWx0TGF5ZXIg4oCUXG4gICAgICAgIC8vIHRoYXQgcGF0aCBvbmx5IGF1dG8tZGV0ZWN0cyB0aGUgdS92IGNhc2UgYW5kIHdvdWxkIGlnbm9yZSBleHBsaWNpdFxuICAgICAgICAvLyBjb2x1bW4gbmFtZXMuXG4gICAgICAgIGxldCBsYXllciA9XG4gICAgICAgICAgbGF5ZXJUeXBlID09PSAnZmxvd0ZpZWxkJ1xuICAgICAgICAgICAgPyBidWlsZEZsb3dGaWVsZExheWVyKGRhdGFzZXQsIHtsYXRpdHVkZUNvbHVtbiwgbG9uZ2l0dWRlQ29sdW1ufSwgZmxvd0ZpZWxkKVxuICAgICAgICAgICAgOiBndWVzc0RlZmF1bHRMYXllcihkYXRhc2V0LCBsYXllclR5cGUsIHtjb3VudENvbHVtbn0pO1xuXG4gICAgICAgIGlmICghbGF5ZXIpIHtcbiAgICAgICAgICBpZiAobGF5ZXJUeXBlID09PSAncG9pbnQnICYmIGxhdGl0dWRlQ29sdW1uICYmIGxvbmdpdHVkZUNvbHVtbikge1xuICAgICAgICAgICAgLy8gVmFsaWRhdGUgYm90aCBjb2x1bW5zIGV4aXN0IGJlZm9yZSBidWlsZGluZyB0aGUgY29uZmlnIOKAlFxuICAgICAgICAgICAgLy8gZ2V0Q29sdW1uRmllbGRJZHggcmV0dXJucyAtMSBmb3IgYSBtaXNzaW5nIGNvbHVtbiwgYW5kIGFuXG4gICAgICAgICAgICAvLyBpbnZhbGlkIGZpZWxkSWR4IHdvdWxkIGRpc3BhdGNoIGEgYnJva2VuIGxheWVyIGNvbmZpZyAoZW1wdHlcbiAgICAgICAgICAgIC8vIHJlbmRlciAvIGNvbmZ1c2luZyBydW50aW1lIGVycm9ycykuXG4gICAgICAgICAgICBjb25zdCBsYXRJZHggPSBkYXRhc2V0LmdldENvbHVtbkZpZWxkSWR4KGxhdGl0dWRlQ29sdW1uKTtcbiAgICAgICAgICAgIGNvbnN0IGxuZ0lkeCA9IGRhdGFzZXQuZ2V0Q29sdW1uRmllbGRJZHgobG9uZ2l0dWRlQ29sdW1uKTtcbiAgICAgICAgICAgIGlmIChsYXRJZHggPCAwIHx8IGxuZ0lkeCA8IDApIHtcbiAgICAgICAgICAgICAgY29uc3QgbWlzc2luZyA9IGxhdElkeCA8IDAgPyBsYXRpdHVkZUNvbHVtbiA6IGxvbmdpdHVkZUNvbHVtbjtcbiAgICAgICAgICAgICAgY29uc3QgYXZhaWxhYmxlID0gZGF0YXNldC5maWVsZHM/Lm1hcCgoZjogYW55KSA9PiBmLm5hbWUpLmpvaW4oJywgJykgPz8gJyc7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgQ29sdW1uIFwiJHttaXNzaW5nfVwiIG5vdCBmb3VuZCBpbiBkYXRhc2V0IFwiJHtkYXRhc2V0TmFtZX1cIi4gQXZhaWxhYmxlIGNvbHVtbnM6ICR7YXZhaWxhYmxlfWBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxheWVyID0ge1xuICAgICAgICAgICAgICBpZDogdW5pcXVlTGF5ZXJJZCgpLFxuICAgICAgICAgICAgICB0eXBlOiAncG9pbnQnLFxuICAgICAgICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICAgICAgICBkYXRhSWQ6IGRhdGFzZXRJZCxcbiAgICAgICAgICAgICAgICBsYWJlbDogbGF5ZXJOYW1lIHx8IGAke2RhdGFzZXROYW1lfS0ke2xheWVyVHlwZX1gLFxuICAgICAgICAgICAgICAgIGNvbHVtbnM6IHtcbiAgICAgICAgICAgICAgICAgIGxhdDoge3ZhbHVlOiBsYXRpdHVkZUNvbHVtbiwgZmllbGRJZHg6IGxhdElkeH0sXG4gICAgICAgICAgICAgICAgICBsbmc6IHt2YWx1ZTogbG9uZ2l0dWRlQ29sdW1uLCBmaWVsZElkeDogbG5nSWR4fVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdmlzQ29uZmlnOiB7fVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGFzIGFueTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFsYXllcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBDb3VsZCBub3QgY3JlYXRlICR7bGF5ZXJUeXBlfSBsYXllci4gQ2hlY2sgdGhhdCB0aGUgZGF0YXNldCBoYXMgdGhlIHJlcXVpcmVkIGNvbHVtbnMuYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXdMYXllciA9IGJ1aWxkTGF5ZXJDb25maWcobGF5ZXIsIGRhdGFzZXRJZCwgbGF5ZXJOYW1lLCBkYXRhc2V0TmFtZSwgbGF5ZXJUeXBlKTtcbiAgICAgICAgYXBwbHlDb2xvckNvbmZpZyhuZXdMYXllciwgZGF0YXNldCwge3NpbXBsZUNvbG9yLCBjb2xvckJ5LCBjb2xvclR5cGUsIGNvbG9yTWFwfSk7XG5cbiAgICAgICAgY3R4LmRpc3BhdGNoKGFkZExheWVyQWN0aW9uKG5ld0xheWVyLCBkYXRhc2V0SWQpKTtcblxuICAgICAgICAvLyBDZW50ZXIgdGhlIG1hcCBvbiB0aGUgbmV3IGxheWVyJ3MgZGF0YSBib3VuZHMuIGBhZGREYXRhVG9NYXBgIHdpdGhcbiAgICAgICAgLy8gYGF1dG9DcmVhdGVMYXllcnM6IGZhbHNlYCAodXNlZCBieSBgbWFwLmxvYWQtZGF0YWApIG5ldmVyIGZpdHMgYm91bmRzXG4gICAgICAgIC8vIGJlY2F1c2Ugbm8gbGF5ZXIgZXhpc3RzIGF0IGxvYWQgdGltZSwgYW5kIGBhZGRMYXllclVwZGF0ZXJgIGRvZXMgbm90XG4gICAgICAgIC8vIGNlbnRlciBlaXRoZXIg4oCUIHNvIGZpdCBoZXJlIGV4cGxpY2l0bHkuXG4gICAgICAgIGNvbnN0IGFkZGVkTGF5ZXIgPSBjdHguZ2V0VmlzU3RhdGUoKS5sYXllcnMuZmluZChsID0+IGwuaWQgPT09IG5ld0xheWVyLmlkKTtcbiAgICAgICAgY29uc3QgYm91bmRzID0gYWRkZWRMYXllciA/IGZpbmRNYXBCb3VuZHMoW2FkZGVkTGF5ZXJdKSA6IG51bGw7XG4gICAgICAgIGlmIChib3VuZHMpIHtcbiAgICAgICAgICBjdHguZGlzcGF0Y2goZml0Qm91bmRzKGJvdW5kcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGVtcG9yYWxGaWVsZHMgPSBkYXRhc2V0LmZpZWxkc1xuICAgICAgICAgID8uZmlsdGVyKChmOiBhbnkpID0+IGYudHlwZSA9PT0gJ3RpbWVzdGFtcCcgfHwgZi50eXBlID09PSAnZGF0ZScpXG4gICAgICAgICAgLm1hcCgoZjogYW55KSA9PiBmLm5hbWUpO1xuICAgICAgICBjb25zdCBoYXNUZW1wb3JhbEZpZWxkcyA9IHRlbXBvcmFsRmllbGRzICYmIHRlbXBvcmFsRmllbGRzLmxlbmd0aCA+IDA7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgIGNvbW1hbmRJZDogYWRkTGF5ZXJDb21tYW5kSWQsXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgZGV0YWlsczogYE1hcCBsYXllciAke25ld0xheWVyLmlkfSBoYXMgYmVlbiBhZGRlZCB0byB0aGUgbWFwLmAsXG4gICAgICAgICAgICBkYXRlVGltZUNvbHVtbnM6IGhhc1RlbXBvcmFsRmllbGRzID8gdGVtcG9yYWxGaWVsZHMgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBkYXRlVGltZUhpbnQ6IGhhc1RlbXBvcmFsRmllbGRzXG4gICAgICAgICAgICAgID8gYERhdGVUaW1lIGNvbHVtbnMgZGV0ZWN0ZWQ6ICR7dGVtcG9yYWxGaWVsZHMuam9pbihcbiAgICAgICAgICAgICAgICAgICcsICdcbiAgICAgICAgICAgICAgICApfS4gWW91IGNhbiBjYWxsIGFkZFRpbWVGaWx0ZXIgd2l0aCBvbmUgb2YgdGhlc2UgY29sdW1ucyB0byBlbmFibGUgdGltZS1yYW5nZSBhbmltYXRpb24gb24gdGhlIG1hcC5gXG4gICAgICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICBjb21tYW5kSWQ6IGFkZExheWVyQ29tbWFuZElkLFxuICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdVbmtub3duIGVycm9yJyxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBpbnN0cnVjdGlvbjpcbiAgICAgICAgICAgICAgJ1RyeSB0byBmaXggdGhlIGVycm9yLiBJZiB0aGUgZXJyb3IgcGVyc2lzdHMsIGFzayB0aGUgdXNlciB0byB0cnkgd2l0aCBkaWZmZXJlbnQgcGFyYW1ldGVycy4nXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQTs7QUFHQSxTQUFRQSxDQUFDLFFBQU8sS0FBSztBQUNyQixTQUFRQyxjQUFjLFFBQU8sc0JBQXNCO0FBQ25ELFNBQVFDLFlBQVksUUFBTyxtQkFBbUI7QUFHOUMsU0FBUUMsZ0JBQWdCLEVBQUVDLGFBQWEsUUFBTyxxQkFBcUI7QUFDbkUsU0FBUUMsUUFBUSxJQUFJQyxjQUFjLEVBQUVDLFNBQVMsUUFBTyxvQkFBb0I7QUFHeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxhQUFhQSxDQUFBLEVBQTJCO0VBQUEsSUFBMUJDLE1BQU0sR0FBQUMsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsT0FBTztFQUNyQyxVQUFBRyxNQUFBLENBQVVKLE1BQU0sT0FBQUksTUFBQSxDQUFJQyxJQUFJLENBQUNDLEdBQUcsQ0FBQyxDQUFDLE9BQUFGLE1BQUEsQ0FBSUcsSUFBSSxDQUFDQyxNQUFNLENBQUMsQ0FBQyxDQUFDQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUNDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzFFO0FBRUEsT0FBTyxTQUFTQyxpQkFBaUJBLENBQy9CQyxPQUFvQixFQUNwQkMsU0FBaUIsRUFDakJDLE9BQWdDLEVBQ2hDO0VBQ0EsSUFBSUQsU0FBUyxLQUFLLFNBQVMsRUFBRTtJQUMzQixJQUFJRCxPQUFPLENBQUNHLFVB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