@macrostrat/cesium-martini 1.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -23
- package/dist/index.js +595 -166
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/webpack.config.js +7 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
3
5
|
var cesium = require('cesium');
|
|
4
6
|
|
|
7
|
+
function ownKeys(object, enumerableOnly) {
|
|
8
|
+
var keys = Object.keys(object);
|
|
9
|
+
|
|
10
|
+
if (Object.getOwnPropertySymbols) {
|
|
11
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
12
|
+
|
|
13
|
+
if (enumerableOnly) {
|
|
14
|
+
symbols = symbols.filter(function (sym) {
|
|
15
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
keys.push.apply(keys, symbols);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return keys;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function _objectSpread2(target) {
|
|
26
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
27
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
28
|
+
|
|
29
|
+
if (i % 2) {
|
|
30
|
+
ownKeys(Object(source), true).forEach(function (key) {
|
|
31
|
+
_defineProperty(target, key, source[key]);
|
|
32
|
+
});
|
|
33
|
+
} else if (Object.getOwnPropertyDescriptors) {
|
|
34
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
35
|
+
} else {
|
|
36
|
+
ownKeys(Object(source)).forEach(function (key) {
|
|
37
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return target;
|
|
43
|
+
}
|
|
44
|
+
|
|
5
45
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
6
46
|
try {
|
|
7
47
|
var info = gen[key](arg);
|
|
@@ -75,6 +115,117 @@ function _defineProperty(obj, key, value) {
|
|
|
75
115
|
return obj;
|
|
76
116
|
}
|
|
77
117
|
|
|
118
|
+
function _inherits(subClass, superClass) {
|
|
119
|
+
if (typeof superClass !== "function" && superClass !== null) {
|
|
120
|
+
throw new TypeError("Super expression must either be null or a function");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
124
|
+
constructor: {
|
|
125
|
+
value: subClass,
|
|
126
|
+
writable: true,
|
|
127
|
+
configurable: true
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function _getPrototypeOf(o) {
|
|
134
|
+
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
|
|
135
|
+
return o.__proto__ || Object.getPrototypeOf(o);
|
|
136
|
+
};
|
|
137
|
+
return _getPrototypeOf(o);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function _setPrototypeOf(o, p) {
|
|
141
|
+
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
142
|
+
o.__proto__ = p;
|
|
143
|
+
return o;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return _setPrototypeOf(o, p);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function _isNativeReflectConstruct() {
|
|
150
|
+
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
151
|
+
if (Reflect.construct.sham) return false;
|
|
152
|
+
if (typeof Proxy === "function") return true;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
156
|
+
return true;
|
|
157
|
+
} catch (e) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function _assertThisInitialized(self) {
|
|
163
|
+
if (self === void 0) {
|
|
164
|
+
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return self;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function _possibleConstructorReturn(self, call) {
|
|
171
|
+
if (call && (typeof call === "object" || typeof call === "function")) {
|
|
172
|
+
return call;
|
|
173
|
+
} else if (call !== void 0) {
|
|
174
|
+
throw new TypeError("Derived constructors may only return object or undefined");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return _assertThisInitialized(self);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function _createSuper(Derived) {
|
|
181
|
+
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
|
182
|
+
|
|
183
|
+
return function _createSuperInternal() {
|
|
184
|
+
var Super = _getPrototypeOf(Derived),
|
|
185
|
+
result;
|
|
186
|
+
|
|
187
|
+
if (hasNativeReflectConstruct) {
|
|
188
|
+
var NewTarget = _getPrototypeOf(this).constructor;
|
|
189
|
+
|
|
190
|
+
result = Reflect.construct(Super, arguments, NewTarget);
|
|
191
|
+
} else {
|
|
192
|
+
result = Super.apply(this, arguments);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return _possibleConstructorReturn(this, result);
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function _superPropBase(object, property) {
|
|
200
|
+
while (!Object.prototype.hasOwnProperty.call(object, property)) {
|
|
201
|
+
object = _getPrototypeOf(object);
|
|
202
|
+
if (object === null) break;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return object;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function _get() {
|
|
209
|
+
if (typeof Reflect !== "undefined" && Reflect.get) {
|
|
210
|
+
_get = Reflect.get;
|
|
211
|
+
} else {
|
|
212
|
+
_get = function _get(target, property, receiver) {
|
|
213
|
+
var base = _superPropBase(target, property);
|
|
214
|
+
|
|
215
|
+
if (!base) return;
|
|
216
|
+
var desc = Object.getOwnPropertyDescriptor(base, property);
|
|
217
|
+
|
|
218
|
+
if (desc.get) {
|
|
219
|
+
return desc.get.call(arguments.length < 3 ? target : receiver);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return desc.value;
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return _get.apply(this, arguments);
|
|
227
|
+
}
|
|
228
|
+
|
|
78
229
|
function _toConsumableArray(arr) {
|
|
79
230
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
80
231
|
}
|
|
@@ -108,6 +259,194 @@ function _nonIterableSpread() {
|
|
|
108
259
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
109
260
|
}
|
|
110
261
|
|
|
262
|
+
var loadImage = function loadImage(url) {
|
|
263
|
+
return new Promise(function (resolve, reject) {
|
|
264
|
+
var img = new Image();
|
|
265
|
+
img.addEventListener("load", function () {
|
|
266
|
+
return resolve(img);
|
|
267
|
+
});
|
|
268
|
+
img.addEventListener("error", function (err) {
|
|
269
|
+
return reject(err);
|
|
270
|
+
});
|
|
271
|
+
img.crossOrigin = "anonymous";
|
|
272
|
+
img.src = url;
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
var DefaultHeightmapResource = /*#__PURE__*/function () {
|
|
277
|
+
function DefaultHeightmapResource() {
|
|
278
|
+
var _this = this,
|
|
279
|
+
_opts$skipOddLevels,
|
|
280
|
+
_opts$tileSize,
|
|
281
|
+
_opts$maxZoom;
|
|
282
|
+
|
|
283
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
284
|
+
|
|
285
|
+
_classCallCheck(this, DefaultHeightmapResource);
|
|
286
|
+
|
|
287
|
+
_defineProperty(this, "resource", null);
|
|
288
|
+
|
|
289
|
+
_defineProperty(this, "tileSize", 256);
|
|
290
|
+
|
|
291
|
+
_defineProperty(this, "maxZoom", void 0);
|
|
292
|
+
|
|
293
|
+
_defineProperty(this, "skipOddLevels", false);
|
|
294
|
+
|
|
295
|
+
_defineProperty(this, "contextQueue", void 0);
|
|
296
|
+
|
|
297
|
+
_defineProperty(this, "getTilePixels", /*#__PURE__*/function () {
|
|
298
|
+
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(coords) {
|
|
299
|
+
var url, img;
|
|
300
|
+
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
301
|
+
while (1) {
|
|
302
|
+
switch (_context.prev = _context.next) {
|
|
303
|
+
case 0:
|
|
304
|
+
url = _this.buildTileURL(coords);
|
|
305
|
+
_context.next = 3;
|
|
306
|
+
return loadImage(url);
|
|
307
|
+
|
|
308
|
+
case 3:
|
|
309
|
+
img = _context.sent;
|
|
310
|
+
return _context.abrupt("return", _this.getPixels(img));
|
|
311
|
+
|
|
312
|
+
case 5:
|
|
313
|
+
case "end":
|
|
314
|
+
return _context.stop();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}, _callee);
|
|
318
|
+
}));
|
|
319
|
+
|
|
320
|
+
return function (_x) {
|
|
321
|
+
return _ref.apply(this, arguments);
|
|
322
|
+
};
|
|
323
|
+
}());
|
|
324
|
+
|
|
325
|
+
if (opts.url) {
|
|
326
|
+
this.resource = cesium.Resource.createIfNeeded(opts.url);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
this.skipOddLevels = (_opts$skipOddLevels = opts.skipOddLevels) !== null && _opts$skipOddLevels !== void 0 ? _opts$skipOddLevels : false;
|
|
330
|
+
this.tileSize = (_opts$tileSize = opts.tileSize) !== null && _opts$tileSize !== void 0 ? _opts$tileSize : 256;
|
|
331
|
+
this.maxZoom = (_opts$maxZoom = opts.maxZoom) !== null && _opts$maxZoom !== void 0 ? _opts$maxZoom : 15;
|
|
332
|
+
this.contextQueue = [];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
_createClass(DefaultHeightmapResource, [{
|
|
336
|
+
key: "getCanvas",
|
|
337
|
+
value: function getCanvas() {
|
|
338
|
+
var ctx = this.contextQueue.pop();
|
|
339
|
+
|
|
340
|
+
if (ctx == null) {
|
|
341
|
+
var canvas = document.createElement("canvas");
|
|
342
|
+
canvas.width = this.tileSize;
|
|
343
|
+
canvas.height = this.tileSize;
|
|
344
|
+
var context = canvas.getContext("2d");
|
|
345
|
+
ctx = {
|
|
346
|
+
canvas: canvas,
|
|
347
|
+
context: context
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return ctx;
|
|
352
|
+
}
|
|
353
|
+
}, {
|
|
354
|
+
key: "getPixels",
|
|
355
|
+
value: function getPixels(img) {
|
|
356
|
+
var canvasRef = this.getCanvas();
|
|
357
|
+
var context = canvasRef.context; //context.scale(1, -1);
|
|
358
|
+
// Chrome appears to vertically flip the image for reasons that are unclear
|
|
359
|
+
// We can make it work in Chrome by drawing the image upside-down at this step.
|
|
360
|
+
|
|
361
|
+
context.drawImage(img, 0, 0, this.tileSize, this.tileSize);
|
|
362
|
+
var pixels = context.getImageData(0, 0, this.tileSize, this.tileSize);
|
|
363
|
+
context.clearRect(0, 0, this.tileSize, this.tileSize);
|
|
364
|
+
this.contextQueue.push(canvasRef);
|
|
365
|
+
return pixels;
|
|
366
|
+
}
|
|
367
|
+
}, {
|
|
368
|
+
key: "buildTileURL",
|
|
369
|
+
value: function buildTileURL(tileCoords) {
|
|
370
|
+
var _this$resource;
|
|
371
|
+
|
|
372
|
+
// reverseY for TMS tiling (https://gist.github.com/tmcw/4954720)
|
|
373
|
+
// See tiling schemes here: https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/
|
|
374
|
+
var z = tileCoords.z,
|
|
375
|
+
y = tileCoords.y;
|
|
376
|
+
return (_this$resource = this.resource) === null || _this$resource === void 0 ? void 0 : _this$resource.getDerivedResource({
|
|
377
|
+
templateValues: _objectSpread2(_objectSpread2({}, tileCoords), {}, {
|
|
378
|
+
reverseY: Math.pow(2, z) - y - 1
|
|
379
|
+
}),
|
|
380
|
+
preserveQueryParameters: true
|
|
381
|
+
}).getUrlComponent(true);
|
|
382
|
+
}
|
|
383
|
+
}, {
|
|
384
|
+
key: "getTileDataAvailable",
|
|
385
|
+
value: function getTileDataAvailable(_ref2) {
|
|
386
|
+
var z = _ref2.z;
|
|
387
|
+
if (z == this.maxZoom) return true;
|
|
388
|
+
if (z % 2 == 1 && this.skipOddLevels) return false;
|
|
389
|
+
if (z > this.maxZoom) return false;
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
}]);
|
|
393
|
+
|
|
394
|
+
return DefaultHeightmapResource;
|
|
395
|
+
}();
|
|
396
|
+
|
|
397
|
+
var ImageFormat;
|
|
398
|
+
|
|
399
|
+
(function (ImageFormat) {
|
|
400
|
+
ImageFormat["WEBP"] = "webp";
|
|
401
|
+
ImageFormat["PNG"] = "png";
|
|
402
|
+
ImageFormat["PNGRAW"] = "pngraw";
|
|
403
|
+
})(ImageFormat || (ImageFormat = {}));
|
|
404
|
+
|
|
405
|
+
var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
|
|
406
|
+
_inherits(MapboxTerrainResource, _DefaultHeightmapReso);
|
|
407
|
+
|
|
408
|
+
var _super = _createSuper(MapboxTerrainResource);
|
|
409
|
+
|
|
410
|
+
function MapboxTerrainResource() {
|
|
411
|
+
var _opts$highResolution, _opts$imageFormat;
|
|
412
|
+
|
|
413
|
+
var _this;
|
|
414
|
+
|
|
415
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
416
|
+
|
|
417
|
+
_classCallCheck(this, MapboxTerrainResource);
|
|
418
|
+
|
|
419
|
+
_this = _super.call(this, opts);
|
|
420
|
+
|
|
421
|
+
_defineProperty(_assertThisInitialized(_this), "resource", null);
|
|
422
|
+
|
|
423
|
+
var highResolution = (_opts$highResolution = opts.highResolution) !== null && _opts$highResolution !== void 0 ? _opts$highResolution : false;
|
|
424
|
+
var format = (_opts$imageFormat = opts.imageFormat) !== null && _opts$imageFormat !== void 0 ? _opts$imageFormat : ImageFormat.WEBP; // overrides based on highResolution flag
|
|
425
|
+
|
|
426
|
+
if (highResolution) {
|
|
427
|
+
if (opts.maxZoom === undefined) {
|
|
428
|
+
_this.maxZoom = 14;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (opts.tileSize === undefined) {
|
|
432
|
+
_this.tileSize = 512;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
_this.resource = cesium.Resource.createIfNeeded("https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format));
|
|
437
|
+
|
|
438
|
+
if (opts.accessToken) {
|
|
439
|
+
_this.resource.setQueryParameters({
|
|
440
|
+
access_token: opts.accessToken
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return _this;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return MapboxTerrainResource;
|
|
448
|
+
}(DefaultHeightmapResource);
|
|
449
|
+
|
|
111
450
|
function decodeBase64(base64, enableUnicode) {
|
|
112
451
|
var binaryString = atob(base64);
|
|
113
452
|
if (enableUnicode) {
|
|
@@ -138,7 +477,7 @@ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
|
|
|
138
477
|
};
|
|
139
478
|
}
|
|
140
479
|
|
|
141
|
-
var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQoKICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkoYXJyKTsKICB9CgogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikgewogICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICJ1bmRlZmluZWQiICYmIGl0ZXJbU3ltYm9sLml0ZXJhdG9yXSAhPSBudWxsIHx8IGl0ZXJbIkBAaXRlcmF0b3IiXSAhPSBudWxsKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTsKICB9CgogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsKICAgIGlmICghbykgcmV0dXJuOwogICAgaWYgKHR5cGVvZiBvID09PSAic3RyaW5nIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7CiAgICB2YXIgbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKS5zbGljZSg4LCAtMSk7CiAgICBpZiAobiA9PT0gIk9iamVjdCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsKICAgIGlmIChuID09PSAiTWFwIiB8fCBuID09PSAiU2V0IikgcmV0dXJuIEFycmF5LmZyb20obyk7CiAgICBpZiAobiA9PT0gIkFyZ3VtZW50cyIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOwogIH0KCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHsKICAgIGlmIChsZW4gPT0gbnVsbCB8fCBsZW4gPiBhcnIubGVuZ3RoKSBsZW4gPSBhcnIubGVuZ3RoOwoKICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTsKCiAgICByZXR1cm4gYXJyMjsKICB9CgogIGZ1bmN0aW9uIF9ub25JdGVyYWJsZVNwcmVhZCgpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlLlxuSW4gb3JkZXIgdG8gYmUgaXRlcmFibGUsIG5vbi1hcnJheSBvYmplY3RzIG11c3QgaGF2ZSBhIFtTeW1ib2wuaXRlcmF0b3JdKCkgbWV0aG9kLiIpOwogIH0KCiAgLy8gV2Ugc2hvdWxkIHNhdmUgdGhlc2UKICAvL2NvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoMjU2LCAyNTYpOwogIC8vY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgZnVuY3Rpb24gbWFwYm94VGVycmFpblRvR3JpZChwbmcpIHsKICAgIC8vIG1heWJlIHdlIHNob3VsZCBkbyB0aGlzIG9uIHRoZSBHUFUgdXNpbmcgUkVHTD8KICAgIC8vIGJ1dCB0aGF0IHdvdWxkIHJlcXVpcmUgR1BVIC0+IENQVSAtPiBHUFUKICAgIHZhciBncmlkU2l6ZSA9IHBuZy5zaGFwZVswXSArIDE7CiAgICB2YXIgdGVycmFpbiA9IG5ldyBGbG9hdDMyQXJyYXkoZ3JpZFNpemUgKiBncmlkU2l6ZSk7CiAgICB2YXIgdGlsZVNpemUgPSBwbmcuc2hhcGVbMF07IC8vIGRlY29kZSB0ZXJyYWluIHZhbHVlcwoKICAgIGZvciAodmFyIHkgPSAwOyB5IDwgdGlsZVNpemU7IHkrKykgewogICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHRpbGVTaXplOyB4KyspIHsKICAgICAgICB2YXIgeWMgPSB5OwogICAgICAgIHZhciByID0gcG5nLmdldCh4LCB5YywgMCk7CiAgICAgICAgdmFyIGcgPSBwbmcuZ2V0KHgsIHljLCAxKTsKICAgICAgICB2YXIgYiA9IHBuZy5nZXQoeCwgeWMsIDIpOwogICAgICAgIHRlcnJhaW5beSAqIGdyaWRTaXplICsgeF0gPSByICogMjU2ICogMjU2IC8gMTAuMCArIGcgKiAyNTYuMCAvIDEwLjAgKyBiIC8gMTAuMCAtIDEwMDAwLjA7CiAgICAgIH0KICAgIH0gLy8gYmFja2ZpbGwgcmlnaHQgYW5kIGJvdHRvbSBib3JkZXJzCgoKICAgIGZvciAodmFyIF94ID0gMDsgX3ggPCBncmlkU2l6ZSAtIDE7IF94KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDEpICsgX3hdID0gdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDIpICsgX3hdOwogICAgfQoKICAgIGZvciAodmFyIF95ID0gMDsgX3kgPCBncmlkU2l6ZTsgX3krKykgewogICAgICB0ZXJyYWluW2dyaWRTaXplICogX3kgKyBncmlkU2l6ZSAtIDFdID0gdGVycmFpbltncmlkU2l6ZSAqIF95ICsgZ3JpZFNpemUgLSAyXTsKICAgIH0KCiAgICByZXR1cm4gdGVycmFpbjsKICB9CgogIGZ1bmN0aW9uIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplKSB7CiAgICB2YXIgeHZhbHMgPSBbXTsKICAgIHZhciB5dmFscyA9IFtdOwogICAgdmFyIGhlaWdodE1ldGVycyA9IFtdOwogICAgdmFyIG5vcnRoSW5kaWNlcyA9IFtdOwogICAgdmFyIHNvdXRoSW5kaWNlcyA9IFtdOwogICAgdmFyIGVhc3RJbmRpY2VzID0gW107CiAgICB2YXIgd2VzdEluZGljZXMgPSBbXTsKICAgIHZhciBtaW5pbXVtSGVpZ2h0ID0gSW5maW5pdHk7CiAgICB2YXIgbWF4aW11bUhlaWdodCA9IC1JbmZpbml0eTsKICAgIHZhciBzY2FsYXIgPSAzMjc2OC4wIC8gdGlsZVNpemU7CgogICAgZm9yICh2YXIgaXggPSAwOyBpeCA8IG1lc2gudmVydGljZXMubGVuZ3RoIC8gMjsgaXgrKykgewogICAgICB2YXIgdmVydGV4SXggPSBpeDsKICAgICAgdmFyIHB4ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDJdOwogICAgICB2YXIgcHkgPSBtZXNoLnZlcnRpY2VzW2l4ICogMiArIDFdOwogICAgICB2YXIgaGVpZ2h0ID0gdGlsZS50ZXJyYWluW3B5ICogKHRpbGVTaXplICsgMSkgKyBweF07CiAgICAgIGlmIChoZWlnaHQgPiBtYXhpbXVtSGVpZ2h0KSBtYXhpbXVtSGVpZ2h0ID0gaGVpZ2h0OwogICAgICBpZiAoaGVpZ2h0IDwgbWluaW11bUhlaWdodCkgbWluaW11bUhlaWdodCA9IGhlaWdodDsKICAgICAgaGVpZ2h0TWV0ZXJzLnB1c2goaGVpZ2h0KTsKICAgICAgaWYgKHB5ID09IDApIG5vcnRoSW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB5ID09IHRpbGVTaXplKSBzb3V0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSAwKSB3ZXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB4ID09IHRpbGVTaXplKSBlYXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgdmFyIHh2ID0gcHggKiBzY2FsYXI7CiAgICAgIHZhciB5diA9ICh0aWxlU2l6ZSAtIHB5KSAqIHNjYWxhcjsKICAgICAgeHZhbHMucHVzaCh4dik7CiAgICAgIHl2YWxzLnB1c2goeXYpOwogICAgfQoKICAgIHZhciBoZWlnaHRSYW5nZSA9IG1heGltdW1IZWlnaHQgLSBtaW5pbXVtSGVpZ2h0OwogICAgdmFyIGhlaWdodHMgPSBoZWlnaHRNZXRlcnMubWFwKGZ1bmN0aW9uIChkKSB7CiAgICAgIGlmIChoZWlnaHRSYW5nZSA8IDEpIHJldHVybiAwOwogICAgICByZXR1cm4gKGQgLSBtaW5pbXVtSGVpZ2h0KSAqICgzMjc2Ny4wIC8gaGVpZ2h0UmFuZ2UpOwogICAgfSk7CiAgICB2YXIgdHJpYW5nbGVzID0gbmV3IFVpbnQxNkFycmF5KG1lc2gudHJpYW5nbGVzKTsKICAgIHZhciBxdWFudGl6ZWRWZXJ0aWNlcyA9IG5ldyBVaW50MTZBcnJheSggLy92ZXJ0cwogICAgW10uY29uY2F0KHh2YWxzLCB5dmFscywgX3RvQ29uc3VtYWJsZUFycmF5KGhlaWdodHMpKSk7IC8vIFNFIE5XIE5FCiAgICAvLyBORSBOVyBTRQoKICAgIHJldHVybiB7CiAgICAgIG1pbmltdW1IZWlnaHQ6IG1pbmltdW1IZWlnaHQsCiAgICAgIG1heGltdW1IZWlnaHQ6IG1heGltdW1IZWlnaHQsCiAgICAgIHF1YW50aXplZFZlcnRpY2VzOiBxdWFudGl6ZWRWZXJ0aWNlcywKICAgICAgaW5kaWNlczogdHJpYW5nbGVzLAogICAgICB3ZXN0SW5kaWNlczogd2VzdEluZGljZXMsCiAgICAgIHNvdXRoSW5kaWNlczogc291dGhJbmRpY2VzLAogICAgICBlYXN0SW5kaWNlczogZWFzdEluZGljZXMsCiAgICAgIG5vcnRoSW5kaWNlczogbm9ydGhJbmRpY2VzCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gaW90YShuKSB7CiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG4pOwogICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7CiAgICAgIHJlc3VsdFtpXSA9IGk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0CiAgfQoKICB2YXIgaW90YV8xID0gaW90YTsKCiAgLyohCiAgICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlcgogICAqCiAgICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz4KICAgKiBAbGljZW5zZSAgTUlUCiAgICovCiAgLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZwogIC8vIE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkKICB2YXIgaXNCdWZmZXJfMSA9IGZ1bmN0aW9uIChvYmopIHsKICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpCiAgfTsKCiAgZnVuY3Rpb24gaXNCdWZmZXIgKG9iaikgewogICAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iaikKICB9CgogIC8vIEZvciBOb2RlIHYwLjEwIHN1cHBvcnQuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkuCiAgZnVuY3Rpb24gaXNTbG93QnVmZmVyIChvYmopIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKQogIH0KCiAgdmFyIGhhc1R5cGVkQXJyYXlzICA9ICgodHlwZW9mIEZsb2F0NjRBcnJheSkgIT09ICJ1bmRlZmluZWQiKTsKCiAgZnVuY3Rpb24gY29tcGFyZTFzdChhLCBiKSB7CiAgICByZXR1cm4gYVswXSAtIGJbMF0KICB9CgogIGZ1bmN0aW9uIG9yZGVyKCkgewogICAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlOwogICAgdmFyIHRlcm1zID0gbmV3IEFycmF5KHN0cmlkZS5sZW5ndGgpOwogICAgdmFyIGk7CiAgICBmb3IoaT0wOyBpPHRlcm1zLmxlbmd0aDsgKytpKSB7CiAgICAgIHRlcm1zW2ldID0gW01hdGguYWJzKHN0cmlkZVtpXSksIGldOwogICAgfQogICAgdGVybXMuc29ydChjb21wYXJlMXN0KTsKICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodGVybXMubGVuZ3RoKTsKICAgIGZvcihpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgKytpKSB7CiAgICAgIHJlc3VsdFtpXSA9IHRlcm1zW2ldWzFdOwogICAgfQogICAgcmV0dXJuIHJlc3VsdAogIH0KCiAgZnVuY3Rpb24gY29tcGlsZUNvbnN0cnVjdG9yKGR0eXBlLCBkaW1lbnNpb24pIHsKICAgIHZhciBjbGFzc05hbWUgPSBbIlZpZXciLCBkaW1lbnNpb24sICJkIiwgZHR5cGVdLmpvaW4oIiIpOwogICAgaWYoZGltZW5zaW9uIDwgMCkgewogICAgICBjbGFzc05hbWUgPSAiVmlld19OaWwiICsgZHR5cGU7CiAgICB9CiAgICB2YXIgdXNlR2V0dGVycyA9IChkdHlwZSA9PT0gImdlbmVyaWMiKTsKCiAgICBpZihkaW1lbnNpb24gPT09IC0xKSB7CiAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciB0cml2aWFsIGFycmF5cwogICAgICB2YXIgY29kZSA9CiAgICAgICAgImZ1bmN0aW9uICIrY2xhc3NOYW1lKyIoYSl7dGhpcy5kYXRhPWE7fTtcCnZhciBwcm90bz0iK2NsYXNzTmFtZSsiLnByb3RvdHlwZTtcCnByb3RvLmR0eXBlPSciK2R0eXBlKyInO1wKcHJvdG8uaW5kZXg9ZnVuY3Rpb24oKXtyZXR1cm4gLTF9O1wKcHJvdG8uc2l6ZT0wO1wKcHJvdG8uZGltZW5zaW9uPS0xO1wKcHJvdG8uc2hhcGU9cHJvdG8uc3RyaWRlPXByb3RvLm9yZGVyPVtdO1wKcHJvdG8ubG89cHJvdG8uaGk9cHJvdG8udHJhbnNwb3NlPXByb3RvLnN0ZXA9XApmdW5jdGlvbigpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEpO307XApwcm90by5nZXQ9cHJvdG8uc2V0PWZ1bmN0aW9uKCl7fTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07XApyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIrY2xhc3NOYW1lKyIoYSl7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKGEpO30iOwogICAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKGNvZGUpOwogICAgICByZXR1cm4gcHJvY2VkdXJlKCkKICAgIH0gZWxzZSBpZihkaW1lbnNpb24gPT09IDApIHsKICAgICAgLy9TcGVjaWFsIGNhc2UgZm9yIDBkIGFycmF5cwogICAgICB2YXIgY29kZSA9CiAgICAgICAgImZ1bmN0aW9uICIrY2xhc3NOYW1lKyIoYSxkKSB7XAp0aGlzLmRhdGEgPSBhO1wKdGhpcy5vZmZzZXQgPSBkXAp9O1wKdmFyIHByb3RvPSIrY2xhc3NOYW1lKyIucHJvdG90eXBlO1wKcHJvdG8uZHR5cGU9JyIrZHR5cGUrIic7XApwcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm9mZnNldH07XApwcm90by5kaW1lbnNpb249MDtcCnByb3RvLnNpemU9MTtcCnByb3RvLnNoYXBlPVwKcHJvdG8uc3RyaWRlPVwKcHJvdG8ub3JkZXI9W107XApwcm90by5sbz1cCnByb3RvLmhpPVwKcHJvdG8udHJhbnNwb3NlPVwKcHJvdG8uc3RlcD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2NvcHkoKSB7XApyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLHRoaXMub2Zmc2V0KVwKfTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9waWNrKCl7XApyZXR1cm4gVHJpdmlhbEFycmF5KHRoaXMuZGF0YSk7XAp9O1wKcHJvdG8udmFsdWVPZj1wcm90by5nZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9nZXQoKXtcCnJldHVybiAiKyh1c2VHZXR0ZXJzID8gInRoaXMuZGF0YS5nZXQodGhpcy5vZmZzZXQpIiA6ICJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdIikrCiAgIn07XApwcm90by5zZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9zZXQodil7XApyZXR1cm4gIisodXNlR2V0dGVycyA/ICJ0aGlzLmRhdGEuc2V0KHRoaXMub2Zmc2V0LHYpIiA6ICJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdPXYiKSsiXAp9O1wKcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF8iK2NsYXNzTmFtZSsiKGEsYixjLGQpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIihhLGQpfSI7CiAgICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oIlRyaXZpYWxBcnJheSIsIGNvZGUpOwogICAgICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdWzBdKQogICAgfQoKICAgIHZhciBjb2RlID0gWyIndXNlIHN0cmljdCciXTsKCiAgICAvL0NyZWF0ZSBjb25zdHJ1Y3RvciBmb3IgdmlldwogICAgdmFyIGluZGljZXMgPSBpb3RhXzEoZGltZW5zaW9uKTsKICAgIHZhciBhcmdzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gImkiK2kgfSk7CiAgICB2YXIgaW5kZXhfc3RyID0gInRoaXMub2Zmc2V0KyIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgICByZXR1cm4gInRoaXMuc3RyaWRlWyIgKyBpICsgIl0qaSIgKyBpCiAgICAgICAgfSkuam9pbigiKyIpOwogICAgdmFyIHNoYXBlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYiIraQogICAgICB9KS5qb2luKCIsIik7CiAgICB2YXIgc3RyaWRlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYyIraQogICAgICB9KS5qb2luKCIsIik7CiAgICBjb2RlLnB1c2goCiAgICAgICJmdW5jdGlvbiAiK2NsYXNzTmFtZSsiKGEsIiArIHNoYXBlQXJnICsgIiwiICsgc3RyaWRlQXJnICsgIixkKXt0aGlzLmRhdGE9YSIsCiAgICAgICAgInRoaXMuc2hhcGU9WyIgKyBzaGFwZUFyZyArICJdIiwKICAgICAgICAidGhpcy5zdHJpZGU9WyIgKyBzdHJpZGVBcmcgKyAiXSIsCiAgICAgICAgInRoaXMub2Zmc2V0PWR8MH0iLAogICAgICAidmFyIHByb3RvPSIrY2xhc3NOYW1lKyIucHJvdG90eXBlIiwKICAgICAgInByb3RvLmR0eXBlPSciK2R0eXBlKyInIiwKICAgICAgInByb3RvLmRpbWVuc2lvbj0iK2RpbWVuc2lvbik7CgogICAgLy92aWV3LnNpemU6CiAgICBjb2RlLnB1c2goIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnc2l6ZScse2dldDpmdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3NpemUoKXtcCnJldHVybiAiK2luZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuICJ0aGlzLnNoYXBlWyIraSsiXSIgfSkuam9pbigiKiIpLAogICJ9fSkiKTsKCiAgICAvL3ZpZXcub3JkZXI6CiAgICBpZihkaW1lbnNpb24gPT09IDEpIHsKICAgICAgY29kZS5wdXNoKCJwcm90by5vcmRlcj1bMF0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdvcmRlcicse2dldDoiKTsKICAgICAgaWYoZGltZW5zaW9uIDwgNCkgewogICAgICAgIGNvZGUucHVzaCgiZnVuY3Rpb24gIitjbGFzc05hbWUrIl9vcmRlcigpeyIpOwogICAgICAgIGlmKGRpbWVuc2lvbiA9PT0gMikgewogICAgICAgICAgY29kZS5wdXNoKCJyZXR1cm4gKE1hdGguYWJzKHRoaXMuc3RyaWRlWzBdKT5NYXRoLmFicyh0aGlzLnN0cmlkZVsxXSkpP1sxLDBdOlswLDFdfX0pIik7CiAgICAgICAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMykgewogICAgICAgICAgY29kZS5wdXNoKAogICJ2YXIgczA9TWF0aC5hYnModGhpcy5zdHJpZGVbMF0pLHMxPU1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSxzMj1NYXRoLmFicyh0aGlzLnN0cmlkZVsyXSk7XAppZihzMD5zMSl7XAppZihzMT5zMil7XApyZXR1cm4gWzIsMSwwXTtcCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMSwyLDBdO1wKfWVsc2V7XApyZXR1cm4gWzEsMCwyXTtcCn1cCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMiwwLDFdO1wKfWVsc2UgaWYoczI+czEpe1wKcmV0dXJuIFswLDEsMl07XAp9ZWxzZXtcCnJldHVybiBbMCwyLDFdO1wKfX19KSIpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb2RlLnB1c2goIk9SREVSfSkiKTsKICAgICAgfQogICAgfQoKICAgIC8vdmlldy5zZXQoaTAsIC4uLiwgdik6CiAgICBjb2RlLnB1c2goCiAgInByb3RvLnNldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3NldCgiK2FyZ3Muam9pbigiLCIpKyIsdil7Iik7CiAgICBpZih1c2VHZXR0ZXJzKSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YS5zZXQoIitpbmRleF9zdHIrIix2KX0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YVsiK2luZGV4X3N0cisiXT12fSIpOwogICAgfQoKICAgIC8vdmlldy5nZXQoaTAsIC4uLik6CiAgICBjb2RlLnB1c2goInByb3RvLmdldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2dldCgiK2FyZ3Muam9pbigiLCIpKyIpeyIpOwogICAgaWYodXNlR2V0dGVycykgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGEuZ2V0KCIraW5kZXhfc3RyKyIpfSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhWyIraW5kZXhfc3RyKyJdfSIpOwogICAgfQoKICAgIC8vdmlldy5pbmRleDoKICAgIGNvZGUucHVzaCgKICAgICAgInByb3RvLmluZGV4PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfaW5kZXgoIiwgYXJncy5qb2luKCksICIpe3JldHVybiAiK2luZGV4X3N0cisifSIpOwoKICAgIC8vdmlldy5oaSgpOgogICAgY29kZS5wdXNoKCJwcm90by5oaT1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2hpKCIrYXJncy5qb2luKCIsIikrIil7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuIFsiKHR5cGVvZiBpIixpLCIhPT0nbnVtYmVyJ3x8aSIsaSwiPDApP3RoaXMuc2hhcGVbIiwgaSwgIl06aSIsIGksInwwIl0uam9pbigiIikKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAidGhpcy5zdHJpZGVbIitpICsgIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLHRoaXMub2Zmc2V0KX0iKTsKCiAgICAvL3ZpZXcubG8oKToKICAgIHZhciBhX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAiYSIraSsiPXRoaXMuc2hhcGVbIitpKyJdIiB9KTsKICAgIHZhciBjX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAiYyIraSsiPXRoaXMuc3RyaWRlWyIraSsiXSIgfSk7CiAgICBjb2RlLnB1c2goInByb3RvLmxvPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfbG8oIithcmdzLmpvaW4oIiwiKSsiKXt2YXIgYj10aGlzLm9mZnNldCxkPTAsIithX3ZhcnMuam9pbigiLCIpKyIsIitjX3ZhcnMuam9pbigiLCIpKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgKICAiaWYodHlwZW9mIGkiK2krIj09PSdudW1iZXInJiZpIitpKyI+PTApe1wKZD1pIitpKyJ8MDtcCmIrPWMiK2krIipkO1wKYSIraSsiLT1kfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImEiK2kKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYyIraQogICAgICB9KS5qb2luKCIsIikrIixiKX0iKTsKCiAgICAvL3ZpZXcuc3RlcCgpOgogICAgY29kZS5wdXNoKCJwcm90by5zdGVwPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfc3RlcCgiK2FyZ3Muam9pbigiLCIpKyIpe3ZhciAiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJhIitpKyI9dGhpcy5zaGFwZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImIiK2krIj10aGlzLnN0cmlkZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLGM9dGhpcy5vZmZzZXQsZD0wLGNlaWw9TWF0aC5jZWlsIik7CiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goCiAgImlmKHR5cGVvZiBpIitpKyI9PT0nbnVtYmVyJyl7XApkPWkiK2krInwwO1wKaWYoZDwwKXtcCmMrPWIiK2krIiooYSIraSsiLTEpO1wKYSIraSsiPWNlaWwoLWEiK2krIi9kKVwKfWVsc2V7XAphIitpKyI9Y2VpbChhIitpKyIvZClcCn1cCmIiK2krIio9ZFwKfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImEiICsgaQogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJiIiArIGkKICAgICAgfSkuam9pbigiLCIpKyIsYyl9Iik7CgogICAgLy92aWV3LnRyYW5zcG9zZSgpOgogICAgdmFyIHRTaGFwZSA9IG5ldyBBcnJheShkaW1lbnNpb24pOwogICAgdmFyIHRTdHJpZGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIHRTaGFwZVtpXSA9ICJhW2kiK2krIl0iOwogICAgICB0U3RyaWRlW2ldID0gImJbaSIraSsiXSI7CiAgICB9CiAgICBjb2RlLnB1c2goInByb3RvLnRyYW5zcG9zZT1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3RyYW5zcG9zZSgiK2FyZ3MrIil7IisKICAgICAgYXJncy5tYXAoZnVuY3Rpb24obixpZHgpIHsgcmV0dXJuIG4gKyAiPSgiICsgbiArICI9PT11bmRlZmluZWQ/IiArIGlkeCArICI6IiArIG4gKyAifDApIn0pLmpvaW4oIjsiKSwKICAgICAgInZhciBhPXRoaXMuc2hhcGUsYj10aGlzLnN0cmlkZTtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrdFNoYXBlLmpvaW4oIiwiKSsiLCIrdFN0cmlkZS5qb2luKCIsIikrIix0aGlzLm9mZnNldCl9Iik7CgogICAgLy92aWV3LnBpY2soKToKICAgIGNvZGUucHVzaCgicHJvdG8ucGljaz1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3BpY2soIithcmdzKyIpe3ZhciBhPVtdLGI9W10sYz10aGlzLm9mZnNldCIpOwogICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKCJpZih0eXBlb2YgaSIraSsiPT09J251bWJlcicmJmkiK2krIj49MCl7Yz0oYyt0aGlzLnN0cmlkZVsiK2krIl0qaSIraSsiKXwwfWVsc2V7YS5wdXNoKHRoaXMuc2hhcGVbIitpKyJdKTtiLnB1c2godGhpcy5zdHJpZGVbIitpKyJdKX0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgidmFyIGN0b3I9Q1RPUl9MSVNUW2EubGVuZ3RoKzFdO3JldHVybiBjdG9yKHRoaXMuZGF0YSxhLGIsYyl9Iik7CgogICAgLy9BZGQgcmV0dXJuIHN0YXRlbWVudAogICAgY29kZS5wdXNoKCJyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIrY2xhc3NOYW1lKyIoZGF0YSxzaGFwZSxzdHJpZGUsb2Zmc2V0KXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIoZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJzaGFwZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gInN0cmlkZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLG9mZnNldCl9Iik7CgogICAgLy9Db21waWxlIHByb2NlZHVyZQogICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbigiQ1RPUl9MSVNUIiwgIk9SREVSIiwgY29kZS5qb2luKCJcbiIpKTsKICAgIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV0sIG9yZGVyKQogIH0KCiAgZnVuY3Rpb24gYXJyYXlEVHlwZShkYXRhKSB7CiAgICBpZihpc0J1ZmZlcl8xKGRhdGEpKSB7CiAgICAgIHJldHVybiAiYnVmZmVyIgogICAgfQogICAgaWYoaGFzVHlwZWRBcnJheXMpIHsKICAgICAgc3dpdGNoKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSkgewogICAgICAgIGNhc2UgIltvYmplY3QgRmxvYXQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImZsb2F0NjQiCiAgICAgICAgY2FzZSAiW29iamVjdCBGbG9hdDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAiZmxvYXQzMiIKICAgICAgICBjYXNlICJbb2JqZWN0IEludDhBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQ4IgogICAgICAgIGNhc2UgIltvYmplY3QgSW50MTZBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQxNiIKICAgICAgICBjYXNlICJbb2JqZWN0IEludDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAiaW50MzIiCiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50OEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQ4IgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDE2QXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDE2IgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDMyIgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDhDbGFtcGVkQXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDhfY2xhbXBlZCIKICAgICAgICBjYXNlICJbb2JqZWN0IEJpZ0ludDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiYmlnaW50NjQiCiAgICAgICAgY2FzZSAiW29iamVjdCBCaWdVaW50NjRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJiaWd1aW50NjQiCiAgICAgIH0KICAgIH0KICAgIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHsKICAgICAgcmV0dXJuICJhcnJheSIKICAgIH0KICAgIHJldHVybiAiZ2VuZXJpYyIKICB9CgogIHZhciBDQUNIRURfQ09OU1RSVUNUT1JTID0gewogICAgImZsb2F0MzIiOltdLAogICAgImZsb2F0NjQiOltdLAogICAgImludDgiOltdLAogICAgImludDE2IjpbXSwKICAgICJpbnQzMiI6W10sCiAgICAidWludDgiOltdLAogICAgInVpbnQxNiI6W10sCiAgICAidWludDMyIjpbXSwKICAgICJhcnJheSI6W10sCiAgICAidWludDhfY2xhbXBlZCI6W10sCiAgICAiYmlnaW50NjQiOiBbXSwKICAgICJiaWd1aW50NjQiOiBbXSwKICAgICJidWZmZXIiOltdLAogICAgImdlbmVyaWMiOltdCiAgfQoKICA7CiAgZnVuY3Rpb24gd3JhcHBlZE5EQXJyYXlDdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkgewogICAgaWYoZGF0YSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhciBjdG9yID0gQ0FDSEVEX0NPTlNUUlVDVE9SUy5hcnJheVswXTsKICAgICAgcmV0dXJuIGN0b3IoW10pCiAgICB9IGVsc2UgaWYodHlwZW9mIGRhdGEgPT09ICJudW1iZXIiKSB7CiAgICAgIGRhdGEgPSBbZGF0YV07CiAgICB9CiAgICBpZihzaGFwZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHNoYXBlID0gWyBkYXRhLmxlbmd0aCBdOwogICAgfQogICAgdmFyIGQgPSBzaGFwZS5sZW5ndGg7CiAgICBpZihzdHJpZGUgPT09IHVuZGVmaW5lZCkgewogICAgICBzdHJpZGUgPSBuZXcgQXJyYXkoZCk7CiAgICAgIGZvcih2YXIgaT1kLTEsIHN6PTE7IGk+PTA7IC0taSkgewogICAgICAgIHN0cmlkZVtpXSA9IHN6OwogICAgICAgIHN6ICo9IHNoYXBlW2ldOwogICAgICB9CiAgICB9CiAgICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkgewogICAgICBvZmZzZXQgPSAwOwogICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHsKICAgICAgICBpZihzdHJpZGVbaV0gPCAwKSB7CiAgICAgICAgICBvZmZzZXQgLT0gKHNoYXBlW2ldLTEpKnN0cmlkZVtpXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZhciBkdHlwZSA9IGFycmF5RFR5cGUoZGF0YSk7CiAgICB2YXIgY3Rvcl9saXN0ID0gQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV07CiAgICB3aGlsZShjdG9yX2xpc3QubGVuZ3RoIDw9IGQrMSkgewogICAgICBjdG9yX2xpc3QucHVzaChjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGN0b3JfbGlzdC5sZW5ndGgtMSkpOwogICAgfQogICAgdmFyIGN0b3IgPSBjdG9yX2xpc3RbZCsxXTsKICAgIHJldHVybiBjdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkKICB9CgogIHZhciBuZGFycmF5ID0gd3JhcHBlZE5EQXJyYXlDdG9yOwoKICBjbGFzcyBNYXJ0aW5pIHsKICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgIGlmICh0aWxlU2l6ZSAmIHRpbGVTaXplIC0gMSkgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBncmlkIHNpemUgdG8gYmUgMl5uKzEsIGdvdCAke2dyaWRTaXplfS5gKTsKICAgICAgdGhpcy5udW1UcmlhbmdsZXMgPSB0aWxlU2l6ZSAqIHRpbGVTaXplICogMiAtIDI7CiAgICAgIHRoaXMubnVtUGFyZW50VHJpYW5nbGVzID0gdGhpcy5udW1UcmlhbmdsZXMgLSB0aWxlU2l6ZSAqIHRpbGVTaXplOwogICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOyAvLyBjb29yZGluYXRlcyBmb3IgYWxsIHBvc3NpYmxlIHRyaWFuZ2xlcyBpbiBhbiBSVElOIHRpbGUKCiAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7IC8vIGdldCB0cmlhbmdsZSBjb29yZGluYXRlcyBmcm9tIGl0cyBpbmRleCBpbiBhbiBpbXBsaWNpdCBiaW5hcnkgdHJlZQoKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgbGV0IGlkID0gaSArIDI7CiAgICAgICAgbGV0IGF4ID0gMCwKICAgICAgICAgICAgYXkgPSAwLAogICAgICAgICAgICBieCA9IDAsCiAgICAgICAgICAgIGJ5ID0gMCwKICAgICAgICAgICAgY3ggPSAwLAogICAgICAgICAgICBjeSA9IDA7CgogICAgICAgIGlmIChpZCAmIDEpIHsKICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgfQoKICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CgogICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAvLyBsZWZ0IGhhbGYKICAgICAgICAgICAgYnggPSBheDsKICAgICAgICAgICAgYnkgPSBheTsKICAgICAgICAgICAgYXggPSBjeDsKICAgICAgICAgICAgYXkgPSBjeTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIHJpZ2h0IGhhbGYKICAgICAgICAgICAgYXggPSBieDsKICAgICAgICAgICAgYXkgPSBieTsKICAgICAgICAgICAgYnggPSBjeDsKICAgICAgICAgICAgYnkgPSBjeTsKICAgICAgICAgIH0KCiAgICAgICAgICBjeCA9IG14OwogICAgICAgICAgY3kgPSBteTsKICAgICAgICB9CgogICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMF0gPSBheDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMl0gPSBieDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgM10gPSBieTsKICAgICAgfQogICAgfQoKICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICB9CgogIH0KCiAgY2xhc3MgVGlsZSB7CiAgICBjb25zdHJ1Y3Rvcih0ZXJyYWluLCBtYXJ0aW5pKSB7CiAgICAgIGNvbnN0IHNpemUgPSBtYXJ0aW5pLmdyaWRTaXplOwogICAgICBpZiAodGVycmFpbi5sZW5ndGggIT09IHNpemUgKiBzaXplKSB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHRlcnJhaW4gZGF0YSBvZiBsZW5ndGggJHtzaXplICogc2l6ZX0gKCR7c2l6ZX0geCAke3NpemV9KSwgZ290ICR7dGVycmFpbi5sZW5ndGh9LmApOwogICAgICB0aGlzLnRlcnJhaW4gPSB0ZXJyYWluOwogICAgICB0aGlzLm1hcnRpbmkgPSBtYXJ0aW5pOwogICAgICB0aGlzLmVycm9ycyA9IG5ldyBGbG9hdDMyQXJyYXkodGVycmFpbi5sZW5ndGgpOwogICAgICB0aGlzLnVwZGF0ZSgpOwogICAgfQoKICAgIHVwZGF0ZSgpIHsKICAgICAgY29uc3QgewogICAgICAgIG51bVRyaWFuZ2xlcywKICAgICAgICBudW1QYXJlbnRUcmlhbmdsZXMsCiAgICAgICAgY29vcmRzLAogICAgICAgIGdyaWRTaXplOiBzaXplCiAgICAgIH0gPSB0aGlzLm1hcnRpbmk7CiAgICAgIGNvbnN0IHsKICAgICAgICB0ZXJyYWluLAogICAgICAgIGVycm9ycwogICAgICB9ID0gdGhpczsgLy8gaXRlcmF0ZSBvdmVyIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMsIHN0YXJ0aW5nIGZyb20gdGhlIHNtYWxsZXN0IGxldmVsCgogICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICBjb25zdCBrID0gaSAqIDQ7CiAgICAgICAgY29uc3QgYXggPSBjb29yZHNbayArIDBdOwogICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICBjb25zdCBieCA9IGNvb3Jkc1trICsgMl07CiAgICAgICAgY29uc3QgYnkgPSBjb29yZHNbayArIDNdOwogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGN4ID0gbXggKyBteSAtIGF5OwogICAgICAgIGNvbnN0IGN5ID0gbXkgKyBheCAtIG14OyAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQoKICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWRIZWlnaHQgPSAodGVycmFpbltheSAqIHNpemUgKyBheF0gKyB0ZXJyYWluW2J5ICogc2l6ZSArIGJ4XSkgLyAyOwogICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgY29uc3QgbWlkZGxlRXJyb3IgPSBNYXRoLmFicyhpbnRlcnBvbGF0ZWRIZWlnaHQgLSB0ZXJyYWluW21pZGRsZUluZGV4XSk7CiAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIG1pZGRsZUVycm9yKTsKCiAgICAgICAgaWYgKGkgPCBudW1QYXJlbnRUcmlhbmdsZXMpIHsKICAgICAgICAgIC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgY29uc3QgbGVmdENoaWxkSW5kZXggPSAoYXkgKyBjeSA+PiAxKSAqIHNpemUgKyAoYXggKyBjeCA+PiAxKTsKICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9IChieSArIGN5ID4+IDEpICogc2l6ZSArIChieCArIGN4ID4+IDEpOwogICAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIGVycm9yc1tsZWZ0Q2hpbGRJbmRleF0sIGVycm9yc1tyaWdodENoaWxkSW5kZXhdKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICBnZXRNZXNoKG1heEVycm9yID0gMCwgbWF4TGVuZ3RoID0gbnVsbCkgewogICAgICBjb25zdCB7CiAgICAgICAgZ3JpZFNpemU6IHNpemUsCiAgICAgICAgaW5kaWNlcwogICAgICB9ID0gdGhpcy5tYXJ0aW5pOwogICAgICBjb25zdCB7CiAgICAgICAgZXJyb3JzCiAgICAgIH0gPSB0aGlzOwogICAgICBsZXQgbnVtVmVydGljZXMgPSAwOwogICAgICBsZXQgbnVtVHJpYW5nbGVzID0gMDsKICAgICAgY29uc3QgbWF4ID0gc2l6ZSAtIDE7IC8vIFRoZSBtYXhMZW5ndGggcGFyYW1ldGVyIHdpbGwgY2F1c2UgdHJpYW5nbGVzIHRvIGJlIGdlbmVyYXRlZCB1bnRpbCB0aGUgbGVncyBhcmUgYmVsb3cgdGhpcyBsZW5ndGgKICAgICAgLy8gSXQgaXMgbWVhbnQgdG8gc3VwcG9ydCBjYXNlcyB3aGVyZSBhIGNlcnRhaW4gbWVzaCBkZW5zaXR5IGlzIHJlcXVpcmVkIHRvIGRvIHNwaGVyaWNhbCBtYXRoIG9uIGRpZ2l0YWwgZ2xvYmVzCgogICAgICBjb25zdCBtYXhTY2FsZSA9IG1heExlbmd0aCB8fCBzaXplOyAvLyB1c2UgYW4gaW5kZXggZ3JpZCB0byBrZWVwIHRyYWNrIG9mIHZlcnRpY2VzIHRoYXQgd2VyZSBhbHJlYWR5IHVzZWQgdG8gYXZvaWQgZHVwbGljYXRpb24KCiAgICAgIGluZGljZXMuZmlsbCgwKTsgLy8gcmV0cmlldmUgbWVzaCBpbiB0d28gc3RhZ2VzIHRoYXQgYm90aCB0cmF2ZXJzZSB0aGUgZXJyb3IgbWFwOgogICAgICAvLyAtIGNvdW50RWxlbWVudHM6IGZpbmQgdXNlZCB2ZXJ0aWNlcyAoYW5kIGFzc2lnbiBlYWNoIGFuIGluZGV4KSwgYW5kIGNvdW50IHRyaWFuZ2xlcyAoZm9yIG1pbmltdW0gYWxsb2NhdGlvbikKICAgICAgLy8gLSBwcm9jZXNzVHJpYW5nbGU6IGZpbGwgdGhlIGFsbG9jYXRlZCB2ZXJ0aWNlcyAmIHRyaWFuZ2xlcyB0eXBlZCBhcnJheXMKCiAgICAgIGZ1bmN0aW9uIGNvdW50RWxlbWVudHMoYXgsIGF5LCBieCwgYnksIGN4LCBjeSkgewogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGxlZ0xlbmd0aCA9IE1hdGguYWJzKGF4IC0gY3gpICsgTWF0aC5hYnMoYXkgLSBjeSk7CgogICAgICAgIGlmIChsZWdMZW5ndGggPiAxICYmIGVycm9yc1tteSAqIHNpemUgKyBteF0gPiBtYXhFcnJvciB8fCBsZWdMZW5ndGggPiBtYXhTY2FsZSkgewogICAgICAgICAgY291bnRFbGVtZW50cyhjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgIGNvdW50RWxlbWVudHMoYngsIGJ5LCBjeCwgY3ksIG14LCBteSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGluZGljZXNbYXkgKiBzaXplICsgYXhdID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIGluZGljZXNbYnkgKiBzaXplICsgYnhdID0gaW5kaWNlc1tieSAqIHNpemUgKyBieF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIG51bVRyaWFuZ2xlcysrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgY291bnRFbGVtZW50cygwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgY291bnRFbGVtZW50cyhtYXgsIG1heCwgMCwgMCwgMCwgbWF4KTsKICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwoKICAgICAgICBpZiAobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IgfHwgbGVnTGVuZ3RoID4gbWF4U2NhbGUpIHsKICAgICAgICAgIC8vIHRyaWFuZ2xlIGRvZXNuJ3QgYXBwcm94aW1hdGUgdGhlIHN1cmZhY2Ugd2VsbCBlbm91Z2g7IGRyaWxsIGRvd24gZnVydGhlcgogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGN4LCBjeSwgYXgsIGF5LCBteCwgbXkpOwogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBhZGQgYSB0cmlhbmdsZQogICAgICAgICAgY29uc3QgYSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIC0gMTsKICAgICAgICAgIGNvbnN0IGIgPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSAtIDE7CiAgICAgICAgICBjb25zdCBjID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gLSAxOwogICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYSArIDFdID0gYXk7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBiICsgMV0gPSBieTsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBjXSA9IGN4OwogICAgICAgICAgdmVydGljZXNbMiAqIGMgKyAxXSA9IGN5OwogICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGI7CiAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBjOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmVydGljZXMsCiAgICAgICAgdHJpYW5nbGVzCiAgICAgIH07CiAgICB9CgogIH0KCiAgZnVuY3Rpb24gY3JlYXRlQ29tbW9uanNNb2R1bGUoZm4pIHsKICAgIHZhciBtb2R1bGUgPSB7IGV4cG9ydHM6IHt9IH07CiAgCXJldHVybiBmbihtb2R1bGUsIG1vZHVsZS5leHBvcnRzKSwgbW9kdWxlLmV4cG9ydHM7CiAgfQoKICAvKioKICAgKiBDb3B5cmlnaHQgKGMpIDIwMTQtcHJlc2VudCwgRmFjZWJvb2ssIEluYy4KICAgKgogICAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZQogICAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS4KICAgKi8KCiAgY3JlYXRlQ29tbW9uanNNb2R1bGUoZnVuY3Rpb24gKG1vZHVsZSkgewogIHZhciBydW50aW1lID0gKGZ1bmN0aW9uIChleHBvcnRzKSB7CgogICAgdmFyIE9wID0gT2JqZWN0LnByb3RvdHlwZTsKICAgIHZhciBoYXNPd24gPSBPcC5oYXNPd25Qcm9wZXJ0eTsKICAgIHZhciB1bmRlZmluZWQkMTsgLy8gTW9yZSBjb21wcmVzc2libGUgdGhhbiB2b2lkIDAuCiAgICB2YXIgJFN5bWJvbCA9IHR5cGVvZiBTeW1ib2wgPT09ICJmdW5jdGlvbiIgPyBTeW1ib2wgOiB7fTsKICAgIHZhciBpdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuaXRlcmF0b3IgfHwgIkBAaXRlcmF0b3IiOwogICAgdmFyIGFzeW5jSXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLmFzeW5jSXRlcmF0b3IgfHwgIkBAYXN5bmNJdGVyYXRvciI7CiAgICB2YXIgdG9TdHJpbmdUYWdTeW1ib2wgPSAkU3ltYm9sLnRvU3RyaW5nVGFnIHx8ICJAQHRvU3RyaW5nVGFnIjsKCiAgICBmdW5jdGlvbiBkZWZpbmUob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgewogICAgICAgIHZhbHVlOiB2YWx1ZSwKICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZQogICAgICB9KTsKICAgICAgcmV0dXJuIG9ialtrZXldOwogICAgfQogICAgdHJ5IHsKICAgICAgLy8gSUUgOCBoYXMgYSBicm9rZW4gT2JqZWN0LmRlZmluZVByb3BlcnR5IHRoYXQgb25seSB3b3JrcyBvbiBET00gb2JqZWN0cy4KICAgICAgZGVmaW5lKHt9LCAiIik7CiAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgZGVmaW5lID0gZnVuY3Rpb24ob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIG9ialtrZXldID0gdmFsdWU7CiAgICAgIH07CiAgICB9CgogICAgZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgewogICAgICAvLyBJZiBvdXRlckZuIHByb3ZpZGVkIGFuZCBvdXRlckZuLnByb3RvdHlwZSBpcyBhIEdlbmVyYXRvciwgdGhlbiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvci4KICAgICAgdmFyIHByb3RvR2VuZXJhdG9yID0gb3V0ZXJGbiAmJiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvciA/IG91dGVyRm4gOiBHZW5lcmF0b3I7CiAgICAgIHZhciBnZW5lcmF0b3IgPSBPYmplY3QuY3JlYXRlKHByb3RvR2VuZXJhdG9yLnByb3RvdHlwZSk7CiAgICAgIHZhciBjb250ZXh0ID0gbmV3IENvbnRleHQodHJ5TG9jc0xpc3QgfHwgW10pOwoKICAgICAgLy8gVGhlIC5faW52b2tlIG1ldGhvZCB1bmlmaWVzIHRoZSBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlIC5uZXh0LAogICAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMuCiAgICAgIGdlbmVyYXRvci5faW52b2tlID0gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKCiAgICAgIHJldHVybiBnZW5lcmF0b3I7CiAgICB9CiAgICBleHBvcnRzLndyYXAgPSB3cmFwOwoKICAgIC8vIFRyeS9jYXRjaCBoZWxwZXIgdG8gbWluaW1pemUgZGVvcHRpbWl6YXRpb25zLiBSZXR1cm5zIGEgY29tcGxldGlvbgogICAgLy8gcmVjb3JkIGxpa2UgY29udGV4dC50cnlFbnRyaWVzW2ldLmNvbXBsZXRpb24uIFRoaXMgaW50ZXJmYWNlIGNvdWxkCiAgICAvLyBoYXZlIGJlZW4gKGFuZCB3YXMgcHJldmlvdXNseSkgZGVzaWduZWQgdG8gdGFrZSBhIGNsb3N1cmUgdG8gYmUKICAgIC8vIGludm9rZWQgd2l0aG91dCBhcmd1bWVudHMsIGJ1dCBpbiBhbGwgdGhlIGNhc2VzIHdlIGNhcmUgYWJvdXQgd2UKICAgIC8vIGFscmVhZHkgaGF2ZSBhbiBleGlzdGluZyBtZXRob2Qgd2Ugd2FudCB0byBjYWxsLCBzbyB0aGVyZSdzIG5vIG5lZWQKICAgIC8vIHRvIGNyZWF0ZSBhIG5ldyBmdW5jdGlvbiBvYmplY3QuIFdlIGNhbiBldmVuIGdldCBhd2F5IHdpdGggYXNzdW1pbmcKICAgIC8vIHRoZSBtZXRob2QgdGFrZXMgZXhhY3RseSBvbmUgYXJndW1lbnQsIHNpbmNlIHRoYXQgaGFwcGVucyB0byBiZSB0cnVlCiAgICAvLyBpbiBldmVyeSBjYXNlLCBzbyB3ZSBkb24ndCBoYXZlIHRvIHRvdWNoIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBUaGUKICAgIC8vIG9ubHkgYWRkaXRpb25hbCBhbGxvY2F0aW9uIHJlcXVpcmVkIGlzIHRoZSBjb21wbGV0aW9uIHJlY29yZCwgd2hpY2gKICAgIC8vIGhhcyBhIHN0YWJsZSBzaGFwZSBhbmQgc28gaG9wZWZ1bGx5IHNob3VsZCBiZSBjaGVhcCB0byBhbGxvY2F0ZS4KICAgIGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgewogICAgICB0cnkgewogICAgICAgIHJldHVybiB7IHR5cGU6ICJub3JtYWwiLCBhcmc6IGZuLmNhbGwob2JqLCBhcmcpIH07CiAgICAgIH0gY2F0Y2ggKGVycikgewogICAgICAgIHJldHVybiB7IHR5cGU6ICJ0aHJvdyIsIGFyZzogZXJyIH07CiAgICAgIH0KICAgIH0KCiAgICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRTdGFydCA9ICJzdXNwZW5kZWRTdGFydCI7CiAgICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRZaWVsZCA9ICJzdXNwZW5kZWRZaWVsZCI7CiAgICB2YXIgR2VuU3RhdGVFeGVjdXRpbmcgPSAiZXhlY3V0aW5nIjsKICAgIHZhciBHZW5TdGF0ZUNvbXBsZXRlZCA9ICJjb21wbGV0ZWQiOwoKICAgIC8vIFJldHVybmluZyB0aGlzIG9iamVjdCBmcm9tIHRoZSBpbm5lckZuIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMKICAgIC8vIGJyZWFraW5nIG91dCBvZiB0aGUgZGlzcGF0Y2ggc3dpdGNoIHN0YXRlbWVudC4KICAgIHZhciBDb250aW51ZVNlbnRpbmVsID0ge307CgogICAgLy8gRHVtbXkgY29uc3RydWN0b3IgZnVuY3Rpb25zIHRoYXQgd2UgdXNlIGFzIHRoZSAuY29uc3RydWN0b3IgYW5kCiAgICAvLyAuY29uc3RydWN0b3IucHJvdG90eXBlIHByb3BlcnRpZXMgZm9yIGZ1bmN0aW9ucyB0aGF0IHJldHVybiBHZW5lcmF0b3IKICAgIC8vIG9iamVjdHMuIEZvciBmdWxsIHNwZWMgY29tcGxpYW5jZSwgeW91IG1heSB3aXNoIHRvIGNvbmZpZ3VyZSB5b3VyCiAgICAvLyBtaW5pZmllciBub3QgdG8gbWFuZ2xlIHRoZSBuYW1lcyBvZiB0aGVzZSB0d28gZnVuY3Rpb25zLgogICAgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30KICAgIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uKCkge30KICAgIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKCkge30KCiAgICAvLyBUaGlzIGlzIGEgcG9seWZpbGwgZm9yICVJdGVyYXRvclByb3RvdHlwZSUgZm9yIGVudmlyb25tZW50cyB0aGF0CiAgICAvLyBkb24ndCBuYXRpdmVseSBzdXBwb3J0IGl0LgogICAgdmFyIEl0ZXJhdG9yUHJvdG90eXBlID0ge307CiAgICBJdGVyYXRvclByb3RvdHlwZVtpdGVyYXRvclN5bWJvbF0gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICB2YXIgZ2V0UHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7CiAgICB2YXIgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90byAmJiBnZXRQcm90byhnZXRQcm90byh2YWx1ZXMoW10pKSk7CiAgICBpZiAoTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgJiYKICAgICAgICBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAhPT0gT3AgJiYKICAgICAgICBoYXNPd24uY2FsbChOYXRpdmVJdGVyYXRvclByb3RvdHlwZSwgaXRlcmF0b3JTeW1ib2wpKSB7CiAgICAgIC8vIFRoaXMgZW52aXJvbm1lbnQgaGFzIGEgbmF0aXZlICVJdGVyYXRvclByb3RvdHlwZSU7IHVzZSBpdCBpbnN0ZWFkCiAgICAgIC8vIG9mIHRoZSBwb2x5ZmlsbC4KICAgICAgSXRlcmF0b3JQcm90b3R5cGUgPSBOYXRpdmVJdGVyYXRvclByb3RvdHlwZTsKICAgIH0KCiAgICB2YXIgR3AgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5wcm90b3R5cGUgPQogICAgICBHZW5lcmF0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7CiAgICBHZW5lcmF0b3JGdW5jdGlvbi5wcm90b3R5cGUgPSBHcC5jb25zdHJ1Y3RvciA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlOwogICAgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUuY29uc3RydWN0b3IgPSBHZW5lcmF0b3JGdW5jdGlvbjsKICAgIEdlbmVyYXRvckZ1bmN0aW9uLmRpc3BsYXlOYW1lID0gZGVmaW5lKAogICAgICBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwKICAgICAgdG9TdHJpbmdUYWdTeW1ib2wsCiAgICAgICJHZW5lcmF0b3JGdW5jdGlvbiIKICAgICk7CgogICAgLy8gSGVscGVyIGZvciBkZWZpbmluZyB0aGUgLm5leHQsIC50aHJvdywgYW5kIC5yZXR1cm4gbWV0aG9kcyBvZiB0aGUKICAgIC8vIEl0ZXJhdG9yIGludGVyZmFjZSBpbiB0ZXJtcyBvZiBhIHNpbmdsZSAuX2ludm9rZSBtZXRob2QuCiAgICBmdW5jdGlvbiBkZWZpbmVJdGVyYXRvck1ldGhvZHMocHJvdG90eXBlKSB7CiAgICAgIFsibmV4dCIsICJ0aHJvdyIsICJyZXR1cm4iXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkgewogICAgICAgIGRlZmluZShwcm90b3R5cGUsIG1ldGhvZCwgZnVuY3Rpb24oYXJnKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5faW52b2tlKG1ldGhvZCwgYXJnKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9CgogICAgZXhwb3J0cy5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24oZ2VuRnVuKSB7CiAgICAgIHZhciBjdG9yID0gdHlwZW9mIGdlbkZ1biA9PT0gImZ1bmN0aW9uIiAmJiBnZW5GdW4uY29uc3RydWN0b3I7CiAgICAgIHJldHVybiBjdG9yCiAgICAgICAgPyBjdG9yID09PSBHZW5lcmF0b3JGdW5jdGlvbiB8fAogICAgICAgICAgLy8gRm9yIHRoZSBuYXRpdmUgR2VuZXJhdG9yRnVuY3Rpb24gY29uc3RydWN0b3IsIHRoZSBiZXN0IHdlIGNhbgogICAgICAgICAgLy8gZG8gaXMgdG8gY2hlY2sgaXRzIC5uYW1lIHByb3BlcnR5LgogICAgICAgICAgKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSA9PT0gIkdlbmVyYXRvckZ1bmN0aW9uIgogICAgICAgIDogZmFsc2U7CiAgICB9OwoKICAgIGV4cG9ydHMubWFyayA9IGZ1bmN0aW9uKGdlbkZ1bikgewogICAgICBpZiAoT2JqZWN0LnNldFByb3RvdHlwZU9mKSB7CiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGdlbkZ1biwgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUpOwogICAgICB9IGVsc2UgewogICAgICAgIGdlbkZ1bi5fX3Byb3RvX18gPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZTsKICAgICAgICBkZWZpbmUoZ2VuRnVuLCB0b1N0cmluZ1RhZ1N5bWJvbCwgIkdlbmVyYXRvckZ1bmN0aW9uIik7CiAgICAgIH0KICAgICAgZ2VuRnVuLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR3ApOwogICAgICByZXR1cm4gZ2VuRnVuOwogICAgfTsKCiAgICAvLyBXaXRoaW4gdGhlIGJvZHkgb2YgYW55IGFzeW5jIGZ1bmN0aW9uLCBgYXdhaXQgeGAgaXMgdHJhbnNmb3JtZWQgdG8KICAgIC8vIGB5aWVsZCByZWdlbmVyYXRvclJ1bnRpbWUuYXdyYXAoeClgLCBzbyB0aGF0IHRoZSBydW50aW1lIGNhbiB0ZXN0CiAgICAvLyBgaGFzT3duLmNhbGwodmFsdWUsICJfX2F3YWl0IilgIHRvIGRldGVybWluZSBpZiB0aGUgeWllbGRlZCB2YWx1ZSBpcwogICAgLy8gbWVhbnQgdG8gYmUgYXdhaXRlZC4KICAgIGV4cG9ydHMuYXdyYXAgPSBmdW5jdGlvbihhcmcpIHsKICAgICAgcmV0dXJuIHsgX19hd2FpdDogYXJnIH07CiAgICB9OwoKICAgIGZ1bmN0aW9uIEFzeW5jSXRlcmF0b3IoZ2VuZXJhdG9yLCBQcm9taXNlSW1wbCkgewogICAgICBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkgewogICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChnZW5lcmF0b3JbbWV0aG9kXSwgZ2VuZXJhdG9yLCBhcmcpOwogICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgcmVqZWN0KHJlY29yZC5hcmcpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YXIgcmVzdWx0ID0gcmVjb3JkLmFyZzsKICAgICAgICAgIHZhciB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsKICAgICAgICAgIGlmICh2YWx1ZSAmJgogICAgICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gIm9iamVjdCIgJiYKICAgICAgICAgICAgICBoYXNPd24uY2FsbCh2YWx1ZSwgIl9fYXdhaXQiKSkgewogICAgICAgICAgICByZXR1cm4gUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZS5fX2F3YWl0KS50aGVuKGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgICAgaW52b2tlKCJuZXh0IiwgdmFsdWUsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGVycikgewogICAgICAgICAgICAgIGludm9rZSgidGhyb3ciLCBlcnIsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBQcm9taXNlSW1wbC5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uKHVud3JhcHBlZCkgewogICAgICAgICAgICAvLyBXaGVuIGEgeWllbGRlZCBQcm9taXNlIGlzIHJlc29sdmVkLCBpdHMgZmluYWwgdmFsdWUgYmVjb21lcwogICAgICAgICAgICAvLyB0aGUgLnZhbHVlIG9mIHRoZSBQcm9taXNlPHt2YWx1ZSxkb25lfT4gcmVzdWx0IGZvciB0aGUKICAgICAgICAgICAgLy8gY3VycmVudCBpdGVyYXRpb24uCiAgICAgICAgICAgIHJlc3VsdC52YWx1ZSA9IHVud3JhcHBlZDsKICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpOwogICAgICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHsKICAgICAgICAgICAgLy8gSWYgYSByZWplY3RlZCBQcm9taXNlIHdhcyB5aWVsZGVkLCB0aHJvdyB0aGUgcmVqZWN0aW9uIGJhY2sKICAgICAgICAgICAgLy8gaW50byB0aGUgYXN5bmMgZ2VuZXJhdG9yIGZ1bmN0aW9uIHNvIGl0IGNhbiBiZSBoYW5kbGVkIHRoZXJlLgogICAgICAgICAgICByZXR1cm4gaW52b2tlKCJ0aHJvdyIsIGVycm9yLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgcHJldmlvdXNQcm9taXNlOwoKICAgICAgZnVuY3Rpb24gZW5xdWV1ZShtZXRob2QsIGFyZykgewogICAgICAgIGZ1bmN0aW9uIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCkgewogICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlSW1wbChmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcHJldmlvdXNQcm9taXNlID0KICAgICAgICAgIC8vIElmIGVucXVldWUgaGFzIGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiB3ZSB3YW50IHRvIHdhaXQgdW50aWwKICAgICAgICAgIC8vIGFsbCBwcmV2aW91cyBQcm9taXNlcyBoYXZlIGJlZW4gcmVzb2x2ZWQgYmVmb3JlIGNhbGxpbmcgaW52b2tlLAogICAgICAgICAgLy8gc28gdGhhdCByZXN1bHRzIGFyZSBhbHdheXMgZGVsaXZlcmVkIGluIHRoZSBjb3JyZWN0IG9yZGVyLiBJZgogICAgICAgICAgLy8gZW5xdWV1ZSBoYXMgbm90IGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiBpdCBpcyBpbXBvcnRhbnQgdG8KICAgICAgICAgIC8vIGNhbGwgaW52b2tlIGltbWVkaWF0ZWx5LCB3aXRob3V0IHdhaXRpbmcgb24gYSBjYWxsYmFjayB0byBmaXJlLAogICAgICAgICAgLy8gc28gdGhhdCB0aGUgYXN5bmMgZ2VuZXJhdG9yIGZ1bmN0aW9uIGhhcyB0aGUgb3Bwb3J0dW5pdHkgdG8gZG8KICAgICAgICAgIC8vIGFueSBuZWNlc3Nhcnkgc2V0dXAgaW4gYSBwcmVkaWN0YWJsZSB3YXkuIFRoaXMgcHJlZGljdGFiaWxpdHkKICAgICAgICAgIC8vIGlzIHdoeSB0aGUgUHJvbWlzZSBjb25zdHJ1Y3RvciBzeW5jaHJvbm91c2x5IGludm9rZXMgaXRzCiAgICAgICAgICAvLyBleGVjdXRvciBjYWxsYmFjaywgYW5kIHdoeSBhc3luYyBmdW5jdGlvbnMgc3luY2hyb25vdXNseQogICAgICAgICAgLy8gZXhlY3V0ZSBjb2RlIGJlZm9yZSB0aGUgZmlyc3QgYXdhaXQuIFNpbmNlIHdlIGltcGxlbWVudCBzaW1wbGUKICAgICAgICAgIC8vIGFzeW5jIGZ1bmN0aW9ucyBpbiB0ZXJtcyBvZiBhc3luYyBnZW5lcmF0b3JzLCBpdCBpcyBlc3BlY2lhbGx5CiAgICAgICAgICAvLyBpbXBvcnRhbnQgdG8gZ2V0IHRoaXMgcmlnaHQsIGV2ZW4gdGhvdWdoIGl0IHJlcXVpcmVzIGNhcmUuCiAgICAgICAgICBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbigKICAgICAgICAgICAgY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcsCiAgICAgICAgICAgIC8vIEF2b2lkIHByb3BhZ2F0aW5nIGZhaWx1cmVzIHRvIFByb21pc2VzIHJldHVybmVkIGJ5IGxhdGVyCiAgICAgICAgICAgIC8vIGludm9jYXRpb25zIG9mIHRoZSBpdGVyYXRvci4KICAgICAgICAgICAgY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcKICAgICAgICAgICkgOiBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZygpOwogICAgICB9CgogICAgICAvLyBEZWZpbmUgdGhlIHVuaWZpZWQgaGVscGVyIG1ldGhvZCB0aGF0IGlzIHVzZWQgdG8gaW1wbGVtZW50IC5uZXh0LAogICAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIChzZWUgZGVmaW5lSXRlcmF0b3JNZXRob2RzKS4KICAgICAgdGhpcy5faW52b2tlID0gZW5xdWV1ZTsKICAgIH0KCiAgICBkZWZpbmVJdGVyYXRvck1ldGhvZHMoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUpOwogICAgQXN5bmNJdGVyYXRvci5wcm90b3R5cGVbYXN5bmNJdGVyYXRvclN5bWJvbF0gPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKICAgIGV4cG9ydHMuQXN5bmNJdGVyYXRvciA9IEFzeW5jSXRlcmF0b3I7CgogICAgLy8gTm90ZSB0aGF0IHNpbXBsZSBhc3luYyBmdW5jdGlvbnMgYXJlIGltcGxlbWVudGVkIG9uIHRvcCBvZgogICAgLy8gQXN5bmNJdGVyYXRvciBvYmplY3RzOyB0aGV5IGp1c3QgcmV0dXJuIGEgUHJvbWlzZSBmb3IgdGhlIHZhbHVlIG9mCiAgICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci4KICAgIGV4cG9ydHMuYXN5bmMgPSBmdW5jdGlvbihpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCwgUHJvbWlzZUltcGwpIHsKICAgICAgaWYgKFByb21pc2VJbXBsID09PSB2b2lkIDApIFByb21pc2VJbXBsID0gUHJvbWlzZTsKCiAgICAgIHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3IoCiAgICAgICAgd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCksCiAgICAgICAgUHJvbWlzZUltcGwKICAgICAgKTsKCiAgICAgIHJldHVybiBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikKICAgICAgICA/IGl0ZXIgLy8gSWYgb3V0ZXJGbiBpcyBhIGdlbmVyYXRvciwgcmV0dXJuIHRoZSBmdWxsIGl0ZXJhdG9yLgogICAgICAgIDogaXRlci5uZXh0KCkudGhlbihmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7CiAgICAgICAgICB9KTsKICAgIH07CgogICAgZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7CiAgICAgIHZhciBzdGF0ZSA9IEdlblN0YXRlU3VzcGVuZGVkU3RhcnQ7CgogICAgICByZXR1cm4gZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnKSB7CiAgICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZUV4ZWN1dGluZykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBydW5uaW5nIik7CiAgICAgICAgfQoKICAgICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlQ29tcGxldGVkKSB7CiAgICAgICAgICBpZiAobWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgIHRocm93IGFyZzsKICAgICAgICAgIH0KCiAgICAgICAgICAvLyBCZSBmb3JnaXZpbmcsIHBlciAyNS4zLjMuMy4zIG9mIHRoZSBzcGVjOgogICAgICAgICAgLy8gaHR0cHM6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLWdlbmVyYXRvcnJlc3VtZQogICAgICAgICAgcmV0dXJuIGRvbmVSZXN1bHQoKTsKICAgICAgICB9CgogICAgICAgIGNvbnRleHQubWV0aG9kID0gbWV0aG9kOwogICAgICAgIGNvbnRleHQuYXJnID0gYXJnOwoKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgdmFyIGRlbGVnYXRlID0gY29udGV4dC5kZWxlZ2F0ZTsKICAgICAgICAgIGlmIChkZWxlZ2F0ZSkgewogICAgICAgICAgICB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTsKICAgICAgICAgICAgaWYgKGRlbGVnYXRlUmVzdWx0KSB7CiAgICAgICAgICAgICAgaWYgKGRlbGVnYXRlUmVzdWx0ID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsKICAgICAgICAgICAgICByZXR1cm4gZGVsZWdhdGVSZXN1bHQ7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoY29udGV4dC5tZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgICAvLyBTZXR0aW5nIGNvbnRleHQuX3NlbnQgZm9yIGxlZ2FjeSBzdXBwb3J0IG9mIEJhYmVsJ3MKICAgICAgICAgICAgLy8gZnVuY3Rpb24uc2VudCBpbXBsZW1lbnRhdGlvbi4KICAgICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnOwoKICAgICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0KSB7CiAgICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDsKICAgICAgICAgICAgICB0aHJvdyBjb250ZXh0LmFyZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGV4dC5kaXNwYXRjaEV4Y2VwdGlvbihjb250ZXh0LmFyZyk7CgogICAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0Lm1ldGhvZCA9PT0gInJldHVybiIpIHsKICAgICAgICAgICAgY29udGV4dC5hYnJ1cHQoInJldHVybiIsIGNvbnRleHQuYXJnKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlRXhlY3V0aW5nOwoKICAgICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gIm5vcm1hbCIpIHsKICAgICAgICAgICAgLy8gSWYgYW4gZXhjZXB0aW9uIGlzIHRocm93biBmcm9tIGlubmVyRm4sIHdlIGxlYXZlIHN0YXRlID09PQogICAgICAgICAgICAvLyBHZW5TdGF0ZUV4ZWN1dGluZyBhbmQgbG9vcCBiYWNrIGZvciBhbm90aGVyIGludm9jYXRpb24uCiAgICAgICAgICAgIHN0YXRlID0gY29udGV4dC5kb25lCiAgICAgICAgICAgICAgPyBHZW5TdGF0ZUNvbXBsZXRlZAogICAgICAgICAgICAgIDogR2VuU3RhdGVTdXNwZW5kZWRZaWVsZDsKCiAgICAgICAgICAgIGlmIChyZWNvcmQuYXJnID09PSBDb250aW51ZVNlbnRpbmVsKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgdmFsdWU6IHJlY29yZC5hcmcsCiAgICAgICAgICAgICAgZG9uZTogY29udGV4dC5kb25lCiAgICAgICAgICAgIH07CgogICAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlQ29tcGxldGVkOwogICAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlCiAgICAgICAgICAgIC8vIGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpIGNhbGwgYWJvdmUuCiAgICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gInRocm93IjsKICAgICAgICAgICAgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKICAgIH0KCiAgICAvLyBDYWxsIGRlbGVnYXRlLml0ZXJhdG9yW2NvbnRleHQubWV0aG9kXShjb250ZXh0LmFyZykgYW5kIGhhbmRsZSB0aGUKICAgIC8vIHJlc3VsdCwgZWl0aGVyIGJ5IHJldHVybmluZyBhIHsgdmFsdWUsIGRvbmUgfSByZXN1bHQgZnJvbSB0aGUKICAgIC8vIGRlbGVnYXRlIGl0ZXJhdG9yLCBvciBieSBtb2RpZnlpbmcgY29udGV4dC5tZXRob2QgYW5kIGNvbnRleHQuYXJnLAogICAgLy8gc2V0dGluZyBjb250ZXh0LmRlbGVnYXRlIHRvIG51bGwsIGFuZCByZXR1cm5pbmcgdGhlIENvbnRpbnVlU2VudGluZWwuCiAgICBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7CiAgICAgIHZhciBtZXRob2QgPSBkZWxlZ2F0ZS5pdGVyYXRvcltjb250ZXh0Lm1ldGhvZF07CiAgICAgIGlmIChtZXRob2QgPT09IHVuZGVmaW5lZCQxKSB7CiAgICAgICAgLy8gQSAudGhyb3cgb3IgLnJldHVybiB3aGVuIHRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBoYXMgbm8gLnRocm93CiAgICAgICAgLy8gbWV0aG9kIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC4KICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKCiAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAvLyBOb3RlOiBbInJldHVybiJdIG11c3QgYmUgdXNlZCBmb3IgRVMzIHBhcnNpbmcgY29tcGF0aWJpbGl0eS4KICAgICAgICAgIGlmIChkZWxlZ2F0ZS5pdGVyYXRvclsicmV0dXJuIl0pIHsKICAgICAgICAgICAgLy8gSWYgdGhlIGRlbGVnYXRlIGl0ZXJhdG9yIGhhcyBhIHJldHVybiBtZXRob2QsIGdpdmUgaXQgYQogICAgICAgICAgICAvLyBjaGFuY2UgdG8gY2xlYW4gdXAuCiAgICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gInJldHVybiI7CiAgICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgICAgIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpOwoKICAgICAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgICAgLy8gSWYgbWF5YmVJbnZva2VEZWxlZ2F0ZShjb250ZXh0KSBjaGFuZ2VkIGNvbnRleHQubWV0aG9kIGZyb20KICAgICAgICAgICAgICAvLyAicmV0dXJuIiB0byAidGhyb3ciLCBsZXQgdGhhdCBvdmVycmlkZSB0aGUgVHlwZUVycm9yIGJlbG93LgogICAgICAgICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgY29udGV4dC5tZXRob2QgPSAidGhyb3ciOwogICAgICAgICAgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKAogICAgICAgICAgICAiVGhlIGl0ZXJhdG9yIGRvZXMgbm90IHByb3ZpZGUgYSAndGhyb3cnIG1ldGhvZCIpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgIH0KCiAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChtZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBjb250ZXh0LmFyZyk7CgogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJ0aHJvdyI7CiAgICAgICAgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnOwogICAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsOwogICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICB9CgogICAgICB2YXIgaW5mbyA9IHJlY29yZC5hcmc7CgogICAgICBpZiAoISBpbmZvKSB7CiAgICAgICAgY29udGV4dC5tZXRob2QgPSAidGhyb3ciOwogICAgICAgIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcigiaXRlcmF0b3IgcmVzdWx0IGlzIG5vdCBhbiBvYmplY3QiKTsKICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgfQoKICAgICAgaWYgKGluZm8uZG9uZSkgewogICAgICAgIC8vIEFzc2lnbiB0aGUgcmVzdWx0IG9mIHRoZSBmaW5pc2hlZCBkZWxlZ2F0ZSB0byB0aGUgdGVtcG9yYXJ5CiAgICAgICAgLy8gdmFyaWFibGUgc3BlY2lmaWVkIGJ5IGRlbGVnYXRlLnJlc3VsdE5hbWUgKHNlZSBkZWxlZ2F0ZVlpZWxkKS4KICAgICAgICBjb250ZXh0W2RlbGVnYXRlLnJlc3VsdE5hbWVdID0gaW5mby52YWx1ZTsKCiAgICAgICAgLy8gUmVzdW1lIGV4ZWN1dGlvbiBhdCB0aGUgZGVzaXJlZCBsb2NhdGlvbiAoc2VlIGRlbGVnYXRlWWllbGQpLgogICAgICAgIGNvbnRleHQubmV4dCA9IGRlbGVnYXRlLm5leHRMb2M7CgogICAgICAgIC8vIElmIGNvbnRleHQubWV0aG9kIHdhcyAidGhyb3ciIGJ1dCB0aGUgZGVsZWdhdGUgaGFuZGxlZCB0aGUKICAgICAgICAvLyBleGNlcHRpb24sIGxldCB0aGUgb3V0ZXIgZ2VuZXJhdG9yIHByb2NlZWQgbm9ybWFsbHkuIElmCiAgICAgICAgLy8gY29udGV4dC5tZXRob2Qgd2FzICJuZXh0IiwgZm9yZ2V0IGNvbnRleHQuYXJnIHNpbmNlIGl0IGhhcyBiZWVuCiAgICAgICAgLy8gImNvbnN1bWVkIiBieSB0aGUgZGVsZWdhdGUgaXRlcmF0b3IuIElmIGNvbnRleHQubWV0aG9kIHdhcwogICAgICAgIC8vICJyZXR1cm4iLCBhbGxvdyB0aGUgb3JpZ2luYWwgLnJldHVybiBjYWxsIHRvIGNvbnRpbnVlIGluIHRoZQogICAgICAgIC8vIG91dGVyIGdlbmVyYXRvci4KICAgICAgICBpZiAoY29udGV4dC5tZXRob2QgIT09ICJyZXR1cm4iKSB7CiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgfQoKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBSZS15aWVsZCB0aGUgcmVzdWx0IHJldHVybmVkIGJ5IHRoZSBkZWxlZ2F0ZSBtZXRob2QuCiAgICAgICAgcmV0dXJuIGluZm87CiAgICAgIH0KCiAgICAgIC8vIFRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBpcyBmaW5pc2hlZCwgc28gZm9yZ2V0IGl0IGFuZCBjb250aW51ZSB3aXRoCiAgICAgIC8vIHRoZSBvdXRlciBnZW5lcmF0b3IuCiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsOwogICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgIH0KCiAgICAvLyBEZWZpbmUgR2VuZXJhdG9yLnByb3RvdHlwZS57bmV4dCx0aHJvdyxyZXR1cm59IGluIHRlcm1zIG9mIHRoZQogICAgLy8gdW5pZmllZCAuX2ludm9rZSBoZWxwZXIgbWV0aG9kLgogICAgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEdwKTsKCiAgICBkZWZpbmUoR3AsIHRvU3RyaW5nVGFnU3ltYm9sLCAiR2VuZXJhdG9yIik7CgogICAgLy8gQSBHZW5lcmF0b3Igc2hvdWxkIGFsd2F5cyByZXR1cm4gaXRzZWxmIGFzIHRoZSBpdGVyYXRvciBvYmplY3Qgd2hlbiB0aGUKICAgIC8vIEBAaXRlcmF0b3IgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGl0LiBTb21lIGJyb3dzZXJzJyBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlCiAgICAvLyBpdGVyYXRvciBwcm90b3R5cGUgY2hhaW4gaW5jb3JyZWN0bHkgaW1wbGVtZW50IHRoaXMsIGNhdXNpbmcgdGhlIEdlbmVyYXRvcgogICAgLy8gb2JqZWN0IHRvIG5vdCBiZSByZXR1cm5lZCBmcm9tIHRoaXMgY2FsbC4gVGhpcyBlbnN1cmVzIHRoYXQgZG9lc24ndCBoYXBwZW4uCiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL2lzc3Vlcy8yNzQgZm9yIG1vcmUgZGV0YWlscy4KICAgIEdwW2l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgR3AudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuICJbb2JqZWN0IEdlbmVyYXRvcl0iOwogICAgfTsKCiAgICBmdW5jdGlvbiBwdXNoVHJ5RW50cnkobG9jcykgewogICAgICB2YXIgZW50cnkgPSB7IHRyeUxvYzogbG9jc1swXSB9OwoKICAgICAgaWYgKDEgaW4gbG9jcykgewogICAgICAgIGVudHJ5LmNhdGNoTG9jID0gbG9jc1sxXTsKICAgICAgfQoKICAgICAgaWYgKDIgaW4gbG9jcykgewogICAgICAgIGVudHJ5LmZpbmFsbHlMb2MgPSBsb2NzWzJdOwogICAgICAgIGVudHJ5LmFmdGVyTG9jID0gbG9jc1szXTsKICAgICAgfQoKICAgICAgdGhpcy50cnlFbnRyaWVzLnB1c2goZW50cnkpOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHsKICAgICAgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb24gfHwge307CiAgICAgIHJlY29yZC50eXBlID0gIm5vcm1hbCI7CiAgICAgIGRlbGV0ZSByZWNvcmQuYXJnOwogICAgICBlbnRyeS5jb21wbGV0aW9uID0gcmVjb3JkOwogICAgfQoKICAgIGZ1bmN0aW9uIENvbnRleHQodHJ5TG9jc0xpc3QpIHsKICAgICAgLy8gVGhlIHJvb3QgZW50cnkgb2JqZWN0IChlZmZlY3RpdmVseSBhIHRyeSBzdGF0ZW1lbnQgd2l0aG91dCBhIGNhdGNoCiAgICAgIC8vIG9yIGEgZmluYWxseSBibG9jaykgZ2l2ZXMgdXMgYSBwbGFjZSB0byBzdG9yZSB2YWx1ZXMgdGhyb3duIGZyb20KICAgICAgLy8gbG9jYXRpb25zIHdoZXJlIHRoZXJlIGlzIG5vIGVuY2xvc2luZyB0cnkgc3RhdGVtZW50LgogICAgICB0aGlzLnRyeUVudHJpZXMgPSBbeyB0cnlMb2M6ICJyb290IiB9XTsKICAgICAgdHJ5TG9jc0xpc3QuZm9yRWFjaChwdXNoVHJ5RW50cnksIHRoaXMpOwogICAgICB0aGlzLnJlc2V0KHRydWUpOwogICAgfQoKICAgIGV4cG9ydHMua2V5cyA9IGZ1bmN0aW9uKG9iamVjdCkgewogICAgICB2YXIga2V5cyA9IFtdOwogICAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7CiAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgIH0KICAgICAga2V5cy5yZXZlcnNlKCk7CgogICAgICAvLyBSYXRoZXIgdGhhbiByZXR1cm5pbmcgYW4gb2JqZWN0IHdpdGggYSBuZXh0IG1ldGhvZCwgd2Uga2VlcAogICAgICAvLyB0aGluZ3Mgc2ltcGxlIGFuZCByZXR1cm4gdGhlIG5leHQgZnVuY3Rpb24gaXRzZWxmLgogICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dCgpIHsKICAgICAgICB3aGlsZSAoa2V5cy5sZW5ndGgpIHsKICAgICAgICAgIHZhciBrZXkgPSBrZXlzLnBvcCgpOwogICAgICAgICAgaWYgKGtleSBpbiBvYmplY3QpIHsKICAgICAgICAgICAgbmV4dC52YWx1ZSA9IGtleTsKICAgICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7CiAgICAgICAgICAgIHJldHVybiBuZXh0OwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gVG8gYXZvaWQgY3JlYXRpbmcgYW4gYWRkaXRpb25hbCBvYmplY3QsIHdlIGp1c3QgaGFuZyB0aGUgLnZhbHVlCiAgICAgICAgLy8gYW5kIC5kb25lIHByb3BlcnRpZXMgb2ZmIHRoZSBuZXh0IGZ1bmN0aW9uIG9iamVjdCBpdHNlbGYuIFRoaXMKICAgICAgICAvLyBhbHNvIGVuc3VyZXMgdGhhdCB0aGUgbWluaWZpZXIgd2lsbCBub3QgYW5vbnltaXplIHRoZSBmdW5jdGlvbi4KICAgICAgICBuZXh0LmRvbmUgPSB0cnVlOwogICAgICAgIHJldHVybiBuZXh0OwogICAgICB9OwogICAgfTsKCiAgICBmdW5jdGlvbiB2YWx1ZXMoaXRlcmFibGUpIHsKICAgICAgaWYgKGl0ZXJhYmxlKSB7CiAgICAgICAgdmFyIGl0ZXJhdG9yTWV0aG9kID0gaXRlcmFibGVbaXRlcmF0b3JTeW1ib2xdOwogICAgICAgIGlmIChpdGVyYXRvck1ldGhvZCkgewogICAgICAgICAgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHR5cGVvZiBpdGVyYWJsZS5uZXh0ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICByZXR1cm4gaXRlcmFibGU7CiAgICAgICAgfQoKICAgICAgICBpZiAoIWlzTmFOKGl0ZXJhYmxlLmxlbmd0aCkpIHsKICAgICAgICAgIHZhciBpID0gLTEsIG5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICAgICAgICB3aGlsZSAoKytpIDwgaXRlcmFibGUubGVuZ3RoKSB7CiAgICAgICAgICAgICAgaWYgKGhhc093bi5jYWxsKGl0ZXJhYmxlLCBpKSkgewogICAgICAgICAgICAgICAgbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldOwogICAgICAgICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7CiAgICAgICAgICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIG5leHQudmFsdWUgPSB1bmRlZmluZWQkMTsKICAgICAgICAgICAgbmV4dC5kb25lID0gdHJ1ZTsKCiAgICAgICAgICAgIHJldHVybiBuZXh0OwogICAgICAgICAgfTsKCiAgICAgICAgICByZXR1cm4gbmV4dC5uZXh0ID0gbmV4dDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIFJldHVybiBhbiBpdGVyYXRvciB3aXRoIG5vIHZhbHVlcy4KICAgICAgcmV0dXJuIHsgbmV4dDogZG9uZVJlc3VsdCB9OwogICAgfQogICAgZXhwb3J0cy52YWx1ZXMgPSB2YWx1ZXM7CgogICAgZnVuY3Rpb24gZG9uZVJlc3VsdCgpIHsKICAgICAgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCQxLCBkb25lOiB0cnVlIH07CiAgICB9CgogICAgQ29udGV4dC5wcm90b3R5cGUgPSB7CiAgICAgIGNvbnN0cnVjdG9yOiBDb250ZXh0LAoKICAgICAgcmVzZXQ6IGZ1bmN0aW9uKHNraXBUZW1wUmVzZXQpIHsKICAgICAgICB0aGlzLnByZXYgPSAwOwogICAgICAgIHRoaXMubmV4dCA9IDA7CiAgICAgICAgLy8gUmVzZXR0aW5nIGNvbnRleHQuX3NlbnQgZm9yIGxlZ2FjeSBzdXBwb3J0IG9mIEJhYmVsJ3MKICAgICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLgogICAgICAgIHRoaXMuc2VudCA9IHRoaXMuX3NlbnQgPSB1bmRlZmluZWQkMTsKICAgICAgICB0aGlzLmRvbmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmRlbGVnYXRlID0gbnVsbDsKCiAgICAgICAgdGhpcy5tZXRob2QgPSAibmV4dCI7CiAgICAgICAgdGhpcy5hcmcgPSB1bmRlZmluZWQkMTsKCiAgICAgICAgdGhpcy50cnlFbnRyaWVzLmZvckVhY2gocmVzZXRUcnlFbnRyeSk7CgogICAgICAgIGlmICghc2tpcFRlbXBSZXNldCkgewogICAgICAgICAgZm9yICh2YXIgbmFtZSBpbiB0aGlzKSB7CiAgICAgICAgICAgIC8vIE5vdCBzdXJlIGFib3V0IHRoZSBvcHRpbWFsIG9yZGVyIG9mIHRoZXNlIGNvbmRpdGlvbnM6CiAgICAgICAgICAgIGlmIChuYW1lLmNoYXJBdCgwKSA9PT0gInQiICYmCiAgICAgICAgICAgICAgICBoYXNPd24uY2FsbCh0aGlzLCBuYW1lKSAmJgogICAgICAgICAgICAgICAgIWlzTmFOKCtuYW1lLnNsaWNlKDEpKSkgewogICAgICAgICAgICAgIHRoaXNbbmFtZV0gPSB1bmRlZmluZWQkMTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKCiAgICAgIHN0b3A6IGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMuZG9uZSA9IHRydWU7CgogICAgICAgIHZhciByb290RW50cnkgPSB0aGlzLnRyeUVudHJpZXNbMF07CiAgICAgICAgdmFyIHJvb3RSZWNvcmQgPSByb290RW50cnkuY29tcGxldGlvbjsKICAgICAgICBpZiAocm9vdFJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgICB0aHJvdyByb290UmVjb3JkLmFyZzsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLnJ2YWw7CiAgICAgIH0sCgogICAgICBkaXNwYXRjaEV4Y2VwdGlvbjogZnVuY3Rpb24oZXhjZXB0aW9uKSB7CiAgICAgICAgaWYgKHRoaXMuZG9uZSkgewogICAgICAgICAgdGhyb3cgZXhjZXB0aW9uOwogICAgICAgIH0KCiAgICAgICAgdmFyIGNvbnRleHQgPSB0aGlzOwogICAgICAgIGZ1bmN0aW9uIGhhbmRsZShsb2MsIGNhdWdodCkgewogICAgICAgICAgcmVjb3JkLnR5cGUgPSAidGhyb3ciOwogICAgICAgICAgcmVjb3JkLmFyZyA9IGV4Y2VwdGlvbjsKICAgICAgICAgIGNvbnRleHQubmV4dCA9IGxvYzsKCiAgICAgICAgICBpZiAoY2F1Z2h0KSB7CiAgICAgICAgICAgIC8vIElmIHRoZSBkaXNwYXRjaGVkIGV4Y2VwdGlvbiB3YXMgY2F1Z2h0IGJ5IGEgY2F0Y2ggYmxvY2ssCiAgICAgICAgICAgIC8vIHRoZW4gbGV0IHRoYXQgY2F0Y2ggYmxvY2sgaGFuZGxlIHRoZSBleGNlcHRpb24gbm9ybWFsbHkuCiAgICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gIm5leHQiOwogICAgICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCQxOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiAhISBjYXVnaHQ7CiAgICAgICAgfQoKICAgICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07CiAgICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsKCiAgICAgICAgICBpZiAoZW50cnkudHJ5TG9jID09PSAicm9vdCIpIHsKICAgICAgICAgICAgLy8gRXhjZXB0aW9uIHRocm93biBvdXRzaWRlIG9mIGFueSB0cnkgYmxvY2sgdGhhdCBjb3VsZCBoYW5kbGUKICAgICAgICAgICAgLy8gaXQsIHNvIHNldCB0aGUgY29tcGxldGlvbiB2YWx1ZSBvZiB0aGUgZW50aXJlIGZ1bmN0aW9uIHRvCiAgICAgICAgICAgIC8vIHRocm93IHRoZSBleGNlcHRpb24uCiAgICAgICAgICAgIHJldHVybiBoYW5kbGUoImVuZCIpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2KSB7CiAgICAgICAgICAgIHZhciBoYXNDYXRjaCA9IGhhc093bi5jYWxsKGVudHJ5LCAiY2F0Y2hMb2MiKTsKICAgICAgICAgICAgdmFyIGhhc0ZpbmFsbHkgPSBoYXNPd24uY2FsbChlbnRyeSwgImZpbmFsbHlMb2MiKTsKCiAgICAgICAgICAgIGlmIChoYXNDYXRjaCAmJiBoYXNGaW5hbGx5KSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCB0cnVlKTsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgfSBlbHNlIGlmIChoYXNDYXRjaCkgewogICAgICAgICAgICAgIGlmICh0aGlzLnByZXYgPCBlbnRyeS5jYXRjaExvYykgewogICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgfSBlbHNlIGlmIChoYXNGaW5hbGx5KSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoInRyeSBzdGF0ZW1lbnQgd2l0aG91dCBjYXRjaCBvciBmaW5hbGx5Iik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCgogICAgICBhYnJ1cHQ6IGZ1bmN0aW9uKHR5cGUsIGFyZykgewogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICAgIGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2ICYmCiAgICAgICAgICAgICAgaGFzT3duLmNhbGwoZW50cnksICJmaW5hbGx5TG9jIikgJiYKICAgICAgICAgICAgICB0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAgIHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoZmluYWxseUVudHJ5ICYmCiAgICAgICAgICAgICh0eXBlID09PSAiYnJlYWsiIHx8CiAgICAgICAgICAgICB0eXBlID09PSAiY29udGludWUiKSAmJgogICAgICAgICAgICBmaW5hbGx5RW50cnkudHJ5TG9jIDw9IGFyZyAmJgogICAgICAgICAgICBhcmcgPD0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgIC8vIElnbm9yZSB0aGUgZmluYWxseSBlbnRyeSBpZiBjb250cm9sIGlzIG5vdCBqdW1waW5nIHRvIGEKICAgICAgICAgIC8vIGxvY2F0aW9uIG91dHNpZGUgdGhlIHRyeS9jYXRjaCBibG9jay4KICAgICAgICAgIGZpbmFsbHlFbnRyeSA9IG51bGw7CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVjb3JkID0gZmluYWxseUVudHJ5ID8gZmluYWxseUVudHJ5LmNvbXBsZXRpb24gOiB7fTsKICAgICAgICByZWNvcmQudHlwZSA9IHR5cGU7CiAgICAgICAgcmVjb3JkLmFyZyA9IGFyZzsKCiAgICAgICAgaWYgKGZpbmFsbHlFbnRyeSkgewogICAgICAgICAgdGhpcy5tZXRob2QgPSAibmV4dCI7CiAgICAgICAgICB0aGlzLm5leHQgPSBmaW5hbGx5RW50cnkuZmluYWxseUxvYzsKICAgICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuY29tcGxldGUocmVjb3JkKTsKICAgICAgfSwKCiAgICAgIGNvbXBsZXRlOiBmdW5jdGlvbihyZWNvcmQsIGFmdGVyTG9jKSB7CiAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgICB0aHJvdyByZWNvcmQuYXJnOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSAiYnJlYWsiIHx8CiAgICAgICAgICAgIHJlY29yZC50eXBlID09PSAiY29udGludWUiKSB7CiAgICAgICAgICB0aGlzLm5leHQgPSByZWNvcmQuYXJnOwogICAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICB0aGlzLnJ2YWwgPSB0aGlzLmFyZyA9IHJlY29yZC5hcmc7CiAgICAgICAgICB0aGlzLm1ldGhvZCA9ICJyZXR1cm4iOwogICAgICAgICAgdGhpcy5uZXh0ID0gImVuZCI7CiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gIm5vcm1hbCIgJiYgYWZ0ZXJMb2MpIHsKICAgICAgICAgIHRoaXMubmV4dCA9IGFmdGVyTG9jOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgIH0sCgogICAgICBmaW5pc2g6IGZ1bmN0aW9uKGZpbmFsbHlMb2MpIHsKICAgICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07CiAgICAgICAgICBpZiAoZW50cnkuZmluYWxseUxvYyA9PT0gZmluYWxseUxvYykgewogICAgICAgICAgICB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKTsKICAgICAgICAgICAgcmVzZXRUcnlFbnRyeShlbnRyeSk7CiAgICAgICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKCiAgICAgICJjYXRjaCI6IGZ1bmN0aW9uKHRyeUxvYykgewogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykgewogICAgICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsKICAgICAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgICAgdmFyIHRocm93biA9IHJlY29yZC5hcmc7CiAgICAgICAgICAgICAgcmVzZXRUcnlFbnRyeShlbnRyeSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRocm93bjsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIFRoZSBjb250ZXh0LmNhdGNoIG1ldGhvZCBtdXN0IG9ubHkgYmUgY2FsbGVkIHdpdGggYSBsb2NhdGlvbgogICAgICAgIC8vIGFyZ3VtZW50IHRoYXQgY29ycmVzcG9uZHMgdG8gYSBrbm93biBjYXRjaCBibG9jay4KICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImlsbGVnYWwgY2F0Y2ggYXR0ZW1wdCIpOwogICAgICB9LAoKICAgICAgZGVsZWdhdGVZaWVsZDogZnVuY3Rpb24oaXRlcmFibGUsIHJlc3VsdE5hbWUsIG5leHRMb2MpIHsKICAgICAgICB0aGlzLmRlbGVnYXRlID0gewogICAgICAgICAgaXRlcmF0b3I6IHZhbHVlcyhpdGVyYWJsZSksCiAgICAgICAgICByZXN1bHROYW1lOiByZXN1bHROYW1lLAogICAgICAgICAgbmV4dExvYzogbmV4dExvYwogICAgICAgIH07CgogICAgICAgIGlmICh0aGlzLm1ldGhvZCA9PT0gIm5leHQiKSB7CiAgICAgICAgICAvLyBEZWxpYmVyYXRlbHkgZm9yZ2V0IHRoZSBsYXN0IHNlbnQgdmFsdWUgc28gdGhhdCB3ZSBkb24ndAogICAgICAgICAgLy8gYWNjaWRlbnRhbGx5IHBhc3MgaXQgb24gdG8gdGhlIGRlbGVnYXRlLgogICAgICAgICAgdGhpcy5hcmcgPSB1bmRlZmluZWQkMTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICB9CiAgICB9OwoKICAgIC8vIFJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGlzIHNjcmlwdCBpcyBleGVjdXRpbmcgYXMgYSBDb21tb25KUyBtb2R1bGUKICAgIC8vIG9yIG5vdCwgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCBzbyB0aGF0IHdlIGNhbiBkZWNsYXJlIHRoZSB2YXJpYWJsZQogICAgLy8gcmVnZW5lcmF0b3JSdW50aW1lIGluIHRoZSBvdXRlciBzY29wZSwgd2hpY2ggYWxsb3dzIHRoaXMgbW9kdWxlIHRvIGJlCiAgICAvLyBpbmplY3RlZCBlYXNpbHkgYnkgYGJpbi9yZWdlbmVyYXRvciAtLWluY2x1ZGUtcnVudGltZSBzY3JpcHQuanNgLgogICAgcmV0dXJuIGV4cG9ydHM7CgogIH0oCiAgICAvLyBJZiB0aGlzIHNjcmlwdCBpcyBleGVjdXRpbmcgYXMgYSBDb21tb25KUyBtb2R1bGUsIHVzZSBtb2R1bGUuZXhwb3J0cwogICAgLy8gYXMgdGhlIHJlZ2VuZXJhdG9yUnVudGltZSBuYW1lc3BhY2UuIE90aGVyd2lzZSBjcmVhdGUgYSBuZXcgZW1wdHkKICAgIC8vIG9iamVjdC4gRWl0aGVyIHdheSwgdGhlIHJlc3VsdGluZyBvYmplY3Qgd2lsbCBiZSB1c2VkIHRvIGluaXRpYWxpemUKICAgIC8vIHRoZSByZWdlbmVyYXRvclJ1bnRpbWUgdmFyaWFibGUgYXQgdGhlIHRvcCBvZiB0aGlzIGZpbGUuCiAgICBtb2R1bGUuZXhwb3J0cyAKICApKTsKCiAgdHJ5IHsKICAgIHJlZ2VuZXJhdG9yUnVudGltZSA9IHJ1bnRpbWU7CiAgfSBjYXRjaCAoYWNjaWRlbnRhbFN0cmljdE1vZGUpIHsKICAgIC8vIFRoaXMgbW9kdWxlIHNob3VsZCBub3QgYmUgcnVubmluZyBpbiBzdHJpY3QgbW9kZSwgc28gdGhlIGFib3ZlCiAgICAvLyBhc3NpZ25tZW50IHNob3VsZCBhbHdheXMgd29yayB1bmxlc3Mgc29tZXRoaW5nIGlzIG1pc2NvbmZpZ3VyZWQuIEp1c3QKICAgIC8vIGluIGNhc2UgcnVudGltZS5qcyBhY2NpZGVudGFsbHkgcnVucyBpbiBzdHJpY3QgbW9kZSwgd2UgY2FuIGVzY2FwZQogICAgLy8gc3RyaWN0IG1vZGUgdXNpbmcgYSBnbG9iYWwgRnVuY3Rpb24gY2FsbC4gVGhpcyBjb3VsZCBjb25jZWl2YWJseSBmYWlsCiAgICAvLyBpZiBhIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5IGZvcmJpZHMgdXNpbmcgRnVuY3Rpb24sIGJ1dCBpbiB0aGF0IGNhc2UKICAgIC8vIHRoZSBwcm9wZXIgc29sdXRpb24gaXMgdG8gZml4IHRoZSBhY2NpZGVudGFsIHN0cmljdCBtb2RlIHByb2JsZW0uIElmCiAgICAvLyB5b3UndmUgbWlzY29uZmlndXJlZCB5b3VyIGJ1bmRsZXIgdG8gZm9yY2Ugc3RyaWN0IG1vZGUgYW5kIGFwcGxpZWQgYQogICAgLy8gQ1NQIHRvIGZvcmJpZCBGdW5jdGlvbiwgYW5kIHlvdSdyZSBub3Qgd2lsbGluZyB0byBmaXggZWl0aGVyIG9mIHRob3NlCiAgICAvLyBwcm9ibGVtcywgcGxlYXNlIGRldGFpbCB5b3VyIHVuaXF1ZSBwcmVkaWNhbWVudCBpbiBhIEdpdEh1YiBpc3N1ZS4KICAgIEZ1bmN0aW9uKCJyIiwgInJlZ2VuZXJhdG9yUnVudGltZSA9IHIiKShydW50aW1lKTsKICB9CiAgfSk7CgogIHZhciBtYXJ0aW5pID0gbnVsbDsKCiAgZnVuY3Rpb24gZGVjb2RlVGVycmFpbihwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICB2YXIgX21hcnRpbmk7CgogICAgdmFyIGltYWdlRGF0YSA9IHBhcmFtZXRlcnMuaW1hZ2VEYXRhLAogICAgICAgIF9wYXJhbWV0ZXJzJHRpbGVTaXplID0gcGFyYW1ldGVycy50aWxlU2l6ZSwKICAgICAgICB0aWxlU2l6ZSA9IF9wYXJhbWV0ZXJzJHRpbGVTaXplID09PSB2b2lkIDAgPyAyNTYgOiBfcGFyYW1ldGVycyR0aWxlU2l6ZSwKICAgICAgICBlcnJvckxldmVsID0gcGFyYW1ldGVycy5lcnJvckxldmVsOwogICAgdmFyIHBpeGVscyA9IG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoaW1hZ2VEYXRhKSwgW3RpbGVTaXplLCB0aWxlU2l6ZSwgNF0sIFs0LCA0ICogdGlsZVNpemUsIDFdLCAwKTsgLy8gVGlsZSBzaXplIG11c3QgYmUgbWFpbnRhaW5lZCB0aHJvdWdoIHRoZSBsaWZlIG9mIHRoZSB3b3JrZXIKCiAgICAoX21hcnRpbmkgPSBtYXJ0aW5pKSAhPT0gbnVsbCAmJiBfbWFydGluaSAhPT0gdm9pZCAwID8gX21hcnRpbmkgOiBtYXJ0aW5pID0gbmV3IE1hcnRpbmkodGlsZVNpemUgKyAxKTsKICAgIHZhciB0ZXJyYWluID0gbWFwYm94VGVycmFpblRvR3JpZChwaXhlbHMpOwogICAgdmFyIHRpbGUgPSBtYXJ0aW5pLmNyZWF0ZVRpbGUodGVycmFpbik7IC8vIGdldCBhIG1lc2ggKHZlcnRpY2VzIGFuZCB0cmlhbmdsZXMgaW5kaWNlcykgZm9yIGEgMTBtIGVycm9yCgogICAgdmFyIG1lc2ggPSB0aWxlLmdldE1lc2goZXJyb3JMZXZlbCwgcGFyYW1ldGVycy5tYXhMZW5ndGgpOwogICAgcmV0dXJuIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplKTsKICB9CgogIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKG1zZykgewogICAgdmFyIF9tc2ckZGF0YSA9IG1zZy5kYXRhLAogICAgICAgIGlkID0gX21zZyRkYXRhLmlkLAogICAgICAgIHBheWxvYWQgPSBfbXNnJGRhdGEucGF5bG9hZDsKICAgIGlmIChpZCA9PSBudWxsKSByZXR1cm47CiAgICB2YXIgb2JqZWN0cyA9IFtdOwogICAgdmFyIHJlcyA9IG51bGw7CgogICAgdHJ5IHsKICAgICAgcmVzID0gZGVjb2RlVGVycmFpbihwYXlsb2FkKTsKICAgICAgb2JqZWN0cy5wdXNoKHJlcy5pbmRpY2VzLmJ1ZmZlcik7CiAgICAgIG9iamVjdHMucHVzaChyZXMucXVhbnRpemVkVmVydGljZXMuYnVmZmVyKTsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIHBheWxvYWQ6IHJlcwogICAgICB9LCBvYmplY3RzKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogaWQsCiAgICAgICAgZXJyOiBlcnIudG9TdHJpbmcoKQogICAgICB9KTsKICAgIH0gZmluYWxseSB7CiAgICAgIHJlcyA9IG51bGw7CiAgICAgIG9iamVjdHMgPSBudWxsOwogICAgfQogIH07CgogIGV4cG9ydHMuZGVjb2RlVGVycmFpbiA9IGRlY29kZVRlcnJhaW47CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7CgogIHJldHVybiBleHBvcnRzOwoKfSh7fSkpOwoK', null, false);
|
|
480
|
+
var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQoKICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkoYXJyKTsKICB9CgogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikgewogICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICJ1bmRlZmluZWQiICYmIGl0ZXJbU3ltYm9sLml0ZXJhdG9yXSAhPSBudWxsIHx8IGl0ZXJbIkBAaXRlcmF0b3IiXSAhPSBudWxsKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTsKICB9CgogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsKICAgIGlmICghbykgcmV0dXJuOwogICAgaWYgKHR5cGVvZiBvID09PSAic3RyaW5nIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7CiAgICB2YXIgbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKS5zbGljZSg4LCAtMSk7CiAgICBpZiAobiA9PT0gIk9iamVjdCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsKICAgIGlmIChuID09PSAiTWFwIiB8fCBuID09PSAiU2V0IikgcmV0dXJuIEFycmF5LmZyb20obyk7CiAgICBpZiAobiA9PT0gIkFyZ3VtZW50cyIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOwogIH0KCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHsKICAgIGlmIChsZW4gPT0gbnVsbCB8fCBsZW4gPiBhcnIubGVuZ3RoKSBsZW4gPSBhcnIubGVuZ3RoOwoKICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTsKCiAgICByZXR1cm4gYXJyMjsKICB9CgogIGZ1bmN0aW9uIF9ub25JdGVyYWJsZVNwcmVhZCgpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlLlxuSW4gb3JkZXIgdG8gYmUgaXRlcmFibGUsIG5vbi1hcnJheSBvYmplY3RzIG11c3QgaGF2ZSBhIFtTeW1ib2wuaXRlcmF0b3JdKCkgbWV0aG9kLiIpOwogIH0KCiAgLy8gV2Ugc2hvdWxkIHNhdmUgdGhlc2UKICAvL2NvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoMjU2LCAyNTYpOwogIC8vY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgZnVuY3Rpb24gbWFwYm94VGVycmFpblRvR3JpZChwbmcsIGludGVydmFsLCBvZmZzZXQpIHsKICAgIHZhciBfaW50ZXJ2YWwsIF9vZmZzZXQ7CgogICAgLy8gbWF5YmUgd2Ugc2hvdWxkIGRvIHRoaXMgb24gdGhlIEdQVSB1c2luZyBSRUdMPwogICAgLy8gYnV0IHRoYXQgd291bGQgcmVxdWlyZSBHUFUgLT4gQ1BVIC0+IEdQVQogICAgdmFyIGdyaWRTaXplID0gcG5nLnNoYXBlWzBdICsgMTsKICAgIHZhciB0ZXJyYWluID0gbmV3IEZsb2F0MzJBcnJheShncmlkU2l6ZSAqIGdyaWRTaXplKTsKICAgIHZhciB0aWxlU2l6ZSA9IHBuZy5zaGFwZVswXTsKICAgIGludGVydmFsID0gKF9pbnRlcnZhbCA9IGludGVydmFsKSAhPT0gbnVsbCAmJiBfaW50ZXJ2YWwgIT09IHZvaWQgMCA/IF9pbnRlcnZhbCA6IDAuMTsKICAgIG9mZnNldCA9IChfb2Zmc2V0ID0gb2Zmc2V0KSAhPT0gbnVsbCAmJiBfb2Zmc2V0ICE9PSB2b2lkIDAgPyBfb2Zmc2V0IDogLTEwMDAwOyAvLyBkZWNvZGUgdGVycmFpbiB2YWx1ZXMKCiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHRpbGVTaXplOyB5KyspIHsKICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCB0aWxlU2l6ZTsgeCsrKSB7CiAgICAgICAgdmFyIHljID0geTsKICAgICAgICB2YXIgciA9IHBuZy5nZXQoeCwgeWMsIDApOwogICAgICAgIHZhciBnID0gcG5nLmdldCh4LCB5YywgMSk7CiAgICAgICAgdmFyIGIgPSBwbmcuZ2V0KHgsIHljLCAyKTsKICAgICAgICB0ZXJyYWluW3kgKiBncmlkU2l6ZSArIHhdID0gciAqIDI1NiAqIDI1NiAqIGludGVydmFsICsgZyAqIDI1Ni4wICogaW50ZXJ2YWwgKyBiICogaW50ZXJ2YWwgKyBvZmZzZXQ7CiAgICAgIH0KICAgIH0gLy8gYmFja2ZpbGwgcmlnaHQgYW5kIGJvdHRvbSBib3JkZXJzCgoKICAgIGZvciAodmFyIF94ID0gMDsgX3ggPCBncmlkU2l6ZSAtIDE7IF94KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDEpICsgX3hdID0gdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDIpICsgX3hdOwogICAgfQoKICAgIGZvciAodmFyIF95ID0gMDsgX3kgPCBncmlkU2l6ZTsgX3krKykgewogICAgICB0ZXJyYWluW2dyaWRTaXplICogX3kgKyBncmlkU2l6ZSAtIDFdID0gdGVycmFpbltncmlkU2l6ZSAqIF95ICsgZ3JpZFNpemUgLSAyXTsKICAgIH0KCiAgICByZXR1cm4gdGVycmFpbjsKICB9CgogIGZ1bmN0aW9uIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplKSB7CiAgICB2YXIgeHZhbHMgPSBbXTsKICAgIHZhciB5dmFscyA9IFtdOwogICAgdmFyIGhlaWdodE1ldGVycyA9IFtdOwogICAgdmFyIG5vcnRoSW5kaWNlcyA9IFtdOwogICAgdmFyIHNvdXRoSW5kaWNlcyA9IFtdOwogICAgdmFyIGVhc3RJbmRpY2VzID0gW107CiAgICB2YXIgd2VzdEluZGljZXMgPSBbXTsKICAgIHZhciBtaW5pbXVtSGVpZ2h0ID0gSW5maW5pdHk7CiAgICB2YXIgbWF4aW11bUhlaWdodCA9IC1JbmZpbml0eTsKICAgIHZhciBzY2FsYXIgPSAzMjc2OC4wIC8gdGlsZVNpemU7CgogICAgZm9yICh2YXIgaXggPSAwOyBpeCA8IG1lc2gudmVydGljZXMubGVuZ3RoIC8gMjsgaXgrKykgewogICAgICB2YXIgdmVydGV4SXggPSBpeDsKICAgICAgdmFyIHB4ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDJdOwogICAgICB2YXIgcHkgPSBtZXNoLnZlcnRpY2VzW2l4ICogMiArIDFdOwogICAgICB2YXIgaGVpZ2h0ID0gdGlsZS50ZXJyYWluW3B5ICogKHRpbGVTaXplICsgMSkgKyBweF07CiAgICAgIGlmIChoZWlnaHQgPiBtYXhpbXVtSGVpZ2h0KSBtYXhpbXVtSGVpZ2h0ID0gaGVpZ2h0OwogICAgICBpZiAoaGVpZ2h0IDwgbWluaW11bUhlaWdodCkgbWluaW11bUhlaWdodCA9IGhlaWdodDsKICAgICAgaGVpZ2h0TWV0ZXJzLnB1c2goaGVpZ2h0KTsKICAgICAgaWYgKHB5ID09IDApIG5vcnRoSW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB5ID09IHRpbGVTaXplKSBzb3V0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSAwKSB3ZXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB4ID09IHRpbGVTaXplKSBlYXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgdmFyIHh2ID0gcHggKiBzY2FsYXI7CiAgICAgIHZhciB5diA9ICh0aWxlU2l6ZSAtIHB5KSAqIHNjYWxhcjsKICAgICAgeHZhbHMucHVzaCh4dik7CiAgICAgIHl2YWxzLnB1c2goeXYpOwogICAgfQoKICAgIHZhciBoZWlnaHRSYW5nZSA9IG1heGltdW1IZWlnaHQgLSBtaW5pbXVtSGVpZ2h0OwogICAgdmFyIGhlaWdodHMgPSBoZWlnaHRNZXRlcnMubWFwKGZ1bmN0aW9uIChkKSB7CiAgICAgIGlmIChoZWlnaHRSYW5nZSA8IDEpIHJldHVybiAwOwogICAgICByZXR1cm4gKGQgLSBtaW5pbXVtSGVpZ2h0KSAqICgzMjc2Ny4wIC8gaGVpZ2h0UmFuZ2UpOwogICAgfSk7CiAgICB2YXIgdHJpYW5nbGVzID0gbmV3IFVpbnQxNkFycmF5KG1lc2gudHJpYW5nbGVzKTsKICAgIHZhciBxdWFudGl6ZWRWZXJ0aWNlcyA9IG5ldyBVaW50MTZBcnJheSggLy92ZXJ0cwogICAgW10uY29uY2F0KHh2YWxzLCB5dmFscywgX3RvQ29uc3VtYWJsZUFycmF5KGhlaWdodHMpKSk7IC8vIFNFIE5XIE5FCiAgICAvLyBORSBOVyBTRQoKICAgIHJldHVybiB7CiAgICAgIG1pbmltdW1IZWlnaHQ6IG1pbmltdW1IZWlnaHQsCiAgICAgIG1heGltdW1IZWlnaHQ6IG1heGltdW1IZWlnaHQsCiAgICAgIHF1YW50aXplZFZlcnRpY2VzOiBxdWFudGl6ZWRWZXJ0aWNlcywKICAgICAgaW5kaWNlczogdHJpYW5nbGVzLAogICAgICB3ZXN0SW5kaWNlczogd2VzdEluZGljZXMsCiAgICAgIHNvdXRoSW5kaWNlczogc291dGhJbmRpY2VzLAogICAgICBlYXN0SW5kaWNlczogZWFzdEluZGljZXMsCiAgICAgIG5vcnRoSW5kaWNlczogbm9ydGhJbmRpY2VzCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gaW90YShuKSB7CiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG4pOwogICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7CiAgICAgIHJlc3VsdFtpXSA9IGk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0CiAgfQoKICB2YXIgaW90YV8xID0gaW90YTsKCiAgLyohCiAgICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlcgogICAqCiAgICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz4KICAgKiBAbGljZW5zZSAgTUlUCiAgICovCiAgLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZwogIC8vIE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkKICB2YXIgaXNCdWZmZXJfMSA9IGZ1bmN0aW9uIChvYmopIHsKICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpCiAgfTsKCiAgZnVuY3Rpb24gaXNCdWZmZXIgKG9iaikgewogICAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iaikKICB9CgogIC8vIEZvciBOb2RlIHYwLjEwIHN1cHBvcnQuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkuCiAgZnVuY3Rpb24gaXNTbG93QnVmZmVyIChvYmopIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKQogIH0KCiAgdmFyIGhhc1R5cGVkQXJyYXlzICA9ICgodHlwZW9mIEZsb2F0NjRBcnJheSkgIT09ICJ1bmRlZmluZWQiKTsKCiAgZnVuY3Rpb24gY29tcGFyZTFzdChhLCBiKSB7CiAgICByZXR1cm4gYVswXSAtIGJbMF0KICB9CgogIGZ1bmN0aW9uIG9yZGVyKCkgewogICAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlOwogICAgdmFyIHRlcm1zID0gbmV3IEFycmF5KHN0cmlkZS5sZW5ndGgpOwogICAgdmFyIGk7CiAgICBmb3IoaT0wOyBpPHRlcm1zLmxlbmd0aDsgKytpKSB7CiAgICAgIHRlcm1zW2ldID0gW01hdGguYWJzKHN0cmlkZVtpXSksIGldOwogICAgfQogICAgdGVybXMuc29ydChjb21wYXJlMXN0KTsKICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodGVybXMubGVuZ3RoKTsKICAgIGZvcihpPTA7IGk8cmVzdWx0Lmxlbmd0aDsgKytpKSB7CiAgICAgIHJlc3VsdFtpXSA9IHRlcm1zW2ldWzFdOwogICAgfQogICAgcmV0dXJuIHJlc3VsdAogIH0KCiAgZnVuY3Rpb24gY29tcGlsZUNvbnN0cnVjdG9yKGR0eXBlLCBkaW1lbnNpb24pIHsKICAgIHZhciBjbGFzc05hbWUgPSBbIlZpZXciLCBkaW1lbnNpb24sICJkIiwgZHR5cGVdLmpvaW4oIiIpOwogICAgaWYoZGltZW5zaW9uIDwgMCkgewogICAgICBjbGFzc05hbWUgPSAiVmlld19OaWwiICsgZHR5cGU7CiAgICB9CiAgICB2YXIgdXNlR2V0dGVycyA9IChkdHlwZSA9PT0gImdlbmVyaWMiKTsKCiAgICBpZihkaW1lbnNpb24gPT09IC0xKSB7CiAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciB0cml2aWFsIGFycmF5cwogICAgICB2YXIgY29kZSA9CiAgICAgICAgImZ1bmN0aW9uICIrY2xhc3NOYW1lKyIoYSl7dGhpcy5kYXRhPWE7fTtcCnZhciBwcm90bz0iK2NsYXNzTmFtZSsiLnByb3RvdHlwZTtcCnByb3RvLmR0eXBlPSciK2R0eXBlKyInO1wKcHJvdG8uaW5kZXg9ZnVuY3Rpb24oKXtyZXR1cm4gLTF9O1wKcHJvdG8uc2l6ZT0wO1wKcHJvdG8uZGltZW5zaW9uPS0xO1wKcHJvdG8uc2hhcGU9cHJvdG8uc3RyaWRlPXByb3RvLm9yZGVyPVtdO1wKcHJvdG8ubG89cHJvdG8uaGk9cHJvdG8udHJhbnNwb3NlPXByb3RvLnN0ZXA9XApmdW5jdGlvbigpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEpO307XApwcm90by5nZXQ9cHJvdG8uc2V0PWZ1bmN0aW9uKCl7fTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07XApyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIrY2xhc3NOYW1lKyIoYSl7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKGEpO30iOwogICAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKGNvZGUpOwogICAgICByZXR1cm4gcHJvY2VkdXJlKCkKICAgIH0gZWxzZSBpZihkaW1lbnNpb24gPT09IDApIHsKICAgICAgLy9TcGVjaWFsIGNhc2UgZm9yIDBkIGFycmF5cwogICAgICB2YXIgY29kZSA9CiAgICAgICAgImZ1bmN0aW9uICIrY2xhc3NOYW1lKyIoYSxkKSB7XAp0aGlzLmRhdGEgPSBhO1wKdGhpcy5vZmZzZXQgPSBkXAp9O1wKdmFyIHByb3RvPSIrY2xhc3NOYW1lKyIucHJvdG90eXBlO1wKcHJvdG8uZHR5cGU9JyIrZHR5cGUrIic7XApwcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm9mZnNldH07XApwcm90by5kaW1lbnNpb249MDtcCnByb3RvLnNpemU9MTtcCnByb3RvLnNoYXBlPVwKcHJvdG8uc3RyaWRlPVwKcHJvdG8ub3JkZXI9W107XApwcm90by5sbz1cCnByb3RvLmhpPVwKcHJvdG8udHJhbnNwb3NlPVwKcHJvdG8uc3RlcD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2NvcHkoKSB7XApyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLHRoaXMub2Zmc2V0KVwKfTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9waWNrKCl7XApyZXR1cm4gVHJpdmlhbEFycmF5KHRoaXMuZGF0YSk7XAp9O1wKcHJvdG8udmFsdWVPZj1wcm90by5nZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9nZXQoKXtcCnJldHVybiAiKyh1c2VHZXR0ZXJzID8gInRoaXMuZGF0YS5nZXQodGhpcy5vZmZzZXQpIiA6ICJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdIikrCiAgIn07XApwcm90by5zZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9zZXQodil7XApyZXR1cm4gIisodXNlR2V0dGVycyA/ICJ0aGlzLmRhdGEuc2V0KHRoaXMub2Zmc2V0LHYpIiA6ICJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdPXYiKSsiXAp9O1wKcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF8iK2NsYXNzTmFtZSsiKGEsYixjLGQpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIihhLGQpfSI7CiAgICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oIlRyaXZpYWxBcnJheSIsIGNvZGUpOwogICAgICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdWzBdKQogICAgfQoKICAgIHZhciBjb2RlID0gWyIndXNlIHN0cmljdCciXTsKCiAgICAvL0NyZWF0ZSBjb25zdHJ1Y3RvciBmb3IgdmlldwogICAgdmFyIGluZGljZXMgPSBpb3RhXzEoZGltZW5zaW9uKTsKICAgIHZhciBhcmdzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gImkiK2kgfSk7CiAgICB2YXIgaW5kZXhfc3RyID0gInRoaXMub2Zmc2V0KyIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgICByZXR1cm4gInRoaXMuc3RyaWRlWyIgKyBpICsgIl0qaSIgKyBpCiAgICAgICAgfSkuam9pbigiKyIpOwogICAgdmFyIHNoYXBlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYiIraQogICAgICB9KS5qb2luKCIsIik7CiAgICB2YXIgc3RyaWRlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYyIraQogICAgICB9KS5qb2luKCIsIik7CiAgICBjb2RlLnB1c2goCiAgICAgICJmdW5jdGlvbiAiK2NsYXNzTmFtZSsiKGEsIiArIHNoYXBlQXJnICsgIiwiICsgc3RyaWRlQXJnICsgIixkKXt0aGlzLmRhdGE9YSIsCiAgICAgICAgInRoaXMuc2hhcGU9WyIgKyBzaGFwZUFyZyArICJdIiwKICAgICAgICAidGhpcy5zdHJpZGU9WyIgKyBzdHJpZGVBcmcgKyAiXSIsCiAgICAgICAgInRoaXMub2Zmc2V0PWR8MH0iLAogICAgICAidmFyIHByb3RvPSIrY2xhc3NOYW1lKyIucHJvdG90eXBlIiwKICAgICAgInByb3RvLmR0eXBlPSciK2R0eXBlKyInIiwKICAgICAgInByb3RvLmRpbWVuc2lvbj0iK2RpbWVuc2lvbik7CgogICAgLy92aWV3LnNpemU6CiAgICBjb2RlLnB1c2goIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnc2l6ZScse2dldDpmdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3NpemUoKXtcCnJldHVybiAiK2luZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuICJ0aGlzLnNoYXBlWyIraSsiXSIgfSkuam9pbigiKiIpLAogICJ9fSkiKTsKCiAgICAvL3ZpZXcub3JkZXI6CiAgICBpZihkaW1lbnNpb24gPT09IDEpIHsKICAgICAgY29kZS5wdXNoKCJwcm90by5vcmRlcj1bMF0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdvcmRlcicse2dldDoiKTsKICAgICAgaWYoZGltZW5zaW9uIDwgNCkgewogICAgICAgIGNvZGUucHVzaCgiZnVuY3Rpb24gIitjbGFzc05hbWUrIl9vcmRlcigpeyIpOwogICAgICAgIGlmKGRpbWVuc2lvbiA9PT0gMikgewogICAgICAgICAgY29kZS5wdXNoKCJyZXR1cm4gKE1hdGguYWJzKHRoaXMuc3RyaWRlWzBdKT5NYXRoLmFicyh0aGlzLnN0cmlkZVsxXSkpP1sxLDBdOlswLDFdfX0pIik7CiAgICAgICAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMykgewogICAgICAgICAgY29kZS5wdXNoKAogICJ2YXIgczA9TWF0aC5hYnModGhpcy5zdHJpZGVbMF0pLHMxPU1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSxzMj1NYXRoLmFicyh0aGlzLnN0cmlkZVsyXSk7XAppZihzMD5zMSl7XAppZihzMT5zMil7XApyZXR1cm4gWzIsMSwwXTtcCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMSwyLDBdO1wKfWVsc2V7XApyZXR1cm4gWzEsMCwyXTtcCn1cCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMiwwLDFdO1wKfWVsc2UgaWYoczI+czEpe1wKcmV0dXJuIFswLDEsMl07XAp9ZWxzZXtcCnJldHVybiBbMCwyLDFdO1wKfX19KSIpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb2RlLnB1c2goIk9SREVSfSkiKTsKICAgICAgfQogICAgfQoKICAgIC8vdmlldy5zZXQoaTAsIC4uLiwgdik6CiAgICBjb2RlLnB1c2goCiAgInByb3RvLnNldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3NldCgiK2FyZ3Muam9pbigiLCIpKyIsdil7Iik7CiAgICBpZih1c2VHZXR0ZXJzKSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YS5zZXQoIitpbmRleF9zdHIrIix2KX0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YVsiK2luZGV4X3N0cisiXT12fSIpOwogICAgfQoKICAgIC8vdmlldy5nZXQoaTAsIC4uLik6CiAgICBjb2RlLnB1c2goInByb3RvLmdldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2dldCgiK2FyZ3Muam9pbigiLCIpKyIpeyIpOwogICAgaWYodXNlR2V0dGVycykgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGEuZ2V0KCIraW5kZXhfc3RyKyIpfSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhWyIraW5kZXhfc3RyKyJdfSIpOwogICAgfQoKICAgIC8vdmlldy5pbmRleDoKICAgIGNvZGUucHVzaCgKICAgICAgInByb3RvLmluZGV4PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfaW5kZXgoIiwgYXJncy5qb2luKCksICIpe3JldHVybiAiK2luZGV4X3N0cisifSIpOwoKICAgIC8vdmlldy5oaSgpOgogICAgY29kZS5wdXNoKCJwcm90by5oaT1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2hpKCIrYXJncy5qb2luKCIsIikrIil7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuIFsiKHR5cGVvZiBpIixpLCIhPT0nbnVtYmVyJ3x8aSIsaSwiPDApP3RoaXMuc2hhcGVbIiwgaSwgIl06aSIsIGksInwwIl0uam9pbigiIikKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAidGhpcy5zdHJpZGVbIitpICsgIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLHRoaXMub2Zmc2V0KX0iKTsKCiAgICAvL3ZpZXcubG8oKToKICAgIHZhciBhX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAiYSIraSsiPXRoaXMuc2hhcGVbIitpKyJdIiB9KTsKICAgIHZhciBjX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAiYyIraSsiPXRoaXMuc3RyaWRlWyIraSsiXSIgfSk7CiAgICBjb2RlLnB1c2goInByb3RvLmxvPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfbG8oIithcmdzLmpvaW4oIiwiKSsiKXt2YXIgYj10aGlzLm9mZnNldCxkPTAsIithX3ZhcnMuam9pbigiLCIpKyIsIitjX3ZhcnMuam9pbigiLCIpKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgKICAiaWYodHlwZW9mIGkiK2krIj09PSdudW1iZXInJiZpIitpKyI+PTApe1wKZD1pIitpKyJ8MDtcCmIrPWMiK2krIipkO1wKYSIraSsiLT1kfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImEiK2kKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYyIraQogICAgICB9KS5qb2luKCIsIikrIixiKX0iKTsKCiAgICAvL3ZpZXcuc3RlcCgpOgogICAgY29kZS5wdXNoKCJwcm90by5zdGVwPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfc3RlcCgiK2FyZ3Muam9pbigiLCIpKyIpe3ZhciAiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJhIitpKyI9dGhpcy5zaGFwZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImIiK2krIj10aGlzLnN0cmlkZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLGM9dGhpcy5vZmZzZXQsZD0wLGNlaWw9TWF0aC5jZWlsIik7CiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goCiAgImlmKHR5cGVvZiBpIitpKyI9PT0nbnVtYmVyJyl7XApkPWkiK2krInwwO1wKaWYoZDwwKXtcCmMrPWIiK2krIiooYSIraSsiLTEpO1wKYSIraSsiPWNlaWwoLWEiK2krIi9kKVwKfWVsc2V7XAphIitpKyI9Y2VpbChhIitpKyIvZClcCn1cCmIiK2krIio9ZFwKfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImEiICsgaQogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJiIiArIGkKICAgICAgfSkuam9pbigiLCIpKyIsYyl9Iik7CgogICAgLy92aWV3LnRyYW5zcG9zZSgpOgogICAgdmFyIHRTaGFwZSA9IG5ldyBBcnJheShkaW1lbnNpb24pOwogICAgdmFyIHRTdHJpZGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIHRTaGFwZVtpXSA9ICJhW2kiK2krIl0iOwogICAgICB0U3RyaWRlW2ldID0gImJbaSIraSsiXSI7CiAgICB9CiAgICBjb2RlLnB1c2goInByb3RvLnRyYW5zcG9zZT1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3RyYW5zcG9zZSgiK2FyZ3MrIil7IisKICAgICAgYXJncy5tYXAoZnVuY3Rpb24obixpZHgpIHsgcmV0dXJuIG4gKyAiPSgiICsgbiArICI9PT11bmRlZmluZWQ/IiArIGlkeCArICI6IiArIG4gKyAifDApIn0pLmpvaW4oIjsiKSwKICAgICAgInZhciBhPXRoaXMuc2hhcGUsYj10aGlzLnN0cmlkZTtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrdFNoYXBlLmpvaW4oIiwiKSsiLCIrdFN0cmlkZS5qb2luKCIsIikrIix0aGlzLm9mZnNldCl9Iik7CgogICAgLy92aWV3LnBpY2soKToKICAgIGNvZGUucHVzaCgicHJvdG8ucGljaz1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3BpY2soIithcmdzKyIpe3ZhciBhPVtdLGI9W10sYz10aGlzLm9mZnNldCIpOwogICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKCJpZih0eXBlb2YgaSIraSsiPT09J251bWJlcicmJmkiK2krIj49MCl7Yz0oYyt0aGlzLnN0cmlkZVsiK2krIl0qaSIraSsiKXwwfWVsc2V7YS5wdXNoKHRoaXMuc2hhcGVbIitpKyJdKTtiLnB1c2godGhpcy5zdHJpZGVbIitpKyJdKX0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgidmFyIGN0b3I9Q1RPUl9MSVNUW2EubGVuZ3RoKzFdO3JldHVybiBjdG9yKHRoaXMuZGF0YSxhLGIsYyl9Iik7CgogICAgLy9BZGQgcmV0dXJuIHN0YXRlbWVudAogICAgY29kZS5wdXNoKCJyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIrY2xhc3NOYW1lKyIoZGF0YSxzaGFwZSxzdHJpZGUsb2Zmc2V0KXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIoZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJzaGFwZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gInN0cmlkZVsiK2krIl0iCiAgICAgIH0pLmpvaW4oIiwiKSsiLG9mZnNldCl9Iik7CgogICAgLy9Db21waWxlIHByb2NlZHVyZQogICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbigiQ1RPUl9MSVNUIiwgIk9SREVSIiwgY29kZS5qb2luKCJcbiIpKTsKICAgIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV0sIG9yZGVyKQogIH0KCiAgZnVuY3Rpb24gYXJyYXlEVHlwZShkYXRhKSB7CiAgICBpZihpc0J1ZmZlcl8xKGRhdGEpKSB7CiAgICAgIHJldHVybiAiYnVmZmVyIgogICAgfQogICAgaWYoaGFzVHlwZWRBcnJheXMpIHsKICAgICAgc3dpdGNoKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSkgewogICAgICAgIGNhc2UgIltvYmplY3QgRmxvYXQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImZsb2F0NjQiCiAgICAgICAgY2FzZSAiW29iamVjdCBGbG9hdDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAiZmxvYXQzMiIKICAgICAgICBjYXNlICJbb2JqZWN0IEludDhBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQ4IgogICAgICAgIGNhc2UgIltvYmplY3QgSW50MTZBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQxNiIKICAgICAgICBjYXNlICJbb2JqZWN0IEludDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAiaW50MzIiCiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50OEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQ4IgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDE2QXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDE2IgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDMyQXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDMyIgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDhDbGFtcGVkQXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDhfY2xhbXBlZCIKICAgICAgICBjYXNlICJbb2JqZWN0IEJpZ0ludDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiYmlnaW50NjQiCiAgICAgICAgY2FzZSAiW29iamVjdCBCaWdVaW50NjRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJiaWd1aW50NjQiCiAgICAgIH0KICAgIH0KICAgIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHsKICAgICAgcmV0dXJuICJhcnJheSIKICAgIH0KICAgIHJldHVybiAiZ2VuZXJpYyIKICB9CgogIHZhciBDQUNIRURfQ09OU1RSVUNUT1JTID0gewogICAgImZsb2F0MzIiOltdLAogICAgImZsb2F0NjQiOltdLAogICAgImludDgiOltdLAogICAgImludDE2IjpbXSwKICAgICJpbnQzMiI6W10sCiAgICAidWludDgiOltdLAogICAgInVpbnQxNiI6W10sCiAgICAidWludDMyIjpbXSwKICAgICJhcnJheSI6W10sCiAgICAidWludDhfY2xhbXBlZCI6W10sCiAgICAiYmlnaW50NjQiOiBbXSwKICAgICJiaWd1aW50NjQiOiBbXSwKICAgICJidWZmZXIiOltdLAogICAgImdlbmVyaWMiOltdCiAgfQoKICA7CiAgZnVuY3Rpb24gd3JhcHBlZE5EQXJyYXlDdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkgewogICAgaWYoZGF0YSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhciBjdG9yID0gQ0FDSEVEX0NPTlNUUlVDVE9SUy5hcnJheVswXTsKICAgICAgcmV0dXJuIGN0b3IoW10pCiAgICB9IGVsc2UgaWYodHlwZW9mIGRhdGEgPT09ICJudW1iZXIiKSB7CiAgICAgIGRhdGEgPSBbZGF0YV07CiAgICB9CiAgICBpZihzaGFwZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHNoYXBlID0gWyBkYXRhLmxlbmd0aCBdOwogICAgfQogICAgdmFyIGQgPSBzaGFwZS5sZW5ndGg7CiAgICBpZihzdHJpZGUgPT09IHVuZGVmaW5lZCkgewogICAgICBzdHJpZGUgPSBuZXcgQXJyYXkoZCk7CiAgICAgIGZvcih2YXIgaT1kLTEsIHN6PTE7IGk+PTA7IC0taSkgewogICAgICAgIHN0cmlkZVtpXSA9IHN6OwogICAgICAgIHN6ICo9IHNoYXBlW2ldOwogICAgICB9CiAgICB9CiAgICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkgewogICAgICBvZmZzZXQgPSAwOwogICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHsKICAgICAgICBpZihzdHJpZGVbaV0gPCAwKSB7CiAgICAgICAgICBvZmZzZXQgLT0gKHNoYXBlW2ldLTEpKnN0cmlkZVtpXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZhciBkdHlwZSA9IGFycmF5RFR5cGUoZGF0YSk7CiAgICB2YXIgY3Rvcl9saXN0ID0gQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV07CiAgICB3aGlsZShjdG9yX2xpc3QubGVuZ3RoIDw9IGQrMSkgewogICAgICBjdG9yX2xpc3QucHVzaChjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGN0b3JfbGlzdC5sZW5ndGgtMSkpOwogICAgfQogICAgdmFyIGN0b3IgPSBjdG9yX2xpc3RbZCsxXTsKICAgIHJldHVybiBjdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkKICB9CgogIHZhciBuZGFycmF5ID0gd3JhcHBlZE5EQXJyYXlDdG9yOwoKICBjbGFzcyBNYXJ0aW5pIHsKICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgIGlmICh0aWxlU2l6ZSAmIHRpbGVTaXplIC0gMSkgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBncmlkIHNpemUgdG8gYmUgMl5uKzEsIGdvdCAke2dyaWRTaXplfS5gKTsKICAgICAgdGhpcy5udW1UcmlhbmdsZXMgPSB0aWxlU2l6ZSAqIHRpbGVTaXplICogMiAtIDI7CiAgICAgIHRoaXMubnVtUGFyZW50VHJpYW5nbGVzID0gdGhpcy5udW1UcmlhbmdsZXMgLSB0aWxlU2l6ZSAqIHRpbGVTaXplOwogICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOyAvLyBjb29yZGluYXRlcyBmb3IgYWxsIHBvc3NpYmxlIHRyaWFuZ2xlcyBpbiBhbiBSVElOIHRpbGUKCiAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7IC8vIGdldCB0cmlhbmdsZSBjb29yZGluYXRlcyBmcm9tIGl0cyBpbmRleCBpbiBhbiBpbXBsaWNpdCBiaW5hcnkgdHJlZQoKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgbGV0IGlkID0gaSArIDI7CiAgICAgICAgbGV0IGF4ID0gMCwKICAgICAgICAgICAgYXkgPSAwLAogICAgICAgICAgICBieCA9IDAsCiAgICAgICAgICAgIGJ5ID0gMCwKICAgICAgICAgICAgY3ggPSAwLAogICAgICAgICAgICBjeSA9IDA7CgogICAgICAgIGlmIChpZCAmIDEpIHsKICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgfQoKICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CgogICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAvLyBsZWZ0IGhhbGYKICAgICAgICAgICAgYnggPSBheDsKICAgICAgICAgICAgYnkgPSBheTsKICAgICAgICAgICAgYXggPSBjeDsKICAgICAgICAgICAgYXkgPSBjeTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIHJpZ2h0IGhhbGYKICAgICAgICAgICAgYXggPSBieDsKICAgICAgICAgICAgYXkgPSBieTsKICAgICAgICAgICAgYnggPSBjeDsKICAgICAgICAgICAgYnkgPSBjeTsKICAgICAgICAgIH0KCiAgICAgICAgICBjeCA9IG14OwogICAgICAgICAgY3kgPSBteTsKICAgICAgICB9CgogICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMF0gPSBheDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMl0gPSBieDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgM10gPSBieTsKICAgICAgfQogICAgfQoKICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICB9CgogIH0KCiAgY2xhc3MgVGlsZSB7CiAgICBjb25zdHJ1Y3Rvcih0ZXJyYWluLCBtYXJ0aW5pKSB7CiAgICAgIGNvbnN0IHNpemUgPSBtYXJ0aW5pLmdyaWRTaXplOwogICAgICBpZiAodGVycmFpbi5sZW5ndGggIT09IHNpemUgKiBzaXplKSB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHRlcnJhaW4gZGF0YSBvZiBsZW5ndGggJHtzaXplICogc2l6ZX0gKCR7c2l6ZX0geCAke3NpemV9KSwgZ290ICR7dGVycmFpbi5sZW5ndGh9LmApOwogICAgICB0aGlzLnRlcnJhaW4gPSB0ZXJyYWluOwogICAgICB0aGlzLm1hcnRpbmkgPSBtYXJ0aW5pOwogICAgICB0aGlzLmVycm9ycyA9IG5ldyBGbG9hdDMyQXJyYXkodGVycmFpbi5sZW5ndGgpOwogICAgICB0aGlzLnVwZGF0ZSgpOwogICAgfQoKICAgIHVwZGF0ZSgpIHsKICAgICAgY29uc3QgewogICAgICAgIG51bVRyaWFuZ2xlcywKICAgICAgICBudW1QYXJlbnRUcmlhbmdsZXMsCiAgICAgICAgY29vcmRzLAogICAgICAgIGdyaWRTaXplOiBzaXplCiAgICAgIH0gPSB0aGlzLm1hcnRpbmk7CiAgICAgIGNvbnN0IHsKICAgICAgICB0ZXJyYWluLAogICAgICAgIGVycm9ycwogICAgICB9ID0gdGhpczsgLy8gaXRlcmF0ZSBvdmVyIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMsIHN0YXJ0aW5nIGZyb20gdGhlIHNtYWxsZXN0IGxldmVsCgogICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICBjb25zdCBrID0gaSAqIDQ7CiAgICAgICAgY29uc3QgYXggPSBjb29yZHNbayArIDBdOwogICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICBjb25zdCBieCA9IGNvb3Jkc1trICsgMl07CiAgICAgICAgY29uc3QgYnkgPSBjb29yZHNbayArIDNdOwogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGN4ID0gbXggKyBteSAtIGF5OwogICAgICAgIGNvbnN0IGN5ID0gbXkgKyBheCAtIG14OyAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQoKICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWRIZWlnaHQgPSAodGVycmFpbltheSAqIHNpemUgKyBheF0gKyB0ZXJyYWluW2J5ICogc2l6ZSArIGJ4XSkgLyAyOwogICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgY29uc3QgbWlkZGxlRXJyb3IgPSBNYXRoLmFicyhpbnRlcnBvbGF0ZWRIZWlnaHQgLSB0ZXJyYWluW21pZGRsZUluZGV4XSk7CiAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIG1pZGRsZUVycm9yKTsKCiAgICAgICAgaWYgKGkgPCBudW1QYXJlbnRUcmlhbmdsZXMpIHsKICAgICAgICAgIC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgY29uc3QgbGVmdENoaWxkSW5kZXggPSAoYXkgKyBjeSA+PiAxKSAqIHNpemUgKyAoYXggKyBjeCA+PiAxKTsKICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9IChieSArIGN5ID4+IDEpICogc2l6ZSArIChieCArIGN4ID4+IDEpOwogICAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIGVycm9yc1tsZWZ0Q2hpbGRJbmRleF0sIGVycm9yc1tyaWdodENoaWxkSW5kZXhdKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICBnZXRNZXNoKG1heEVycm9yID0gMCwgbWF4TGVuZ3RoID0gbnVsbCkgewogICAgICBjb25zdCB7CiAgICAgICAgZ3JpZFNpemU6IHNpemUsCiAgICAgICAgaW5kaWNlcwogICAgICB9ID0gdGhpcy5tYXJ0aW5pOwogICAgICBjb25zdCB7CiAgICAgICAgZXJyb3JzCiAgICAgIH0gPSB0aGlzOwogICAgICBsZXQgbnVtVmVydGljZXMgPSAwOwogICAgICBsZXQgbnVtVHJpYW5nbGVzID0gMDsKICAgICAgY29uc3QgbWF4ID0gc2l6ZSAtIDE7IC8vIFRoZSBtYXhMZW5ndGggcGFyYW1ldGVyIHdpbGwgY2F1c2UgdHJpYW5nbGVzIHRvIGJlIGdlbmVyYXRlZCB1bnRpbCB0aGUgbGVncyBhcmUgYmVsb3cgdGhpcyBsZW5ndGgKICAgICAgLy8gSXQgaXMgbWVhbnQgdG8gc3VwcG9ydCBjYXNlcyB3aGVyZSBhIGNlcnRhaW4gbWVzaCBkZW5zaXR5IGlzIHJlcXVpcmVkIHRvIGRvIHNwaGVyaWNhbCBtYXRoIG9uIGRpZ2l0YWwgZ2xvYmVzCgogICAgICBjb25zdCBtYXhTY2FsZSA9IG1heExlbmd0aCB8fCBzaXplOyAvLyB1c2UgYW4gaW5kZXggZ3JpZCB0byBrZWVwIHRyYWNrIG9mIHZlcnRpY2VzIHRoYXQgd2VyZSBhbHJlYWR5IHVzZWQgdG8gYXZvaWQgZHVwbGljYXRpb24KCiAgICAgIGluZGljZXMuZmlsbCgwKTsgLy8gcmV0cmlldmUgbWVzaCBpbiB0d28gc3RhZ2VzIHRoYXQgYm90aCB0cmF2ZXJzZSB0aGUgZXJyb3IgbWFwOgogICAgICAvLyAtIGNvdW50RWxlbWVudHM6IGZpbmQgdXNlZCB2ZXJ0aWNlcyAoYW5kIGFzc2lnbiBlYWNoIGFuIGluZGV4KSwgYW5kIGNvdW50IHRyaWFuZ2xlcyAoZm9yIG1pbmltdW0gYWxsb2NhdGlvbikKICAgICAgLy8gLSBwcm9jZXNzVHJpYW5nbGU6IGZpbGwgdGhlIGFsbG9jYXRlZCB2ZXJ0aWNlcyAmIHRyaWFuZ2xlcyB0eXBlZCBhcnJheXMKCiAgICAgIGZ1bmN0aW9uIGNvdW50RWxlbWVudHMoYXgsIGF5LCBieCwgYnksIGN4LCBjeSkgewogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGxlZ0xlbmd0aCA9IE1hdGguYWJzKGF4IC0gY3gpICsgTWF0aC5hYnMoYXkgLSBjeSk7CgogICAgICAgIGlmIChsZWdMZW5ndGggPiAxICYmIGVycm9yc1tteSAqIHNpemUgKyBteF0gPiBtYXhFcnJvciB8fCBsZWdMZW5ndGggPiBtYXhTY2FsZSkgewogICAgICAgICAgY291bnRFbGVtZW50cyhjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgIGNvdW50RWxlbWVudHMoYngsIGJ5LCBjeCwgY3ksIG14LCBteSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGluZGljZXNbYXkgKiBzaXplICsgYXhdID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIGluZGljZXNbYnkgKiBzaXplICsgYnhdID0gaW5kaWNlc1tieSAqIHNpemUgKyBieF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgIG51bVRyaWFuZ2xlcysrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgY291bnRFbGVtZW50cygwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgY291bnRFbGVtZW50cyhtYXgsIG1heCwgMCwgMCwgMCwgbWF4KTsKICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwoKICAgICAgICBpZiAobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IgfHwgbGVnTGVuZ3RoID4gbWF4U2NhbGUpIHsKICAgICAgICAgIC8vIHRyaWFuZ2xlIGRvZXNuJ3QgYXBwcm94aW1hdGUgdGhlIHN1cmZhY2Ugd2VsbCBlbm91Z2g7IGRyaWxsIGRvd24gZnVydGhlcgogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGN4LCBjeSwgYXgsIGF5LCBteCwgbXkpOwogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBhZGQgYSB0cmlhbmdsZQogICAgICAgICAgY29uc3QgYSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIC0gMTsKICAgICAgICAgIGNvbnN0IGIgPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSAtIDE7CiAgICAgICAgICBjb25zdCBjID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gLSAxOwogICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYSArIDFdID0gYXk7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBiICsgMV0gPSBieTsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBjXSA9IGN4OwogICAgICAgICAgdmVydGljZXNbMiAqIGMgKyAxXSA9IGN5OwogICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGI7CiAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBjOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmVydGljZXMsCiAgICAgICAgdHJpYW5nbGVzCiAgICAgIH07CiAgICB9CgogIH0KCiAgZnVuY3Rpb24gY3JlYXRlQ29tbW9uanNNb2R1bGUoZm4pIHsKICAgIHZhciBtb2R1bGUgPSB7IGV4cG9ydHM6IHt9IH07CiAgCXJldHVybiBmbihtb2R1bGUsIG1vZHVsZS5leHBvcnRzKSwgbW9kdWxlLmV4cG9ydHM7CiAgfQoKICAvKioKICAgKiBDb3B5cmlnaHQgKGMpIDIwMTQtcHJlc2VudCwgRmFjZWJvb2ssIEluYy4KICAgKgogICAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZQogICAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS4KICAgKi8KCiAgY3JlYXRlQ29tbW9uanNNb2R1bGUoZnVuY3Rpb24gKG1vZHVsZSkgewogIHZhciBydW50aW1lID0gKGZ1bmN0aW9uIChleHBvcnRzKSB7CgogICAgdmFyIE9wID0gT2JqZWN0LnByb3RvdHlwZTsKICAgIHZhciBoYXNPd24gPSBPcC5oYXNPd25Qcm9wZXJ0eTsKICAgIHZhciB1bmRlZmluZWQkMTsgLy8gTW9yZSBjb21wcmVzc2libGUgdGhhbiB2b2lkIDAuCiAgICB2YXIgJFN5bWJvbCA9IHR5cGVvZiBTeW1ib2wgPT09ICJmdW5jdGlvbiIgPyBTeW1ib2wgOiB7fTsKICAgIHZhciBpdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuaXRlcmF0b3IgfHwgIkBAaXRlcmF0b3IiOwogICAgdmFyIGFzeW5jSXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLmFzeW5jSXRlcmF0b3IgfHwgIkBAYXN5bmNJdGVyYXRvciI7CiAgICB2YXIgdG9TdHJpbmdUYWdTeW1ib2wgPSAkU3ltYm9sLnRvU3RyaW5nVGFnIHx8ICJAQHRvU3RyaW5nVGFnIjsKCiAgICBmdW5jdGlvbiBkZWZpbmUob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgewogICAgICAgIHZhbHVlOiB2YWx1ZSwKICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZQogICAgICB9KTsKICAgICAgcmV0dXJuIG9ialtrZXldOwogICAgfQogICAgdHJ5IHsKICAgICAgLy8gSUUgOCBoYXMgYSBicm9rZW4gT2JqZWN0LmRlZmluZVByb3BlcnR5IHRoYXQgb25seSB3b3JrcyBvbiBET00gb2JqZWN0cy4KICAgICAgZGVmaW5lKHt9LCAiIik7CiAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgZGVmaW5lID0gZnVuY3Rpb24ob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIG9ialtrZXldID0gdmFsdWU7CiAgICAgIH07CiAgICB9CgogICAgZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgewogICAgICAvLyBJZiBvdXRlckZuIHByb3ZpZGVkIGFuZCBvdXRlckZuLnByb3RvdHlwZSBpcyBhIEdlbmVyYXRvciwgdGhlbiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvci4KICAgICAgdmFyIHByb3RvR2VuZXJhdG9yID0gb3V0ZXJGbiAmJiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvciA/IG91dGVyRm4gOiBHZW5lcmF0b3I7CiAgICAgIHZhciBnZW5lcmF0b3IgPSBPYmplY3QuY3JlYXRlKHByb3RvR2VuZXJhdG9yLnByb3RvdHlwZSk7CiAgICAgIHZhciBjb250ZXh0ID0gbmV3IENvbnRleHQodHJ5TG9jc0xpc3QgfHwgW10pOwoKICAgICAgLy8gVGhlIC5faW52b2tlIG1ldGhvZCB1bmlmaWVzIHRoZSBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlIC5uZXh0LAogICAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMuCiAgICAgIGdlbmVyYXRvci5faW52b2tlID0gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKCiAgICAgIHJldHVybiBnZW5lcmF0b3I7CiAgICB9CiAgICBleHBvcnRzLndyYXAgPSB3cmFwOwoKICAgIC8vIFRyeS9jYXRjaCBoZWxwZXIgdG8gbWluaW1pemUgZGVvcHRpbWl6YXRpb25zLiBSZXR1cm5zIGEgY29tcGxldGlvbgogICAgLy8gcmVjb3JkIGxpa2UgY29udGV4dC50cnlFbnRyaWVzW2ldLmNvbXBsZXRpb24uIFRoaXMgaW50ZXJmYWNlIGNvdWxkCiAgICAvLyBoYXZlIGJlZW4gKGFuZCB3YXMgcHJldmlvdXNseSkgZGVzaWduZWQgdG8gdGFrZSBhIGNsb3N1cmUgdG8gYmUKICAgIC8vIGludm9rZWQgd2l0aG91dCBhcmd1bWVudHMsIGJ1dCBpbiBhbGwgdGhlIGNhc2VzIHdlIGNhcmUgYWJvdXQgd2UKICAgIC8vIGFscmVhZHkgaGF2ZSBhbiBleGlzdGluZyBtZXRob2Qgd2Ugd2FudCB0byBjYWxsLCBzbyB0aGVyZSdzIG5vIG5lZWQKICAgIC8vIHRvIGNyZWF0ZSBhIG5ldyBmdW5jdGlvbiBvYmplY3QuIFdlIGNhbiBldmVuIGdldCBhd2F5IHdpdGggYXNzdW1pbmcKICAgIC8vIHRoZSBtZXRob2QgdGFrZXMgZXhhY3RseSBvbmUgYXJndW1lbnQsIHNpbmNlIHRoYXQgaGFwcGVucyB0byBiZSB0cnVlCiAgICAvLyBpbiBldmVyeSBjYXNlLCBzbyB3ZSBkb24ndCBoYXZlIHRvIHRvdWNoIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBUaGUKICAgIC8vIG9ubHkgYWRkaXRpb25hbCBhbGxvY2F0aW9uIHJlcXVpcmVkIGlzIHRoZSBjb21wbGV0aW9uIHJlY29yZCwgd2hpY2gKICAgIC8vIGhhcyBhIHN0YWJsZSBzaGFwZSBhbmQgc28gaG9wZWZ1bGx5IHNob3VsZCBiZSBjaGVhcCB0byBhbGxvY2F0ZS4KICAgIGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgewogICAgICB0cnkgewogICAgICAgIHJldHVybiB7IHR5cGU6ICJub3JtYWwiLCBhcmc6IGZuLmNhbGwob2JqLCBhcmcpIH07CiAgICAgIH0gY2F0Y2ggKGVycikgewogICAgICAgIHJldHVybiB7IHR5cGU6ICJ0aHJvdyIsIGFyZzogZXJyIH07CiAgICAgIH0KICAgIH0KCiAgICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRTdGFydCA9ICJzdXNwZW5kZWRTdGFydCI7CiAgICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRZaWVsZCA9ICJzdXNwZW5kZWRZaWVsZCI7CiAgICB2YXIgR2VuU3RhdGVFeGVjdXRpbmcgPSAiZXhlY3V0aW5nIjsKICAgIHZhciBHZW5TdGF0ZUNvbXBsZXRlZCA9ICJjb21wbGV0ZWQiOwoKICAgIC8vIFJldHVybmluZyB0aGlzIG9iamVjdCBmcm9tIHRoZSBpbm5lckZuIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMKICAgIC8vIGJyZWFraW5nIG91dCBvZiB0aGUgZGlzcGF0Y2ggc3dpdGNoIHN0YXRlbWVudC4KICAgIHZhciBDb250aW51ZVNlbnRpbmVsID0ge307CgogICAgLy8gRHVtbXkgY29uc3RydWN0b3IgZnVuY3Rpb25zIHRoYXQgd2UgdXNlIGFzIHRoZSAuY29uc3RydWN0b3IgYW5kCiAgICAvLyAuY29uc3RydWN0b3IucHJvdG90eXBlIHByb3BlcnRpZXMgZm9yIGZ1bmN0aW9ucyB0aGF0IHJldHVybiBHZW5lcmF0b3IKICAgIC8vIG9iamVjdHMuIEZvciBmdWxsIHNwZWMgY29tcGxpYW5jZSwgeW91IG1heSB3aXNoIHRvIGNvbmZpZ3VyZSB5b3VyCiAgICAvLyBtaW5pZmllciBub3QgdG8gbWFuZ2xlIHRoZSBuYW1lcyBvZiB0aGVzZSB0d28gZnVuY3Rpb25zLgogICAgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30KICAgIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uKCkge30KICAgIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKCkge30KCiAgICAvLyBUaGlzIGlzIGEgcG9seWZpbGwgZm9yICVJdGVyYXRvclByb3RvdHlwZSUgZm9yIGVudmlyb25tZW50cyB0aGF0CiAgICAvLyBkb24ndCBuYXRpdmVseSBzdXBwb3J0IGl0LgogICAgdmFyIEl0ZXJhdG9yUHJvdG90eXBlID0ge307CiAgICBkZWZpbmUoSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSk7CgogICAgdmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mOwogICAgdmFyIE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG8gJiYgZ2V0UHJvdG8oZ2V0UHJvdG8odmFsdWVzKFtdKSkpOwogICAgaWYgKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlICYmCiAgICAgICAgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgIT09IE9wICYmCiAgICAgICAgaGFzT3duLmNhbGwoTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sKSkgewogICAgICAvLyBUaGlzIGVudmlyb25tZW50IGhhcyBhIG5hdGl2ZSAlSXRlcmF0b3JQcm90b3R5cGUlOyB1c2UgaXQgaW5zdGVhZAogICAgICAvLyBvZiB0aGUgcG9seWZpbGwuCiAgICAgIEl0ZXJhdG9yUHJvdG90eXBlID0gTmF0aXZlSXRlcmF0b3JQcm90b3R5cGU7CiAgICB9CgogICAgdmFyIEdwID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUucHJvdG90eXBlID0KICAgICAgR2VuZXJhdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUpOwogICAgR2VuZXJhdG9yRnVuY3Rpb24ucHJvdG90eXBlID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgICBkZWZpbmUoR3AsICJjb25zdHJ1Y3RvciIsIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKTsKICAgIGRlZmluZShHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgImNvbnN0cnVjdG9yIiwgR2VuZXJhdG9yRnVuY3Rpb24pOwogICAgR2VuZXJhdG9yRnVuY3Rpb24uZGlzcGxheU5hbWUgPSBkZWZpbmUoCiAgICAgIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLAogICAgICB0b1N0cmluZ1RhZ1N5bWJvbCwKICAgICAgIkdlbmVyYXRvckZ1bmN0aW9uIgogICAgKTsKCiAgICAvLyBIZWxwZXIgZm9yIGRlZmluaW5nIHRoZSAubmV4dCwgLnRocm93LCBhbmQgLnJldHVybiBtZXRob2RzIG9mIHRoZQogICAgLy8gSXRlcmF0b3IgaW50ZXJmYWNlIGluIHRlcm1zIG9mIGEgc2luZ2xlIC5faW52b2tlIG1ldGhvZC4KICAgIGZ1bmN0aW9uIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhwcm90b3R5cGUpIHsKICAgICAgWyJuZXh0IiwgInRocm93IiwgInJldHVybiJdLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7CiAgICAgICAgZGVmaW5lKHByb3RvdHlwZSwgbWV0aG9kLCBmdW5jdGlvbihhcmcpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9pbnZva2UobWV0aG9kLCBhcmcpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KCiAgICBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24gPSBmdW5jdGlvbihnZW5GdW4pIHsKICAgICAgdmFyIGN0b3IgPSB0eXBlb2YgZ2VuRnVuID09PSAiZnVuY3Rpb24iICYmIGdlbkZ1bi5jb25zdHJ1Y3RvcjsKICAgICAgcmV0dXJuIGN0b3IKICAgICAgICA/IGN0b3IgPT09IEdlbmVyYXRvckZ1bmN0aW9uIHx8CiAgICAgICAgICAvLyBGb3IgdGhlIG5hdGl2ZSBHZW5lcmF0b3JGdW5jdGlvbiBjb25zdHJ1Y3RvciwgdGhlIGJlc3Qgd2UgY2FuCiAgICAgICAgICAvLyBkbyBpcyB0byBjaGVjayBpdHMgLm5hbWUgcHJvcGVydHkuCiAgICAgICAgICAoY3Rvci5kaXNwbGF5TmFtZSB8fCBjdG9yLm5hbWUpID09PSAiR2VuZXJhdG9yRnVuY3Rpb24iCiAgICAgICAgOiBmYWxzZTsKICAgIH07CgogICAgZXhwb3J0cy5tYXJrID0gZnVuY3Rpb24oZ2VuRnVuKSB7CiAgICAgIGlmIChPYmplY3Quc2V0UHJvdG90eXBlT2YpIHsKICAgICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoZ2VuRnVuLCBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZ2VuRnVuLl9fcHJvdG9fXyA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlOwogICAgICAgIGRlZmluZShnZW5GdW4sIHRvU3RyaW5nVGFnU3ltYm9sLCAiR2VuZXJhdG9yRnVuY3Rpb24iKTsKICAgICAgfQogICAgICBnZW5GdW4ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHcCk7CiAgICAgIHJldHVybiBnZW5GdW47CiAgICB9OwoKICAgIC8vIFdpdGhpbiB0aGUgYm9keSBvZiBhbnkgYXN5bmMgZnVuY3Rpb24sIGBhd2FpdCB4YCBpcyB0cmFuc2Zvcm1lZCB0bwogICAgLy8gYHlpZWxkIHJlZ2VuZXJhdG9yUnVudGltZS5hd3JhcCh4KWAsIHNvIHRoYXQgdGhlIHJ1bnRpbWUgY2FuIHRlc3QKICAgIC8vIGBoYXNPd24uY2FsbCh2YWx1ZSwgIl9fYXdhaXQiKWAgdG8gZGV0ZXJtaW5lIGlmIHRoZSB5aWVsZGVkIHZhbHVlIGlzCiAgICAvLyBtZWFudCB0byBiZSBhd2FpdGVkLgogICAgZXhwb3J0cy5hd3JhcCA9IGZ1bmN0aW9uKGFyZykgewogICAgICByZXR1cm4geyBfX2F3YWl0OiBhcmcgfTsKICAgIH07CgogICAgZnVuY3Rpb24gQXN5bmNJdGVyYXRvcihnZW5lcmF0b3IsIFByb21pc2VJbXBsKSB7CiAgICAgIGZ1bmN0aW9uIGludm9rZShtZXRob2QsIGFyZywgcmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgdmFyIHJlY29yZCA9IHRyeUNhdGNoKGdlbmVyYXRvclttZXRob2RdLCBnZW5lcmF0b3IsIGFyZyk7CiAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgICByZWplY3QocmVjb3JkLmFyZyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciByZXN1bHQgPSByZWNvcmQuYXJnOwogICAgICAgICAgdmFyIHZhbHVlID0gcmVzdWx0LnZhbHVlOwogICAgICAgICAgaWYgKHZhbHVlICYmCiAgICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAib2JqZWN0IiAmJgogICAgICAgICAgICAgIGhhc093bi5jYWxsKHZhbHVlLCAiX19hd2FpdCIpKSB7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlSW1wbC5yZXNvbHZlKHZhbHVlLl9fYXdhaXQpLnRoZW4oZnVuY3Rpb24odmFsdWUpIHsKICAgICAgICAgICAgICBpbnZva2UoIm5leHQiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oZXJyKSB7CiAgICAgICAgICAgICAgaW52b2tlKCJ0aHJvdyIsIGVyciwgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIFByb21pc2VJbXBsLnJlc29sdmUodmFsdWUpLnRoZW4oZnVuY3Rpb24odW53cmFwcGVkKSB7CiAgICAgICAgICAgIC8vIFdoZW4gYSB5aWVsZGVkIFByb21pc2UgaXMgcmVzb2x2ZWQsIGl0cyBmaW5hbCB2YWx1ZSBiZWNvbWVzCiAgICAgICAgICAgIC8vIHRoZSAudmFsdWUgb2YgdGhlIFByb21pc2U8e3ZhbHVlLGRvbmV9PiByZXN1bHQgZm9yIHRoZQogICAgICAgICAgICAvLyBjdXJyZW50IGl0ZXJhdGlvbi4KICAgICAgICAgICAgcmVzdWx0LnZhbHVlID0gdW53cmFwcGVkOwogICAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7CiAgICAgICAgICB9LCBmdW5jdGlvbihlcnJvcikgewogICAgICAgICAgICAvLyBJZiBhIHJlamVjdGVkIFByb21pc2Ugd2FzIHlpZWxkZWQsIHRocm93IHRoZSByZWplY3Rpb24gYmFjawogICAgICAgICAgICAvLyBpbnRvIHRoZSBhc3luYyBnZW5lcmF0b3IgZnVuY3Rpb24gc28gaXQgY2FuIGJlIGhhbmRsZWQgdGhlcmUuCiAgICAgICAgICAgIHJldHVybiBpbnZva2UoInRocm93IiwgZXJyb3IsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBwcmV2aW91c1Byb21pc2U7CgogICAgICBmdW5jdGlvbiBlbnF1ZXVlKG1ldGhvZCwgYXJnKSB7CiAgICAgICAgZnVuY3Rpb24gY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2VJbXBsKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBwcmV2aW91c1Byb21pc2UgPQogICAgICAgICAgLy8gSWYgZW5xdWV1ZSBoYXMgYmVlbiBjYWxsZWQgYmVmb3JlLCB0aGVuIHdlIHdhbnQgdG8gd2FpdCB1bnRpbAogICAgICAgICAgLy8gYWxsIHByZXZpb3VzIFByb21pc2VzIGhhdmUgYmVlbiByZXNvbHZlZCBiZWZvcmUgY2FsbGluZyBpbnZva2UsCiAgICAgICAgICAvLyBzbyB0aGF0IHJlc3VsdHMgYXJlIGFsd2F5cyBkZWxpdmVyZWQgaW4gdGhlIGNvcnJlY3Qgb3JkZXIuIElmCiAgICAgICAgICAvLyBlbnF1ZXVlIGhhcyBub3QgYmVlbiBjYWxsZWQgYmVmb3JlLCB0aGVuIGl0IGlzIGltcG9ydGFudCB0bwogICAgICAgICAgLy8gY2FsbCBpbnZva2UgaW1tZWRpYXRlbHksIHdpdGhvdXQgd2FpdGluZyBvbiBhIGNhbGxiYWNrIHRvIGZpcmUsCiAgICAgICAgICAvLyBzbyB0aGF0IHRoZSBhc3luYyBnZW5lcmF0b3IgZnVuY3Rpb24gaGFzIHRoZSBvcHBvcnR1bml0eSB0byBkbwogICAgICAgICAgLy8gYW55IG5lY2Vzc2FyeSBzZXR1cCBpbiBhIHByZWRpY3RhYmxlIHdheS4gVGhpcyBwcmVkaWN0YWJpbGl0eQogICAgICAgICAgLy8gaXMgd2h5IHRoZSBQcm9taXNlIGNvbnN0cnVjdG9yIHN5bmNocm9ub3VzbHkgaW52b2tlcyBpdHMKICAgICAgICAgIC8vIGV4ZWN1dG9yIGNhbGxiYWNrLCBhbmQgd2h5IGFzeW5jIGZ1bmN0aW9ucyBzeW5jaHJvbm91c2x5CiAgICAgICAgICAvLyBleGVjdXRlIGNvZGUgYmVmb3JlIHRoZSBmaXJzdCBhd2FpdC4gU2luY2Ugd2UgaW1wbGVtZW50IHNpbXBsZQogICAgICAgICAgLy8gYXN5bmMgZnVuY3Rpb25zIGluIHRlcm1zIG9mIGFzeW5jIGdlbmVyYXRvcnMsIGl0IGlzIGVzcGVjaWFsbHkKICAgICAgICAgIC8vIGltcG9ydGFudCB0byBnZXQgdGhpcyByaWdodCwgZXZlbiB0aG91Z2ggaXQgcmVxdWlyZXMgY2FyZS4KICAgICAgICAgIHByZXZpb3VzUHJvbWlzZSA/IHByZXZpb3VzUHJvbWlzZS50aGVuKAogICAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZywKICAgICAgICAgICAgLy8gQXZvaWQgcHJvcGFnYXRpbmcgZmFpbHVyZXMgdG8gUHJvbWlzZXMgcmV0dXJuZWQgYnkgbGF0ZXIKICAgICAgICAgICAgLy8gaW52b2NhdGlvbnMgb2YgdGhlIGl0ZXJhdG9yLgogICAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZwogICAgICAgICAgKSA6IGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCk7CiAgICAgIH0KCiAgICAgIC8vIERlZmluZSB0aGUgdW5pZmllZCBoZWxwZXIgbWV0aG9kIHRoYXQgaXMgdXNlZCB0byBpbXBsZW1lbnQgLm5leHQsCiAgICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gKHNlZSBkZWZpbmVJdGVyYXRvck1ldGhvZHMpLgogICAgICB0aGlzLl9pbnZva2UgPSBlbnF1ZXVlOwogICAgfQoKICAgIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSk7CiAgICBkZWZpbmUoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUsIGFzeW5jSXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9KTsKICAgIGV4cG9ydHMuQXN5bmNJdGVyYXRvciA9IEFzeW5jSXRlcmF0b3I7CgogICAgLy8gTm90ZSB0aGF0IHNpbXBsZSBhc3luYyBmdW5jdGlvbnMgYXJlIGltcGxlbWVudGVkIG9uIHRvcCBvZgogICAgLy8gQXN5bmNJdGVyYXRvciBvYmplY3RzOyB0aGV5IGp1c3QgcmV0dXJuIGEgUHJvbWlzZSBmb3IgdGhlIHZhbHVlIG9mCiAgICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci4KICAgIGV4cG9ydHMuYXN5bmMgPSBmdW5jdGlvbihpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCwgUHJvbWlzZUltcGwpIHsKICAgICAgaWYgKFByb21pc2VJbXBsID09PSB2b2lkIDApIFByb21pc2VJbXBsID0gUHJvbWlzZTsKCiAgICAgIHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3IoCiAgICAgICAgd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCksCiAgICAgICAgUHJvbWlzZUltcGwKICAgICAgKTsKCiAgICAgIHJldHVybiBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikKICAgICAgICA/IGl0ZXIgLy8gSWYgb3V0ZXJGbiBpcyBhIGdlbmVyYXRvciwgcmV0dXJuIHRoZSBmdWxsIGl0ZXJhdG9yLgogICAgICAgIDogaXRlci5uZXh0KCkudGhlbihmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7CiAgICAgICAgICB9KTsKICAgIH07CgogICAgZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7CiAgICAgIHZhciBzdGF0ZSA9IEdlblN0YXRlU3VzcGVuZGVkU3RhcnQ7CgogICAgICByZXR1cm4gZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnKSB7CiAgICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZUV4ZWN1dGluZykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBydW5uaW5nIik7CiAgICAgICAgfQoKICAgICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlQ29tcGxldGVkKSB7CiAgICAgICAgICBpZiAobWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgIHRocm93IGFyZzsKICAgICAgICAgIH0KCiAgICAgICAgICAvLyBCZSBmb3JnaXZpbmcsIHBlciAyNS4zLjMuMy4zIG9mIHRoZSBzcGVjOgogICAgICAgICAgLy8gaHR0cHM6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLWdlbmVyYXRvcnJlc3VtZQogICAgICAgICAgcmV0dXJuIGRvbmVSZXN1bHQoKTsKICAgICAgICB9CgogICAgICAgIGNvbnRleHQubWV0aG9kID0gbWV0aG9kOwogICAgICAgIGNvbnRleHQuYXJnID0gYXJnOwoKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgdmFyIGRlbGVnYXRlID0gY29udGV4dC5kZWxlZ2F0ZTsKICAgICAgICAgIGlmIChkZWxlZ2F0ZSkgewogICAgICAgICAgICB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTsKICAgICAgICAgICAgaWYgKGRlbGVnYXRlUmVzdWx0KSB7CiAgICAgICAgICAgICAgaWYgKGRlbGVnYXRlUmVzdWx0ID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsKICAgICAgICAgICAgICByZXR1cm4gZGVsZWdhdGVSZXN1bHQ7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoY29udGV4dC5tZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgICAvLyBTZXR0aW5nIGNvbnRleHQuX3NlbnQgZm9yIGxlZ2FjeSBzdXBwb3J0IG9mIEJhYmVsJ3MKICAgICAgICAgICAgLy8gZnVuY3Rpb24uc2VudCBpbXBsZW1lbnRhdGlvbi4KICAgICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnOwoKICAgICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0KSB7CiAgICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDsKICAgICAgICAgICAgICB0aHJvdyBjb250ZXh0LmFyZzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29udGV4dC5kaXNwYXRjaEV4Y2VwdGlvbihjb250ZXh0LmFyZyk7CgogICAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0Lm1ldGhvZCA9PT0gInJldHVybiIpIHsKICAgICAgICAgICAgY29udGV4dC5hYnJ1cHQoInJldHVybiIsIGNvbnRleHQuYXJnKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlRXhlY3V0aW5nOwoKICAgICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gIm5vcm1hbCIpIHsKICAgICAgICAgICAgLy8gSWYgYW4gZXhjZXB0aW9uIGlzIHRocm93biBmcm9tIGlubmVyRm4sIHdlIGxlYXZlIHN0YXRlID09PQogICAgICAgICAgICAvLyBHZW5TdGF0ZUV4ZWN1dGluZyBhbmQgbG9vcCBiYWNrIGZvciBhbm90aGVyIGludm9jYXRpb24uCiAgICAgICAgICAgIHN0YXRlID0gY29udGV4dC5kb25lCiAgICAgICAgICAgICAgPyBHZW5TdGF0ZUNvbXBsZXRlZAogICAgICAgICAgICAgIDogR2VuU3RhdGVTdXNwZW5kZWRZaWVsZDsKCiAgICAgICAgICAgIGlmIChyZWNvcmQuYXJnID09PSBDb250aW51ZVNlbnRpbmVsKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgdmFsdWU6IHJlY29yZC5hcmcsCiAgICAgICAgICAgICAgZG9uZTogY29udGV4dC5kb25lCiAgICAgICAgICAgIH07CgogICAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlQ29tcGxldGVkOwogICAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlCiAgICAgICAgICAgIC8vIGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpIGNhbGwgYWJvdmUuCiAgICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gInRocm93IjsKICAgICAgICAgICAgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKICAgIH0KCiAgICAvLyBDYWxsIGRlbGVnYXRlLml0ZXJhdG9yW2NvbnRleHQubWV0aG9kXShjb250ZXh0LmFyZykgYW5kIGhhbmRsZSB0aGUKICAgIC8vIHJlc3VsdCwgZWl0aGVyIGJ5IHJldHVybmluZyBhIHsgdmFsdWUsIGRvbmUgfSByZXN1bHQgZnJvbSB0aGUKICAgIC8vIGRlbGVnYXRlIGl0ZXJhdG9yLCBvciBieSBtb2RpZnlpbmcgY29udGV4dC5tZXRob2QgYW5kIGNvbnRleHQuYXJnLAogICAgLy8gc2V0dGluZyBjb250ZXh0LmRlbGVnYXRlIHRvIG51bGwsIGFuZCByZXR1cm5pbmcgdGhlIENvbnRpbnVlU2VudGluZWwuCiAgICBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7CiAgICAgIHZhciBtZXRob2QgPSBkZWxlZ2F0ZS5pdGVyYXRvcltjb250ZXh0Lm1ldGhvZF07CiAgICAgIGlmIChtZXRob2QgPT09IHVuZGVmaW5lZCQxKSB7CiAgICAgICAgLy8gQSAudGhyb3cgb3IgLnJldHVybiB3aGVuIHRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBoYXMgbm8gLnRocm93CiAgICAgICAgLy8gbWV0aG9kIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC4KICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKCiAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAvLyBOb3RlOiBbInJldHVybiJdIG11c3QgYmUgdXNlZCBmb3IgRVMzIHBhcnNpbmcgY29tcGF0aWJpbGl0eS4KICAgICAgICAgIGlmIChkZWxlZ2F0ZS5pdGVyYXRvclsicmV0dXJuIl0pIHsKICAgICAgICAgICAgLy8gSWYgdGhlIGRlbGVnYXRlIGl0ZXJhdG9yIGhhcyBhIHJldHVybiBtZXRob2QsIGdpdmUgaXQgYQogICAgICAgICAgICAvLyBjaGFuY2UgdG8gY2xlYW4gdXAuCiAgICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gInJldHVybiI7CiAgICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgICAgIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpOwoKICAgICAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgICAgLy8gSWYgbWF5YmVJbnZva2VEZWxlZ2F0ZShjb250ZXh0KSBjaGFuZ2VkIGNvbnRleHQubWV0aG9kIGZyb20KICAgICAgICAgICAgICAvLyAicmV0dXJuIiB0byAidGhyb3ciLCBsZXQgdGhhdCBvdmVycmlkZSB0aGUgVHlwZUVycm9yIGJlbG93LgogICAgICAgICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgY29udGV4dC5tZXRob2QgPSAidGhyb3ciOwogICAgICAgICAgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKAogICAgICAgICAgICAiVGhlIGl0ZXJhdG9yIGRvZXMgbm90IHByb3ZpZGUgYSAndGhyb3cnIG1ldGhvZCIpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgIH0KCiAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChtZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBjb250ZXh0LmFyZyk7CgogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJ0aHJvdyI7CiAgICAgICAgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnOwogICAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsOwogICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICB9CgogICAgICB2YXIgaW5mbyA9IHJlY29yZC5hcmc7CgogICAgICBpZiAoISBpbmZvKSB7CiAgICAgICAgY29udGV4dC5tZXRob2QgPSAidGhyb3ciOwogICAgICAgIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcigiaXRlcmF0b3IgcmVzdWx0IGlzIG5vdCBhbiBvYmplY3QiKTsKICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgfQoKICAgICAgaWYgKGluZm8uZG9uZSkgewogICAgICAgIC8vIEFzc2lnbiB0aGUgcmVzdWx0IG9mIHRoZSBmaW5pc2hlZCBkZWxlZ2F0ZSB0byB0aGUgdGVtcG9yYXJ5CiAgICAgICAgLy8gdmFyaWFibGUgc3BlY2lmaWVkIGJ5IGRlbGVnYXRlLnJlc3VsdE5hbWUgKHNlZSBkZWxlZ2F0ZVlpZWxkKS4KICAgICAgICBjb250ZXh0W2RlbGVnYXRlLnJlc3VsdE5hbWVdID0gaW5mby52YWx1ZTsKCiAgICAgICAgLy8gUmVzdW1lIGV4ZWN1dGlvbiBhdCB0aGUgZGVzaXJlZCBsb2NhdGlvbiAoc2VlIGRlbGVnYXRlWWllbGQpLgogICAgICAgIGNvbnRleHQubmV4dCA9IGRlbGVnYXRlLm5leHRMb2M7CgogICAgICAgIC8vIElmIGNvbnRleHQubWV0aG9kIHdhcyAidGhyb3ciIGJ1dCB0aGUgZGVsZWdhdGUgaGFuZGxlZCB0aGUKICAgICAgICAvLyBleGNlcHRpb24sIGxldCB0aGUgb3V0ZXIgZ2VuZXJhdG9yIHByb2NlZWQgbm9ybWFsbHkuIElmCiAgICAgICAgLy8gY29udGV4dC5tZXRob2Qgd2FzICJuZXh0IiwgZm9yZ2V0IGNvbnRleHQuYXJnIHNpbmNlIGl0IGhhcyBiZWVuCiAgICAgICAgLy8gImNvbnN1bWVkIiBieSB0aGUgZGVsZWdhdGUgaXRlcmF0b3IuIElmIGNvbnRleHQubWV0aG9kIHdhcwogICAgICAgIC8vICJyZXR1cm4iLCBhbGxvdyB0aGUgb3JpZ2luYWwgLnJldHVybiBjYWxsIHRvIGNvbnRpbnVlIGluIHRoZQogICAgICAgIC8vIG91dGVyIGdlbmVyYXRvci4KICAgICAgICBpZiAoY29udGV4dC5tZXRob2QgIT09ICJyZXR1cm4iKSB7CiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgfQoKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBSZS15aWVsZCB0aGUgcmVzdWx0IHJldHVybmVkIGJ5IHRoZSBkZWxlZ2F0ZSBtZXRob2QuCiAgICAgICAgcmV0dXJuIGluZm87CiAgICAgIH0KCiAgICAgIC8vIFRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBpcyBmaW5pc2hlZCwgc28gZm9yZ2V0IGl0IGFuZCBjb250aW51ZSB3aXRoCiAgICAgIC8vIHRoZSBvdXRlciBnZW5lcmF0b3IuCiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsOwogICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgIH0KCiAgICAvLyBEZWZpbmUgR2VuZXJhdG9yLnByb3RvdHlwZS57bmV4dCx0aHJvdyxyZXR1cm59IGluIHRlcm1zIG9mIHRoZQogICAgLy8gdW5pZmllZCAuX2ludm9rZSBoZWxwZXIgbWV0aG9kLgogICAgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEdwKTsKCiAgICBkZWZpbmUoR3AsIHRvU3RyaW5nVGFnU3ltYm9sLCAiR2VuZXJhdG9yIik7CgogICAgLy8gQSBHZW5lcmF0b3Igc2hvdWxkIGFsd2F5cyByZXR1cm4gaXRzZWxmIGFzIHRoZSBpdGVyYXRvciBvYmplY3Qgd2hlbiB0aGUKICAgIC8vIEBAaXRlcmF0b3IgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGl0LiBTb21lIGJyb3dzZXJzJyBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlCiAgICAvLyBpdGVyYXRvciBwcm90b3R5cGUgY2hhaW4gaW5jb3JyZWN0bHkgaW1wbGVtZW50IHRoaXMsIGNhdXNpbmcgdGhlIEdlbmVyYXRvcgogICAgLy8gb2JqZWN0IHRvIG5vdCBiZSByZXR1cm5lZCBmcm9tIHRoaXMgY2FsbC4gVGhpcyBlbnN1cmVzIHRoYXQgZG9lc24ndCBoYXBwZW4uCiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL2lzc3Vlcy8yNzQgZm9yIG1vcmUgZGV0YWlscy4KICAgIGRlZmluZShHcCwgaXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0pOwoKICAgIGRlZmluZShHcCwgInRvU3RyaW5nIiwgZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiAiW29iamVjdCBHZW5lcmF0b3JdIjsKICAgIH0pOwoKICAgIGZ1bmN0aW9uIHB1c2hUcnlFbnRyeShsb2NzKSB7CiAgICAgIHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07CgogICAgICBpZiAoMSBpbiBsb2NzKSB7CiAgICAgICAgZW50cnkuY2F0Y2hMb2MgPSBsb2NzWzFdOwogICAgICB9CgogICAgICBpZiAoMiBpbiBsb2NzKSB7CiAgICAgICAgZW50cnkuZmluYWxseUxvYyA9IGxvY3NbMl07CiAgICAgICAgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdOwogICAgICB9CgogICAgICB0aGlzLnRyeUVudHJpZXMucHVzaChlbnRyeSk7CiAgICB9CgogICAgZnVuY3Rpb24gcmVzZXRUcnlFbnRyeShlbnRyeSkgewogICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbiB8fCB7fTsKICAgICAgcmVjb3JkLnR5cGUgPSAibm9ybWFsIjsKICAgICAgZGVsZXRlIHJlY29yZC5hcmc7CiAgICAgIGVudHJ5LmNvbXBsZXRpb24gPSByZWNvcmQ7CiAgICB9CgogICAgZnVuY3Rpb24gQ29udGV4dCh0cnlMb2NzTGlzdCkgewogICAgICAvLyBUaGUgcm9vdCBlbnRyeSBvYmplY3QgKGVmZmVjdGl2ZWx5IGEgdHJ5IHN0YXRlbWVudCB3aXRob3V0IGEgY2F0Y2gKICAgICAgLy8gb3IgYSBmaW5hbGx5IGJsb2NrKSBnaXZlcyB1cyBhIHBsYWNlIHRvIHN0b3JlIHZhbHVlcyB0aHJvd24gZnJvbQogICAgICAvLyBsb2NhdGlvbnMgd2hlcmUgdGhlcmUgaXMgbm8gZW5jbG9zaW5nIHRyeSBzdGF0ZW1lbnQuCiAgICAgIHRoaXMudHJ5RW50cmllcyA9IFt7IHRyeUxvYzogInJvb3QiIH1dOwogICAgICB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyk7CiAgICAgIHRoaXMucmVzZXQodHJ1ZSk7CiAgICB9CgogICAgZXhwb3J0cy5rZXlzID0gZnVuY3Rpb24ob2JqZWN0KSB7CiAgICAgIHZhciBrZXlzID0gW107CiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHsKICAgICAgICBrZXlzLnB1c2goa2V5KTsKICAgICAgfQogICAgICBrZXlzLnJldmVyc2UoKTsKCiAgICAgIC8vIFJhdGhlciB0aGFuIHJldHVybmluZyBhbiBvYmplY3Qgd2l0aCBhIG5leHQgbWV0aG9kLCB3ZSBrZWVwCiAgICAgIC8vIHRoaW5ncyBzaW1wbGUgYW5kIHJldHVybiB0aGUgbmV4dCBmdW5jdGlvbiBpdHNlbGYuCiAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0KCkgewogICAgICAgIHdoaWxlIChrZXlzLmxlbmd0aCkgewogICAgICAgICAgdmFyIGtleSA9IGtleXMucG9wKCk7CiAgICAgICAgICBpZiAoa2V5IGluIG9iamVjdCkgewogICAgICAgICAgICBuZXh0LnZhbHVlID0ga2V5OwogICAgICAgICAgICBuZXh0LmRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBUbyBhdm9pZCBjcmVhdGluZyBhbiBhZGRpdGlvbmFsIG9iamVjdCwgd2UganVzdCBoYW5nIHRoZSAudmFsdWUKICAgICAgICAvLyBhbmQgLmRvbmUgcHJvcGVydGllcyBvZmYgdGhlIG5leHQgZnVuY3Rpb24gb2JqZWN0IGl0c2VsZi4gVGhpcwogICAgICAgIC8vIGFsc28gZW5zdXJlcyB0aGF0IHRoZSBtaW5pZmllciB3aWxsIG5vdCBhbm9ueW1pemUgdGhlIGZ1bmN0aW9uLgogICAgICAgIG5leHQuZG9uZSA9IHRydWU7CiAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgIH07CiAgICB9OwoKICAgIGZ1bmN0aW9uIHZhbHVlcyhpdGVyYWJsZSkgewogICAgICBpZiAoaXRlcmFibGUpIHsKICAgICAgICB2YXIgaXRlcmF0b3JNZXRob2QgPSBpdGVyYWJsZVtpdGVyYXRvclN5bWJvbF07CiAgICAgICAgaWYgKGl0ZXJhdG9yTWV0aG9kKSB7CiAgICAgICAgICByZXR1cm4gaXRlcmF0b3JNZXRob2QuY2FsbChpdGVyYWJsZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAodHlwZW9mIGl0ZXJhYmxlLm5leHQgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgIHJldHVybiBpdGVyYWJsZTsKICAgICAgICB9CgogICAgICAgIGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkgewogICAgICAgICAgdmFyIGkgPSAtMSwgbmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgICAgICAgIHdoaWxlICgrK2kgPCBpdGVyYWJsZS5sZW5ndGgpIHsKICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSB7CiAgICAgICAgICAgICAgICBuZXh0LnZhbHVlID0gaXRlcmFibGVbaV07CiAgICAgICAgICAgICAgICBuZXh0LmRvbmUgPSBmYWxzZTsKICAgICAgICAgICAgICAgIHJldHVybiBuZXh0OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgbmV4dC52YWx1ZSA9IHVuZGVmaW5lZCQxOwogICAgICAgICAgICBuZXh0LmRvbmUgPSB0cnVlOwoKICAgICAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgICAgICB9OwoKICAgICAgICAgIHJldHVybiBuZXh0Lm5leHQgPSBuZXh0OwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gUmV0dXJuIGFuIGl0ZXJhdG9yIHdpdGggbm8gdmFsdWVzLgogICAgICByZXR1cm4geyBuZXh0OiBkb25lUmVzdWx0IH07CiAgICB9CiAgICBleHBvcnRzLnZhbHVlcyA9IHZhbHVlczsKCiAgICBmdW5jdGlvbiBkb25lUmVzdWx0KCkgewogICAgICByZXR1cm4geyB2YWx1ZTogdW5kZWZpbmVkJDEsIGRvbmU6IHRydWUgfTsKICAgIH0KCiAgICBDb250ZXh0LnByb3RvdHlwZSA9IHsKICAgICAgY29uc3RydWN0b3I6IENvbnRleHQsCgogICAgICByZXNldDogZnVuY3Rpb24oc2tpcFRlbXBSZXNldCkgewogICAgICAgIHRoaXMucHJldiA9IDA7CiAgICAgICAgdGhpcy5uZXh0ID0gMDsKICAgICAgICAvLyBSZXNldHRpbmcgY29udGV4dC5fc2VudCBmb3IgbGVnYWN5IHN1cHBvcnQgb2YgQmFiZWwncwogICAgICAgIC8vIGZ1bmN0aW9uLnNlbnQgaW1wbGVtZW50YXRpb24uCiAgICAgICAgdGhpcy5zZW50ID0gdGhpcy5fc2VudCA9IHVuZGVmaW5lZCQxOwogICAgICAgIHRoaXMuZG9uZSA9IGZhbHNlOwogICAgICAgIHRoaXMuZGVsZWdhdGUgPSBudWxsOwoKICAgICAgICB0aGlzLm1ldGhvZCA9ICJuZXh0IjsKICAgICAgICB0aGlzLmFyZyA9IHVuZGVmaW5lZCQxOwoKICAgICAgICB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KTsKCiAgICAgICAgaWYgKCFza2lwVGVtcFJlc2V0KSB7CiAgICAgICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMpIHsKICAgICAgICAgICAgLy8gTm90IHN1cmUgYWJvdXQgdGhlIG9wdGltYWwgb3JkZXIgb2YgdGhlc2UgY29uZGl0aW9uczoKICAgICAgICAgICAgaWYgKG5hbWUuY2hhckF0KDApID09PSAidCIgJiYKICAgICAgICAgICAgICAgIGhhc093bi5jYWxsKHRoaXMsIG5hbWUpICYmCiAgICAgICAgICAgICAgICAhaXNOYU4oK25hbWUuc2xpY2UoMSkpKSB7CiAgICAgICAgICAgICAgdGhpc1tuYW1lXSA9IHVuZGVmaW5lZCQxOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAoKICAgICAgc3RvcDogZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5kb25lID0gdHJ1ZTsKCiAgICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMudHJ5RW50cmllc1swXTsKICAgICAgICB2YXIgcm9vdFJlY29yZCA9IHJvb3RFbnRyeS5jb21wbGV0aW9uOwogICAgICAgIGlmIChyb290UmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIHRocm93IHJvb3RSZWNvcmQuYXJnOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMucnZhbDsKICAgICAgfSwKCiAgICAgIGRpc3BhdGNoRXhjZXB0aW9uOiBmdW5jdGlvbihleGNlcHRpb24pIHsKICAgICAgICBpZiAodGhpcy5kb25lKSB7CiAgICAgICAgICB0aHJvdyBleGNlcHRpb247CiAgICAgICAgfQoKICAgICAgICB2YXIgY29udGV4dCA9IHRoaXM7CiAgICAgICAgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7CiAgICAgICAgICByZWNvcmQudHlwZSA9ICJ0aHJvdyI7CiAgICAgICAgICByZWNvcmQuYXJnID0gZXhjZXB0aW9uOwogICAgICAgICAgY29udGV4dC5uZXh0ID0gbG9jOwoKICAgICAgICAgIGlmIChjYXVnaHQpIHsKICAgICAgICAgICAgLy8gSWYgdGhlIGRpc3BhdGNoZWQgZXhjZXB0aW9uIHdhcyBjYXVnaHQgYnkgYSBjYXRjaCBibG9jaywKICAgICAgICAgICAgLy8gdGhlbiBsZXQgdGhhdCBjYXRjaCBibG9jayBoYW5kbGUgdGhlIGV4Y2VwdGlvbiBub3JtYWxseS4KICAgICAgICAgICAgY29udGV4dC5tZXRob2QgPSAibmV4dCI7CiAgICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuICEhIGNhdWdodDsKICAgICAgICB9CgogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uOwoKICAgICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09ICJyb290IikgewogICAgICAgICAgICAvLyBFeGNlcHRpb24gdGhyb3duIG91dHNpZGUgb2YgYW55IHRyeSBibG9jayB0aGF0IGNvdWxkIGhhbmRsZQogICAgICAgICAgICAvLyBpdCwgc28gc2V0IHRoZSBjb21wbGV0aW9uIHZhbHVlIG9mIHRoZSBlbnRpcmUgZnVuY3Rpb24gdG8KICAgICAgICAgICAgLy8gdGhyb3cgdGhlIGV4Y2VwdGlvbi4KICAgICAgICAgICAgcmV0dXJuIGhhbmRsZSgiZW5kIik7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYpIHsKICAgICAgICAgICAgdmFyIGhhc0NhdGNoID0gaGFzT3duLmNhbGwoZW50cnksICJjYXRjaExvYyIpOwogICAgICAgICAgICB2YXIgaGFzRmluYWxseSA9IGhhc093bi5jYWxsKGVudHJ5LCAiZmluYWxseUxvYyIpOwoKICAgICAgICAgICAgaWYgKGhhc0NhdGNoICYmIGhhc0ZpbmFsbHkpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHsKICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsIHRydWUpOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgewogICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsKICAgICAgICAgICAgICB9CgogICAgICAgICAgICB9IGVsc2UgaWYgKGhhc0NhdGNoKSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCB0cnVlKTsKICAgICAgICAgICAgICB9CgogICAgICAgICAgICB9IGVsc2UgaWYgKGhhc0ZpbmFsbHkpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgewogICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsKICAgICAgICAgICAgICB9CgogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigidHJ5IHN0YXRlbWVudCB3aXRob3V0IGNhdGNoIG9yIGZpbmFsbHkiKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKCiAgICAgIGFicnVwdDogZnVuY3Rpb24odHlwZSwgYXJnKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYgJiYKICAgICAgICAgICAgICBoYXNPd24uY2FsbChlbnRyeSwgImZpbmFsbHlMb2MiKSAmJgogICAgICAgICAgICAgIHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgdmFyIGZpbmFsbHlFbnRyeSA9IGVudHJ5OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChmaW5hbGx5RW50cnkgJiYKICAgICAgICAgICAgKHR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgICAgIHR5cGUgPT09ICJjb250aW51ZSIpICYmCiAgICAgICAgICAgIGZpbmFsbHlFbnRyeS50cnlMb2MgPD0gYXJnICYmCiAgICAgICAgICAgIGFyZyA8PSBmaW5hbGx5RW50cnkuZmluYWxseUxvYykgewogICAgICAgICAgLy8gSWdub3JlIHRoZSBmaW5hbGx5IGVudHJ5IGlmIGNvbnRyb2wgaXMgbm90IGp1bXBpbmcgdG8gYQogICAgICAgICAgLy8gbG9jYXRpb24gb3V0c2lkZSB0aGUgdHJ5L2NhdGNoIGJsb2NrLgogICAgICAgICAgZmluYWxseUVudHJ5ID0gbnVsbDsKICAgICAgICB9CgogICAgICAgIHZhciByZWNvcmQgPSBmaW5hbGx5RW50cnkgPyBmaW5hbGx5RW50cnkuY29tcGxldGlvbiA6IHt9OwogICAgICAgIHJlY29yZC50eXBlID0gdHlwZTsKICAgICAgICByZWNvcmQuYXJnID0gYXJnOwoKICAgICAgICBpZiAoZmluYWxseUVudHJ5KSB7CiAgICAgICAgICB0aGlzLm1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgIHRoaXMubmV4dCA9IGZpbmFsbHlFbnRyeS5maW5hbGx5TG9jOwogICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5jb21wbGV0ZShyZWNvcmQpOwogICAgICB9LAoKICAgICAgY29tcGxldGU6IGZ1bmN0aW9uKHJlY29yZCwgYWZ0ZXJMb2MpIHsKICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIHRocm93IHJlY29yZC5hcmc7CiAgICAgICAgfQoKICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgICAgcmVjb3JkLnR5cGUgPT09ICJjb250aW51ZSIpIHsKICAgICAgICAgIHRoaXMubmV4dCA9IHJlY29yZC5hcmc7CiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gInJldHVybiIpIHsKICAgICAgICAgIHRoaXMucnZhbCA9IHRoaXMuYXJnID0gcmVjb3JkLmFyZzsKICAgICAgICAgIHRoaXMubWV0aG9kID0gInJldHVybiI7CiAgICAgICAgICB0aGlzLm5leHQgPSAiZW5kIjsKICAgICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSAibm9ybWFsIiAmJiBhZnRlckxvYykgewogICAgICAgICAgdGhpcy5uZXh0ID0gYWZ0ZXJMb2M7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgfSwKCiAgICAgIGZpbmlzaDogZnVuY3Rpb24oZmluYWxseUxvYykgewogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICAgIGlmIChlbnRyeS5maW5hbGx5TG9jID09PSBmaW5hbGx5TG9jKSB7CiAgICAgICAgICAgIHRoaXMuY29tcGxldGUoZW50cnkuY29tcGxldGlvbiwgZW50cnkuYWZ0ZXJMb2MpOwogICAgICAgICAgICByZXNldFRyeUVudHJ5KGVudHJ5KTsKICAgICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAoKICAgICAgImNhdGNoIjogZnVuY3Rpb24odHJ5TG9jKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA9PT0gdHJ5TG9jKSB7CiAgICAgICAgICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uOwogICAgICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgICB2YXIgdGhyb3duID0gcmVjb3JkLmFyZzsKICAgICAgICAgICAgICByZXNldFRyeUVudHJ5KGVudHJ5KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhyb3duOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gVGhlIGNvbnRleHQuY2F0Y2ggbWV0aG9kIG11c3Qgb25seSBiZSBjYWxsZWQgd2l0aCBhIGxvY2F0aW9uCiAgICAgICAgLy8gYXJndW1lbnQgdGhhdCBjb3JyZXNwb25kcyB0byBhIGtub3duIGNhdGNoIGJsb2NrLgogICAgICAgIHRocm93IG5ldyBFcnJvcigiaWxsZWdhbCBjYXRjaCBhdHRlbXB0Iik7CiAgICAgIH0sCgogICAgICBkZWxlZ2F0ZVlpZWxkOiBmdW5jdGlvbihpdGVyYWJsZSwgcmVzdWx0TmFtZSwgbmV4dExvYykgewogICAgICAgIHRoaXMuZGVsZWdhdGUgPSB7CiAgICAgICAgICBpdGVyYXRvcjogdmFsdWVzKGl0ZXJhYmxlKSwKICAgICAgICAgIHJlc3VsdE5hbWU6IHJlc3VsdE5hbWUsCiAgICAgICAgICBuZXh0TG9jOiBuZXh0TG9jCiAgICAgICAgfTsKCiAgICAgICAgaWYgKHRoaXMubWV0aG9kID09PSAibmV4dCIpIHsKICAgICAgICAgIC8vIERlbGliZXJhdGVseSBmb3JnZXQgdGhlIGxhc3Qgc2VudCB2YWx1ZSBzbyB0aGF0IHdlIGRvbid0CiAgICAgICAgICAvLyBhY2NpZGVudGFsbHkgcGFzcyBpdCBvbiB0byB0aGUgZGVsZWdhdGUuCiAgICAgICAgICB0aGlzLmFyZyA9IHVuZGVmaW5lZCQxOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgIH0KICAgIH07CgogICAgLy8gUmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoaXMgc2NyaXB0IGlzIGV4ZWN1dGluZyBhcyBhIENvbW1vbkpTIG1vZHVsZQogICAgLy8gb3Igbm90LCByZXR1cm4gdGhlIHJ1bnRpbWUgb2JqZWN0IHNvIHRoYXQgd2UgY2FuIGRlY2xhcmUgdGhlIHZhcmlhYmxlCiAgICAvLyByZWdlbmVyYXRvclJ1bnRpbWUgaW4gdGhlIG91dGVyIHNjb3BlLCB3aGljaCBhbGxvd3MgdGhpcyBtb2R1bGUgdG8gYmUKICAgIC8vIGluamVjdGVkIGVhc2lseSBieSBgYmluL3JlZ2VuZXJhdG9yIC0taW5jbHVkZS1ydW50aW1lIHNjcmlwdC5qc2AuCiAgICByZXR1cm4gZXhwb3J0czsKCiAgfSgKICAgIC8vIElmIHRoaXMgc2NyaXB0IGlzIGV4ZWN1dGluZyBhcyBhIENvbW1vbkpTIG1vZHVsZSwgdXNlIG1vZHVsZS5leHBvcnRzCiAgICAvLyBhcyB0aGUgcmVnZW5lcmF0b3JSdW50aW1lIG5hbWVzcGFjZS4gT3RoZXJ3aXNlIGNyZWF0ZSBhIG5ldyBlbXB0eQogICAgLy8gb2JqZWN0LiBFaXRoZXIgd2F5LCB0aGUgcmVzdWx0aW5nIG9iamVjdCB3aWxsIGJlIHVzZWQgdG8gaW5pdGlhbGl6ZQogICAgLy8gdGhlIHJlZ2VuZXJhdG9yUnVudGltZSB2YXJpYWJsZSBhdCB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgIG1vZHVsZS5leHBvcnRzIAogICkpOwoKICB0cnkgewogICAgcmVnZW5lcmF0b3JSdW50aW1lID0gcnVudGltZTsKICB9IGNhdGNoIChhY2NpZGVudGFsU3RyaWN0TW9kZSkgewogICAgLy8gVGhpcyBtb2R1bGUgc2hvdWxkIG5vdCBiZSBydW5uaW5nIGluIHN0cmljdCBtb2RlLCBzbyB0aGUgYWJvdmUKICAgIC8vIGFzc2lnbm1lbnQgc2hvdWxkIGFsd2F5cyB3b3JrIHVubGVzcyBzb21ldGhpbmcgaXMgbWlzY29uZmlndXJlZC4gSnVzdAogICAgLy8gaW4gY2FzZSBydW50aW1lLmpzIGFjY2lkZW50YWxseSBydW5zIGluIHN0cmljdCBtb2RlLCBpbiBtb2Rlcm4gZW5naW5lcwogICAgLy8gd2UgY2FuIGV4cGxpY2l0bHkgYWNjZXNzIGdsb2JhbFRoaXMuIEluIG9sZGVyIGVuZ2luZXMgd2UgY2FuIGVzY2FwZQogICAgLy8gc3RyaWN0IG1vZGUgdXNpbmcgYSBnbG9iYWwgRnVuY3Rpb24gY2FsbC4gVGhpcyBjb3VsZCBjb25jZWl2YWJseSBmYWlsCiAgICAvLyBpZiBhIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5IGZvcmJpZHMgdXNpbmcgRnVuY3Rpb24sIGJ1dCBpbiB0aGF0IGNhc2UKICAgIC8vIHRoZSBwcm9wZXIgc29sdXRpb24gaXMgdG8gZml4IHRoZSBhY2NpZGVudGFsIHN0cmljdCBtb2RlIHByb2JsZW0uIElmCiAgICAvLyB5b3UndmUgbWlzY29uZmlndXJlZCB5b3VyIGJ1bmRsZXIgdG8gZm9yY2Ugc3RyaWN0IG1vZGUgYW5kIGFwcGxpZWQgYQogICAgLy8gQ1NQIHRvIGZvcmJpZCBGdW5jdGlvbiwgYW5kIHlvdSdyZSBub3Qgd2lsbGluZyB0byBmaXggZWl0aGVyIG9mIHRob3NlCiAgICAvLyBwcm9ibGVtcywgcGxlYXNlIGRldGFpbCB5b3VyIHVuaXF1ZSBwcmVkaWNhbWVudCBpbiBhIEdpdEh1YiBpc3N1ZS4KICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gIm9iamVjdCIpIHsKICAgICAgZ2xvYmFsVGhpcy5yZWdlbmVyYXRvclJ1bnRpbWUgPSBydW50aW1lOwogICAgfSBlbHNlIHsKICAgICAgRnVuY3Rpb24oInIiLCAicmVnZW5lcmF0b3JSdW50aW1lID0gciIpKHJ1bnRpbWUpOwogICAgfQogIH0KICB9KTsKCiAgdmFyIG1hcnRpbmkgPSBudWxsOwoKICBmdW5jdGlvbiBkZWNvZGVUZXJyYWluKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHZhciBfbWFydGluaTsKCiAgICB2YXIgaW1hZ2VEYXRhID0gcGFyYW1ldGVycy5pbWFnZURhdGEsCiAgICAgICAgX3BhcmFtZXRlcnMkdGlsZVNpemUgPSBwYXJhbWV0ZXJzLnRpbGVTaXplLAogICAgICAgIHRpbGVTaXplID0gX3BhcmFtZXRlcnMkdGlsZVNpemUgPT09IHZvaWQgMCA/IDI1NiA6IF9wYXJhbWV0ZXJzJHRpbGVTaXplLAogICAgICAgIGVycm9yTGV2ZWwgPSBwYXJhbWV0ZXJzLmVycm9yTGV2ZWwsCiAgICAgICAgaW50ZXJ2YWwgPSBwYXJhbWV0ZXJzLmludGVydmFsLAogICAgICAgIG9mZnNldCA9IHBhcmFtZXRlcnMub2Zmc2V0OwogICAgdmFyIHBpeGVscyA9IG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoaW1hZ2VEYXRhKSwgW3RpbGVTaXplLCB0aWxlU2l6ZSwgNF0sIFs0LCA0ICogdGlsZVNpemUsIDFdLCAwKTsgLy8gVGlsZSBzaXplIG11c3QgYmUgbWFpbnRhaW5lZCB0aHJvdWdoIHRoZSBsaWZlIG9mIHRoZSB3b3JrZXIKCiAgICAoX21hcnRpbmkgPSBtYXJ0aW5pKSAhPT0gbnVsbCAmJiBfbWFydGluaSAhPT0gdm9pZCAwID8gX21hcnRpbmkgOiBtYXJ0aW5pID0gbmV3IE1hcnRpbmkodGlsZVNpemUgKyAxKTsKICAgIHZhciB0ZXJyYWluID0gbWFwYm94VGVycmFpblRvR3JpZChwaXhlbHMsIGludGVydmFsLCBvZmZzZXQpOwogICAgdmFyIHRpbGUgPSBtYXJ0aW5pLmNyZWF0ZVRpbGUodGVycmFpbik7IC8vIGdldCBhIG1lc2ggKHZlcnRpY2VzIGFuZCB0cmlhbmdsZXMgaW5kaWNlcykgZm9yIGEgMTBtIGVycm9yCgogICAgdmFyIG1lc2ggPSB0aWxlLmdldE1lc2goZXJyb3JMZXZlbCwgcGFyYW1ldGVycy5tYXhMZW5ndGgpOwogICAgcmV0dXJuIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplKTsKICB9CgogIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKG1zZykgewogICAgdmFyIF9tc2ckZGF0YSA9IG1zZy5kYXRhLAogICAgICAgIGlkID0gX21zZyRkYXRhLmlkLAogICAgICAgIHBheWxvYWQgPSBfbXNnJGRhdGEucGF5bG9hZDsKICAgIGlmIChpZCA9PSBudWxsKSByZXR1cm47CiAgICB2YXIgb2JqZWN0cyA9IFtdOwogICAgdmFyIHJlcyA9IG51bGw7CgogICAgdHJ5IHsKICAgICAgcmVzID0gZGVjb2RlVGVycmFpbihwYXlsb2FkKTsKICAgICAgb2JqZWN0cy5wdXNoKHJlcy5pbmRpY2VzLmJ1ZmZlcik7CiAgICAgIG9iamVjdHMucHVzaChyZXMucXVhbnRpemVkVmVydGljZXMuYnVmZmVyKTsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIHBheWxvYWQ6IHJlcwogICAgICB9LCBvYmplY3RzKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogaWQsCiAgICAgICAgZXJyOiBlcnIudG9TdHJpbmcoKQogICAgICB9KTsKICAgIH0gZmluYWxseSB7CiAgICAgIHJlcyA9IG51bGw7CiAgICAgIG9iamVjdHMgPSBudWxsOwogICAgfQogIH07CgogIGV4cG9ydHMuZGVjb2RlVGVycmFpbiA9IGRlY29kZVRlcnJhaW47CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7CgogIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwoK', null, false);
|
|
142
481
|
/* eslint-enable */
|
|
143
482
|
|
|
144
483
|
var resolves = {};
|
|
@@ -255,12 +594,16 @@ var WorkerFarm = /*#__PURE__*/function () {
|
|
|
255
594
|
// We should save these
|
|
256
595
|
//const canvas = new OffscreenCanvas(256, 256);
|
|
257
596
|
//const ctx = canvas.getContext("2d");
|
|
258
|
-
function mapboxTerrainToGrid(png) {
|
|
597
|
+
function mapboxTerrainToGrid(png, interval, offset) {
|
|
598
|
+
var _interval, _offset;
|
|
599
|
+
|
|
259
600
|
// maybe we should do this on the GPU using REGL?
|
|
260
601
|
// but that would require GPU -> CPU -> GPU
|
|
261
602
|
var gridSize = png.shape[0] + 1;
|
|
262
603
|
var terrain = new Float32Array(gridSize * gridSize);
|
|
263
|
-
var tileSize = png.shape[0];
|
|
604
|
+
var tileSize = png.shape[0];
|
|
605
|
+
interval = (_interval = interval) !== null && _interval !== void 0 ? _interval : 0.1;
|
|
606
|
+
offset = (_offset = offset) !== null && _offset !== void 0 ? _offset : -10000; // decode terrain values
|
|
264
607
|
|
|
265
608
|
for (var y = 0; y < tileSize; y++) {
|
|
266
609
|
for (var x = 0; x < tileSize; x++) {
|
|
@@ -268,7 +611,7 @@ function mapboxTerrainToGrid(png) {
|
|
|
268
611
|
var r = png.get(x, yc, 0);
|
|
269
612
|
var g = png.get(x, yc, 1);
|
|
270
613
|
var b = png.get(x, yc, 2);
|
|
271
|
-
terrain[y * gridSize + x] = r * 256 * 256
|
|
614
|
+
terrain[y * gridSize + x] = r * 256 * 256 * interval + g * 256.0 * interval + b * interval + offset;
|
|
272
615
|
}
|
|
273
616
|
} // backfill right and bottom borders
|
|
274
617
|
|
|
@@ -284,6 +627,74 @@ function mapboxTerrainToGrid(png) {
|
|
|
284
627
|
return terrain;
|
|
285
628
|
}
|
|
286
629
|
|
|
630
|
+
function _emptyMesh(n) {
|
|
631
|
+
n = Math.max(n, 2);
|
|
632
|
+
var nTriangles = Math.pow(n - 1, 2) * 2;
|
|
633
|
+
var nVertices = Math.pow(n, 2);
|
|
634
|
+
var quantizedVertices = new Uint16Array(nVertices * 3);
|
|
635
|
+
var indices = new Uint16Array(nTriangles * 3);
|
|
636
|
+
var westIndices = [];
|
|
637
|
+
var southIndices = [];
|
|
638
|
+
var eastIndices = [];
|
|
639
|
+
var northIndices = [];
|
|
640
|
+
var tix = 0;
|
|
641
|
+
|
|
642
|
+
for (var i = 0; i < nVertices; i++) {
|
|
643
|
+
var rx = i % n; //* 32767) / (n - 1);
|
|
644
|
+
|
|
645
|
+
var ry = Math.floor(i / n); //* 32767) / (n - 1);
|
|
646
|
+
|
|
647
|
+
var ix = n * rx + ry;
|
|
648
|
+
quantizedVertices[ix] = rx * 32768 / (n - 1);
|
|
649
|
+
quantizedVertices[nVertices + ix] = ry * 32768 / (n - 1);
|
|
650
|
+
quantizedVertices[2 * nVertices + ix] = 0;
|
|
651
|
+
if (ry == 0) westIndices.push(ix);
|
|
652
|
+
if (rx == 0) southIndices.push(ix);
|
|
653
|
+
if (rx == n - 1) eastIndices.push(ix);
|
|
654
|
+
if (ry == n - 1) northIndices.push(ix); // Add triangles
|
|
655
|
+
|
|
656
|
+
var rix = i - ry * n;
|
|
657
|
+
|
|
658
|
+
if (rix != n - 1) {
|
|
659
|
+
indices[tix * 3] = i;
|
|
660
|
+
indices[tix * 3 + 1] = i + n + 1;
|
|
661
|
+
indices[tix * 3 + 2] = i + 1;
|
|
662
|
+
tix++;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (rix != 0) {
|
|
666
|
+
indices[tix * 3] = i - 1;
|
|
667
|
+
indices[tix * 3 + 1] = i + n - 1;
|
|
668
|
+
indices[tix * 3 + 2] = i + n;
|
|
669
|
+
tix++;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return {
|
|
674
|
+
minimumHeight: 0,
|
|
675
|
+
maximumHeight: 0,
|
|
676
|
+
quantizedVertices: quantizedVertices,
|
|
677
|
+
indices: indices,
|
|
678
|
+
westIndices: westIndices,
|
|
679
|
+
southIndices: southIndices,
|
|
680
|
+
eastIndices: eastIndices,
|
|
681
|
+
northIndices: northIndices
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
var _meshCache = [];
|
|
686
|
+
function emptyMesh(n) {
|
|
687
|
+
// A memoized function to return empty meshes
|
|
688
|
+
if (n in _meshCache) {
|
|
689
|
+
return _meshCache[n];
|
|
690
|
+
} else {
|
|
691
|
+
var result = _emptyMesh(n);
|
|
692
|
+
|
|
693
|
+
_meshCache[n] = result;
|
|
694
|
+
return result;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
287
698
|
function createQuantizedMeshData(tile, mesh, tileSize) {
|
|
288
699
|
var xvals = [];
|
|
289
700
|
var yvals = [];
|
|
@@ -988,9 +1399,9 @@ var runtime = (function (exports) {
|
|
|
988
1399
|
// This is a polyfill for %IteratorPrototype% for environments that
|
|
989
1400
|
// don't natively support it.
|
|
990
1401
|
var IteratorPrototype = {};
|
|
991
|
-
IteratorPrototype
|
|
1402
|
+
define(IteratorPrototype, iteratorSymbol, function () {
|
|
992
1403
|
return this;
|
|
993
|
-
};
|
|
1404
|
+
});
|
|
994
1405
|
|
|
995
1406
|
var getProto = Object.getPrototypeOf;
|
|
996
1407
|
var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
|
|
@@ -1004,8 +1415,9 @@ var runtime = (function (exports) {
|
|
|
1004
1415
|
|
|
1005
1416
|
var Gp = GeneratorFunctionPrototype.prototype =
|
|
1006
1417
|
Generator.prototype = Object.create(IteratorPrototype);
|
|
1007
|
-
GeneratorFunction.prototype =
|
|
1008
|
-
|
|
1418
|
+
GeneratorFunction.prototype = GeneratorFunctionPrototype;
|
|
1419
|
+
define(Gp, "constructor", GeneratorFunctionPrototype);
|
|
1420
|
+
define(GeneratorFunctionPrototype, "constructor", GeneratorFunction);
|
|
1009
1421
|
GeneratorFunction.displayName = define(
|
|
1010
1422
|
GeneratorFunctionPrototype,
|
|
1011
1423
|
toStringTagSymbol,
|
|
@@ -1119,9 +1531,9 @@ var runtime = (function (exports) {
|
|
|
1119
1531
|
}
|
|
1120
1532
|
|
|
1121
1533
|
defineIteratorMethods(AsyncIterator.prototype);
|
|
1122
|
-
AsyncIterator.prototype
|
|
1534
|
+
define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
|
|
1123
1535
|
return this;
|
|
1124
|
-
};
|
|
1536
|
+
});
|
|
1125
1537
|
exports.AsyncIterator = AsyncIterator;
|
|
1126
1538
|
|
|
1127
1539
|
// Note that simple async functions are implemented on top of
|
|
@@ -1314,13 +1726,13 @@ var runtime = (function (exports) {
|
|
|
1314
1726
|
// iterator prototype chain incorrectly implement this, causing the Generator
|
|
1315
1727
|
// object to not be returned from this call. This ensures that doesn't happen.
|
|
1316
1728
|
// See https://github.com/facebook/regenerator/issues/274 for more details.
|
|
1317
|
-
Gp
|
|
1729
|
+
define(Gp, iteratorSymbol, function() {
|
|
1318
1730
|
return this;
|
|
1319
|
-
};
|
|
1731
|
+
});
|
|
1320
1732
|
|
|
1321
|
-
Gp
|
|
1733
|
+
define(Gp, "toString", function() {
|
|
1322
1734
|
return "[object Generator]";
|
|
1323
|
-
};
|
|
1735
|
+
});
|
|
1324
1736
|
|
|
1325
1737
|
function pushTryEntry(locs) {
|
|
1326
1738
|
var entry = { tryLoc: locs[0] };
|
|
@@ -1639,14 +2051,19 @@ try {
|
|
|
1639
2051
|
} catch (accidentalStrictMode) {
|
|
1640
2052
|
// This module should not be running in strict mode, so the above
|
|
1641
2053
|
// assignment should always work unless something is misconfigured. Just
|
|
1642
|
-
// in case runtime.js accidentally runs in strict mode,
|
|
2054
|
+
// in case runtime.js accidentally runs in strict mode, in modern engines
|
|
2055
|
+
// we can explicitly access globalThis. In older engines we can escape
|
|
1643
2056
|
// strict mode using a global Function call. This could conceivably fail
|
|
1644
2057
|
// if a Content Security Policy forbids using Function, but in that case
|
|
1645
2058
|
// the proper solution is to fix the accidental strict mode problem. If
|
|
1646
2059
|
// you've misconfigured your bundler to force strict mode and applied a
|
|
1647
2060
|
// CSP to forbid Function, and you're not willing to fix either of those
|
|
1648
2061
|
// problems, please detail your unique predicament in a GitHub issue.
|
|
1649
|
-
|
|
2062
|
+
if (typeof globalThis === "object") {
|
|
2063
|
+
globalThis.regeneratorRuntime = runtime;
|
|
2064
|
+
} else {
|
|
2065
|
+
Function("r", "regeneratorRuntime = r")(runtime);
|
|
2066
|
+
}
|
|
1650
2067
|
}
|
|
1651
2068
|
});
|
|
1652
2069
|
|
|
@@ -1658,11 +2075,13 @@ function decodeTerrain(parameters, transferableObjects) {
|
|
|
1658
2075
|
var imageData = parameters.imageData,
|
|
1659
2076
|
_parameters$tileSize = parameters.tileSize,
|
|
1660
2077
|
tileSize = _parameters$tileSize === void 0 ? 256 : _parameters$tileSize,
|
|
1661
|
-
errorLevel = parameters.errorLevel
|
|
2078
|
+
errorLevel = parameters.errorLevel,
|
|
2079
|
+
interval = parameters.interval,
|
|
2080
|
+
offset = parameters.offset;
|
|
1662
2081
|
var pixels = ndarray(new Uint8Array(imageData), [tileSize, tileSize, 4], [4, 4 * tileSize, 1], 0); // Tile size must be maintained through the life of the worker
|
|
1663
2082
|
|
|
1664
2083
|
(_martini = martini) !== null && _martini !== void 0 ? _martini : martini = new Martini(tileSize + 1);
|
|
1665
|
-
var terrain = mapboxTerrainToGrid(pixels);
|
|
2084
|
+
var terrain = mapboxTerrainToGrid(pixels, interval, offset);
|
|
1666
2085
|
var tile = martini.createTile(terrain); // get a mesh (vertices and triangles indices) for a 10m error
|
|
1667
2086
|
|
|
1668
2087
|
var mesh = tile.getMesh(errorLevel, parameters.maxLength);
|
|
@@ -1696,34 +2115,42 @@ self.onmessage = function (msg) {
|
|
|
1696
2115
|
}
|
|
1697
2116
|
};
|
|
1698
2117
|
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
var ImageFormat;
|
|
2118
|
+
var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
|
|
2119
|
+
_inherits(StretchedTilingScheme, _WebMercatorTilingSch);
|
|
1702
2120
|
|
|
1703
|
-
|
|
1704
|
-
ImageFormat["WEBP"] = "webp";
|
|
1705
|
-
ImageFormat["PNG"] = "png";
|
|
1706
|
-
ImageFormat["PNGRAW"] = "pngraw";
|
|
1707
|
-
})(ImageFormat || (ImageFormat = {}));
|
|
2121
|
+
var _super = _createSuper(StretchedTilingScheme);
|
|
1708
2122
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
2123
|
+
function StretchedTilingScheme() {
|
|
2124
|
+
_classCallCheck(this, StretchedTilingScheme);
|
|
2125
|
+
|
|
2126
|
+
return _super.apply(this, arguments);
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
_createClass(StretchedTilingScheme, [{
|
|
2130
|
+
key: "tileXYToRectangle",
|
|
2131
|
+
value: function tileXYToRectangle(x, y, level, res) {
|
|
2132
|
+
var result = _get(_getPrototypeOf(StretchedTilingScheme.prototype), "tileXYToRectangle", this).call(this, x, y, level);
|
|
2133
|
+
|
|
2134
|
+
if (y == 0) {
|
|
2135
|
+
//console.log("Top row", res, y, level);
|
|
2136
|
+
result.north = Math.PI / 2;
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
if (y + 1 == Math.pow(2, level)) {
|
|
2140
|
+
result.south = -Math.PI / 2;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
return result;
|
|
2144
|
+
}
|
|
2145
|
+
}]);
|
|
2146
|
+
|
|
2147
|
+
return StretchedTilingScheme;
|
|
2148
|
+
}(cesium.WebMercatorTilingScheme);
|
|
1722
2149
|
|
|
1723
2150
|
var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
1724
2151
|
// @ts-ignore
|
|
1725
2152
|
function MartiniTerrainProvider() {
|
|
1726
|
-
var _opts$
|
|
2153
|
+
var _opts$interval, _opts$offset, _opts$maxWorkers, _opts$minZoomLevel, _opts$fillPoles, _opts$detailScalar, _opts$minimumErrorLev, _opts$ellipsoid;
|
|
1727
2154
|
|
|
1728
2155
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1729
2156
|
|
|
@@ -1747,106 +2174,75 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1747
2174
|
|
|
1748
2175
|
_defineProperty(this, "ellipsoid", void 0);
|
|
1749
2176
|
|
|
1750
|
-
_defineProperty(this, "
|
|
2177
|
+
_defineProperty(this, "workerFarm", null);
|
|
1751
2178
|
|
|
1752
|
-
_defineProperty(this, "
|
|
2179
|
+
_defineProperty(this, "inProgressWorkers", 0);
|
|
1753
2180
|
|
|
1754
|
-
_defineProperty(this, "
|
|
2181
|
+
_defineProperty(this, "levelOfDetailScalar", null);
|
|
1755
2182
|
|
|
1756
|
-
_defineProperty(this, "
|
|
2183
|
+
_defineProperty(this, "maxWorkers", 5);
|
|
1757
2184
|
|
|
1758
|
-
_defineProperty(this, "
|
|
2185
|
+
_defineProperty(this, "minError", 0.1);
|
|
1759
2186
|
|
|
1760
|
-
_defineProperty(this, "
|
|
2187
|
+
_defineProperty(this, "minZoomLevel", void 0);
|
|
1761
2188
|
|
|
1762
|
-
_defineProperty(this, "
|
|
2189
|
+
_defineProperty(this, "fillPoles", true);
|
|
1763
2190
|
|
|
1764
|
-
_defineProperty(this, "
|
|
2191
|
+
_defineProperty(this, "_errorAtMinZoom", 1000);
|
|
1765
2192
|
|
|
1766
|
-
_defineProperty(this, "
|
|
2193
|
+
_defineProperty(this, "resource", null);
|
|
1767
2194
|
|
|
1768
|
-
_defineProperty(this, "
|
|
2195
|
+
_defineProperty(this, "interval", void 0);
|
|
1769
2196
|
|
|
1770
|
-
_defineProperty(this, "
|
|
2197
|
+
_defineProperty(this, "offset", void 0);
|
|
1771
2198
|
|
|
1772
2199
|
_defineProperty(this, "RADIUS_SCALAR", 1.0);
|
|
1773
2200
|
|
|
1774
2201
|
//this.martini = new Martini(257);
|
|
1775
|
-
this.
|
|
1776
|
-
this.
|
|
1777
|
-
this.
|
|
1778
|
-
this.
|
|
1779
|
-
this.
|
|
2202
|
+
this.resource = opts.resource;
|
|
2203
|
+
this.interval = (_opts$interval = opts.interval) !== null && _opts$interval !== void 0 ? _opts$interval : 0.1;
|
|
2204
|
+
this.offset = (_opts$offset = opts.offset) !== null && _opts$offset !== void 0 ? _opts$offset : -10000;
|
|
2205
|
+
this.maxWorkers = (_opts$maxWorkers = opts.maxWorkers) !== null && _opts$maxWorkers !== void 0 ? _opts$maxWorkers : 5;
|
|
2206
|
+
this.minZoomLevel = (_opts$minZoomLevel = opts.minZoomLevel) !== null && _opts$minZoomLevel !== void 0 ? _opts$minZoomLevel : 3;
|
|
2207
|
+
this.fillPoles = (_opts$fillPoles = opts.fillPoles) !== null && _opts$fillPoles !== void 0 ? _opts$fillPoles : true;
|
|
1780
2208
|
this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 4.0) + cesium.Math.EPSILON5;
|
|
1781
2209
|
this.ready = true;
|
|
1782
2210
|
this.readyPromise = Promise.resolve(true);
|
|
1783
|
-
this.accessToken = opts.accessToken;
|
|
1784
2211
|
this.minError = (_opts$minimumErrorLev = opts.minimumErrorLevel) !== null && _opts$minimumErrorLev !== void 0 ? _opts$minimumErrorLev : 0.1;
|
|
1785
2212
|
this.errorEvent.addEventListener(console.log, this);
|
|
1786
2213
|
this.ellipsoid = (_opts$ellipsoid = opts.ellipsoid) !== null && _opts$ellipsoid !== void 0 ? _opts$ellipsoid : cesium.Ellipsoid.WGS84;
|
|
1787
|
-
this.format = (_opts$format = opts.format) !== null && _opts$format !== void 0 ? _opts$format : ImageFormat.WEBP;
|
|
1788
2214
|
|
|
1789
|
-
if (this.
|
|
2215
|
+
if (this.maxWorkers > 0) {
|
|
1790
2216
|
this.workerFarm = new WorkerFarm();
|
|
1791
2217
|
}
|
|
1792
2218
|
|
|
1793
|
-
|
|
2219
|
+
var scheme = cesium.WebMercatorTilingScheme;
|
|
2220
|
+
|
|
2221
|
+
if (this.fillPoles) {
|
|
2222
|
+
scheme = StretchedTilingScheme;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
this.tilingScheme = new scheme({
|
|
1794
2226
|
numberOfLevelZeroTilesX: 1,
|
|
1795
2227
|
numberOfLevelZeroTilesY: 1,
|
|
1796
2228
|
ellipsoid: this.ellipsoid
|
|
1797
2229
|
});
|
|
2230
|
+
this._errorAtMinZoom = this.errorAtZoom(this.minZoomLevel);
|
|
1798
2231
|
}
|
|
1799
2232
|
|
|
1800
2233
|
_createClass(MartiniTerrainProvider, [{
|
|
1801
|
-
key: "getCanvas",
|
|
1802
|
-
value: function getCanvas() {
|
|
1803
|
-
var ctx = this.contextQueue.pop();
|
|
1804
|
-
|
|
1805
|
-
if (ctx == null) {
|
|
1806
|
-
var canvas = document.createElement("canvas");
|
|
1807
|
-
canvas.width = this.tileSize;
|
|
1808
|
-
canvas.height = this.tileSize;
|
|
1809
|
-
var context = canvas.getContext("2d");
|
|
1810
|
-
ctx = {
|
|
1811
|
-
canvas: canvas,
|
|
1812
|
-
context: context
|
|
1813
|
-
};
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
return ctx;
|
|
1817
|
-
}
|
|
1818
|
-
}, {
|
|
1819
|
-
key: "getPixels",
|
|
1820
|
-
value: function getPixels(img) {
|
|
1821
|
-
var canvasRef = this.getCanvas();
|
|
1822
|
-
var context = canvasRef.context; //context.scale(1, -1);
|
|
1823
|
-
// Chrome appears to vertically flip the image for reasons that are unclear
|
|
1824
|
-
// We can make it work in Chrome by drawing the image upside-down at this step.
|
|
1825
|
-
|
|
1826
|
-
context.drawImage(img, 0, 0, this.tileSize, this.tileSize);
|
|
1827
|
-
var pixels = context.getImageData(0, 0, this.tileSize, this.tileSize);
|
|
1828
|
-
context.clearRect(0, 0, this.tileSize, this.tileSize);
|
|
1829
|
-
this.contextQueue.push(canvasRef);
|
|
1830
|
-
return pixels;
|
|
1831
|
-
}
|
|
1832
|
-
}, {
|
|
1833
|
-
key: "buildTileURL",
|
|
1834
|
-
value: function buildTileURL(tileCoords) {
|
|
1835
|
-
var z = tileCoords.z,
|
|
1836
|
-
x = tileCoords.x,
|
|
1837
|
-
y = tileCoords.y;
|
|
1838
|
-
var hires = this.highResolution ? "@2x" : ""; // SKU token generation code: https://github.com/mapbox/mapbox-gl-js/blob/79f594fab76d932ccea0f171709718568af660e3/src/util/sku_token.js#L23
|
|
1839
|
-
// https://api.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}&sku=101EX9Btybqbj
|
|
1840
|
-
|
|
1841
|
-
return "https://api.mapbox.com/v4/mapbox.terrain-rgb/".concat(z, "/").concat(x, "/").concat(y).concat(hires, ".").concat(this.format, "?access_token=").concat(this.accessToken);
|
|
1842
|
-
}
|
|
1843
|
-
}, {
|
|
1844
2234
|
key: "requestTileGeometry",
|
|
1845
2235
|
value: function requestTileGeometry(x, y, z, request) {
|
|
1846
2236
|
var _this = this;
|
|
1847
2237
|
|
|
1848
|
-
|
|
1849
|
-
if (this.
|
|
2238
|
+
// Look for tiles both below the zoom level and below the error threshold for the zoom level at the equator...
|
|
2239
|
+
if (z < this.minZoomLevel || this.scaledErrorForTile(x, y, z) > this._errorAtMinZoom) {
|
|
2240
|
+
// If we are below the minimum zoom level, we return empty heightmaps
|
|
2241
|
+
// to avoid unnecessary requests for low-resolution data.
|
|
2242
|
+
return Promise.resolve(this.emptyMesh(x, y, z));
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
if (this.inProgressWorkers > this.maxWorkers) return undefined;
|
|
1850
2246
|
this.inProgressWorkers += 1;
|
|
1851
2247
|
return this.processTile(x, y, z)["finally"](function () {
|
|
1852
2248
|
_this.inProgressWorkers -= 1;
|
|
@@ -1856,30 +2252,28 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1856
2252
|
key: "processTile",
|
|
1857
2253
|
value: function () {
|
|
1858
2254
|
var _processTile = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(x, y, z) {
|
|
1859
|
-
var
|
|
2255
|
+
var _this$resource, tileSize, getTilePixels, px, pixelData, tileRect, err, maxLength, params, res;
|
|
2256
|
+
|
|
1860
2257
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
1861
2258
|
while (1) {
|
|
1862
2259
|
switch (_context.prev = _context.next) {
|
|
1863
2260
|
case 0:
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
_context.prev = 1;
|
|
1869
|
-
url = this.buildTileURL({
|
|
2261
|
+
_context.prev = 0;
|
|
2262
|
+
_this$resource = this.resource, tileSize = _this$resource.tileSize, getTilePixels = _this$resource.getTilePixels;
|
|
2263
|
+
_context.next = 4;
|
|
2264
|
+
return getTilePixels({
|
|
1870
2265
|
x: x,
|
|
1871
2266
|
y: y,
|
|
1872
2267
|
z: z
|
|
1873
2268
|
});
|
|
1874
|
-
_context.next = 5;
|
|
1875
|
-
return loadImage(url);
|
|
1876
2269
|
|
|
1877
|
-
case
|
|
1878
|
-
|
|
1879
|
-
px = this.getPixels(image);
|
|
2270
|
+
case 4:
|
|
2271
|
+
px = _context.sent;
|
|
1880
2272
|
pixelData = px.data;
|
|
1881
|
-
tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
|
|
1882
|
-
|
|
2273
|
+
tileRect = this.tilingScheme.tileXYToRectangle(x, y, z); ///const center = Rectangle.center(tileRect);
|
|
2274
|
+
|
|
2275
|
+
err = this.errorAtZoom(z);
|
|
2276
|
+
maxLength = this.maxVertexDistance(tileRect);
|
|
1883
2277
|
params = {
|
|
1884
2278
|
imageData: pixelData,
|
|
1885
2279
|
maxLength: maxLength,
|
|
@@ -1888,45 +2282,44 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1888
2282
|
z: z,
|
|
1889
2283
|
errorLevel: err,
|
|
1890
2284
|
ellipsoidRadius: this.ellipsoid.maximumRadius,
|
|
1891
|
-
tileSize:
|
|
2285
|
+
tileSize: tileSize,
|
|
2286
|
+
interval: this.interval,
|
|
2287
|
+
offset: this.offset
|
|
1892
2288
|
};
|
|
1893
2289
|
|
|
1894
2290
|
if (!(this.workerFarm != null)) {
|
|
1895
|
-
_context.next =
|
|
2291
|
+
_context.next = 16;
|
|
1896
2292
|
break;
|
|
1897
2293
|
}
|
|
1898
2294
|
|
|
1899
|
-
_context.next =
|
|
2295
|
+
_context.next = 13;
|
|
1900
2296
|
return this.workerFarm.scheduleTask(params, [pixelData.buffer]);
|
|
1901
2297
|
|
|
1902
|
-
case
|
|
2298
|
+
case 13:
|
|
1903
2299
|
res = _context.sent;
|
|
1904
|
-
_context.next =
|
|
2300
|
+
_context.next = 17;
|
|
1905
2301
|
break;
|
|
1906
2302
|
|
|
1907
|
-
case
|
|
2303
|
+
case 16:
|
|
1908
2304
|
res = decodeTerrain(params);
|
|
1909
2305
|
|
|
1910
|
-
case
|
|
2306
|
+
case 17:
|
|
1911
2307
|
pixelData = undefined;
|
|
1912
|
-
image = undefined;
|
|
1913
2308
|
px = undefined;
|
|
1914
2309
|
return _context.abrupt("return", this.createQuantizedMeshData(tileRect, err, res));
|
|
1915
2310
|
|
|
1916
|
-
case
|
|
1917
|
-
_context.prev =
|
|
1918
|
-
_context.t0 = _context["catch"](
|
|
1919
|
-
console.log(_context.t0);
|
|
1920
|
-
|
|
1921
|
-
v = Math.max(32 - 4 * z, 4);
|
|
1922
|
-
return _context.abrupt("return", this.emptyHeightmap(v));
|
|
2311
|
+
case 22:
|
|
2312
|
+
_context.prev = 22;
|
|
2313
|
+
_context.t0 = _context["catch"](0);
|
|
2314
|
+
console.log(_context.t0);
|
|
2315
|
+
return _context.abrupt("return", this.emptyMesh(x, y, z));
|
|
1923
2316
|
|
|
1924
|
-
case
|
|
2317
|
+
case 26:
|
|
1925
2318
|
case "end":
|
|
1926
2319
|
return _context.stop();
|
|
1927
2320
|
}
|
|
1928
2321
|
}
|
|
1929
|
-
}, _callee, this, [[
|
|
2322
|
+
}, _callee, this, [[0, 22]]);
|
|
1930
2323
|
}));
|
|
1931
2324
|
|
|
1932
2325
|
function processTile(_x, _x2, _x3) {
|
|
@@ -1936,10 +2329,33 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1936
2329
|
return processTile;
|
|
1937
2330
|
}()
|
|
1938
2331
|
}, {
|
|
1939
|
-
key: "
|
|
1940
|
-
value: function
|
|
2332
|
+
key: "errorAtZoom",
|
|
2333
|
+
value: function errorAtZoom(zoom) {
|
|
1941
2334
|
return Math.max(this.getLevelMaximumGeometricError(zoom) / this.levelOfDetailScalar, this.minError);
|
|
1942
2335
|
}
|
|
2336
|
+
}, {
|
|
2337
|
+
key: "scaledErrorForTile",
|
|
2338
|
+
value: function scaledErrorForTile(x, y, z) {
|
|
2339
|
+
var tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
|
|
2340
|
+
var center = cesium.Rectangle.center(tileRect);
|
|
2341
|
+
return this.errorAtZoom(z) / (1 - Math.sin(center.latitude));
|
|
2342
|
+
}
|
|
2343
|
+
}, {
|
|
2344
|
+
key: "maxVertexDistance",
|
|
2345
|
+
value: function maxVertexDistance(tileRect) {
|
|
2346
|
+
return Math.round(5 / tileRect.height);
|
|
2347
|
+
}
|
|
2348
|
+
}, {
|
|
2349
|
+
key: "emptyMesh",
|
|
2350
|
+
value: function emptyMesh$1(x, y, z) {
|
|
2351
|
+
var tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
|
|
2352
|
+
var v = Math.max(Math.ceil(256 / this.maxVertexDistance(tileRect)), 4);
|
|
2353
|
+
|
|
2354
|
+
var output = emptyMesh(v);
|
|
2355
|
+
|
|
2356
|
+
var err = this.errorAtZoom(z);
|
|
2357
|
+
return this.createQuantizedMeshData(tileRect, err, output);
|
|
2358
|
+
}
|
|
1943
2359
|
}, {
|
|
1944
2360
|
key: "createQuantizedMeshData",
|
|
1945
2361
|
value: function createQuantizedMeshData(tileRect, errorLevel, workerOutput) {
|
|
@@ -1953,16 +2369,19 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1953
2369
|
northIndices = workerOutput.northIndices;
|
|
1954
2370
|
var err = errorLevel;
|
|
1955
2371
|
var skirtHeight = err * 20;
|
|
1956
|
-
var center = cesium.Rectangle.center(tileRect); //
|
|
1957
|
-
// tileRect.width is given in radians
|
|
1958
|
-
// cos of half-tile-width allows us to use right-triangle relationship
|
|
2372
|
+
var center = cesium.Rectangle.center(tileRect); // Calculating occlusion height is kind of messy currently, but it definitely works
|
|
1959
2373
|
|
|
1960
|
-
var
|
|
1961
|
-
//
|
|
1962
|
-
|
|
1963
|
-
|
|
2374
|
+
var halfAngle = tileRect.width / 2;
|
|
2375
|
+
var dr = Math.cos(halfAngle); // half tile width since our ref point is at the center
|
|
2376
|
+
|
|
2377
|
+
var occlusionHeight = dr * this.ellipsoid.maximumRadius + maximumHeight;
|
|
2378
|
+
|
|
2379
|
+
if (halfAngle > Math.PI / 4) {
|
|
2380
|
+
occlusionHeight = (1 + halfAngle) * this.ellipsoid.maximumRadius;
|
|
2381
|
+
}
|
|
1964
2382
|
|
|
1965
|
-
var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude,
|
|
2383
|
+
var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude, occlusionHeight // Scaling factor of two just to be sure.
|
|
2384
|
+
);
|
|
1966
2385
|
var horizonOcclusionPoint = this.ellipsoid.transformPositionToScaledSpace(cesium.Cartographic.toCartesian(occlusionPoint));
|
|
1967
2386
|
var orientedBoundingBox = cesium.OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, this.tilingScheme.ellipsoid);
|
|
1968
2387
|
var boundingSphere = cesium.BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox); // SE NW NE
|
|
@@ -1985,20 +2404,8 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1985
2404
|
eastSkirtHeight: skirtHeight,
|
|
1986
2405
|
northSkirtHeight: skirtHeight,
|
|
1987
2406
|
childTileMask: 15
|
|
1988
|
-
}); //debugger;
|
|
1989
|
-
//if (tileRect.width < 0.01) debugger;
|
|
1990
|
-
//return this.emptyHeightmap(2);
|
|
1991
|
-
|
|
1992
|
-
return result;
|
|
1993
|
-
}
|
|
1994
|
-
}, {
|
|
1995
|
-
key: "emptyHeightmap",
|
|
1996
|
-
value: function emptyHeightmap(samples) {
|
|
1997
|
-
return new cesium.HeightmapTerrainData({
|
|
1998
|
-
buffer: new Uint8Array(Array(samples * samples).fill(0)),
|
|
1999
|
-
width: samples,
|
|
2000
|
-
height: samples
|
|
2001
2407
|
});
|
|
2408
|
+
return result;
|
|
2002
2409
|
}
|
|
2003
2410
|
}, {
|
|
2004
2411
|
key: "getLevelMaximumGeometricError",
|
|
@@ -2006,22 +2413,44 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
2006
2413
|
var levelZeroMaximumGeometricError = cesium.TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this.tilingScheme.ellipsoid, 65, this.tilingScheme.getNumberOfXTilesAtLevel(0)); // Scalar to control overzooming
|
|
2007
2414
|
// also seems to control zooming for imagery layers
|
|
2008
2415
|
|
|
2009
|
-
var scalar = this.
|
|
2416
|
+
var scalar = this.resource.tileSize / 256;
|
|
2010
2417
|
return levelZeroMaximumGeometricError / scalar / (1 << level);
|
|
2011
2418
|
}
|
|
2012
2419
|
}, {
|
|
2013
2420
|
key: "getTileDataAvailable",
|
|
2014
2421
|
value: function getTileDataAvailable(x, y, z) {
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2422
|
+
return this.resource.getTileDataAvailable({
|
|
2423
|
+
x: x,
|
|
2424
|
+
y: y,
|
|
2425
|
+
z: z
|
|
2426
|
+
});
|
|
2020
2427
|
}
|
|
2021
2428
|
}]);
|
|
2022
2429
|
|
|
2023
2430
|
return MartiniTerrainProvider;
|
|
2024
2431
|
}();
|
|
2025
2432
|
|
|
2026
|
-
|
|
2433
|
+
var MapboxTerrainProvider = /*#__PURE__*/function (_MartiniTerrainProvid) {
|
|
2434
|
+
_inherits(MapboxTerrainProvider, _MartiniTerrainProvid);
|
|
2435
|
+
|
|
2436
|
+
var _super2 = _createSuper(MapboxTerrainProvider);
|
|
2437
|
+
|
|
2438
|
+
function MapboxTerrainProvider() {
|
|
2439
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2440
|
+
|
|
2441
|
+
_classCallCheck(this, MapboxTerrainProvider);
|
|
2442
|
+
|
|
2443
|
+
var resource = new MapboxTerrainResource(opts);
|
|
2444
|
+
return _super2.call(this, _objectSpread2(_objectSpread2({}, opts), {}, {
|
|
2445
|
+
resource: resource
|
|
2446
|
+
}));
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
return MapboxTerrainProvider;
|
|
2450
|
+
}(MartiniTerrainProvider);
|
|
2451
|
+
|
|
2452
|
+
exports.DefaultHeightmapResource = DefaultHeightmapResource;
|
|
2453
|
+
exports.MapboxTerrainResource = MapboxTerrainResource;
|
|
2454
|
+
exports.MartiniTerrainProvider = MartiniTerrainProvider;
|
|
2455
|
+
exports["default"] = MapboxTerrainProvider;
|
|
2027
2456
|
//# sourceMappingURL=index.js.map
|