@macrostrat/cesium-martini 1.1.1 → 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 +39 -22
- package/dist/index.js +847 -420
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- 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,191 +259,193 @@ 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
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
+
};
|
|
119
275
|
|
|
120
|
-
|
|
276
|
+
var DefaultHeightmapResource = /*#__PURE__*/function () {
|
|
277
|
+
function DefaultHeightmapResource() {
|
|
278
|
+
var _this = this,
|
|
279
|
+
_opts$skipOddLevels,
|
|
280
|
+
_opts$tileSize,
|
|
281
|
+
_opts$maxZoom;
|
|
121
282
|
|
|
122
|
-
|
|
123
|
-
let id = i + 2;
|
|
124
|
-
let ax = 0,
|
|
125
|
-
ay = 0,
|
|
126
|
-
bx = 0,
|
|
127
|
-
by = 0,
|
|
128
|
-
cx = 0,
|
|
129
|
-
cy = 0;
|
|
283
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
130
284
|
|
|
131
|
-
|
|
132
|
-
bx = by = cx = tileSize; // bottom-left triangle
|
|
133
|
-
} else {
|
|
134
|
-
ax = ay = cy = tileSize; // top-right triangle
|
|
135
|
-
}
|
|
285
|
+
_classCallCheck(this, DefaultHeightmapResource);
|
|
136
286
|
|
|
137
|
-
|
|
138
|
-
const mx = ax + bx >> 1;
|
|
139
|
-
const my = ay + by >> 1;
|
|
287
|
+
_defineProperty(this, "resource", null);
|
|
140
288
|
|
|
141
|
-
|
|
142
|
-
// left half
|
|
143
|
-
bx = ax;
|
|
144
|
-
by = ay;
|
|
145
|
-
ax = cx;
|
|
146
|
-
ay = cy;
|
|
147
|
-
} else {
|
|
148
|
-
// right half
|
|
149
|
-
ax = bx;
|
|
150
|
-
ay = by;
|
|
151
|
-
bx = cx;
|
|
152
|
-
by = cy;
|
|
153
|
-
}
|
|
289
|
+
_defineProperty(this, "tileSize", 256);
|
|
154
290
|
|
|
155
|
-
|
|
156
|
-
cy = my;
|
|
157
|
-
}
|
|
291
|
+
_defineProperty(this, "maxZoom", void 0);
|
|
158
292
|
|
|
159
|
-
|
|
160
|
-
this.coords[k + 0] = ax;
|
|
161
|
-
this.coords[k + 1] = ay;
|
|
162
|
-
this.coords[k + 2] = bx;
|
|
163
|
-
this.coords[k + 3] = by;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
293
|
+
_defineProperty(this, "skipOddLevels", false);
|
|
166
294
|
|
|
167
|
-
|
|
168
|
-
return new Tile(terrain, this);
|
|
169
|
-
}
|
|
295
|
+
_defineProperty(this, "contextQueue", void 0);
|
|
170
296
|
|
|
171
|
-
|
|
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);
|
|
172
307
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (terrain.length !== size * size) throw new Error(`Expected terrain data of length ${size * size} (${size} x ${size}), got ${terrain.length}.`);
|
|
177
|
-
this.terrain = terrain;
|
|
178
|
-
this.martini = martini;
|
|
179
|
-
this.errors = new Float32Array(terrain.length);
|
|
180
|
-
this.update();
|
|
181
|
-
}
|
|
308
|
+
case 3:
|
|
309
|
+
img = _context.sent;
|
|
310
|
+
return _context.abrupt("return", _this.getPixels(img));
|
|
182
311
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const {
|
|
191
|
-
terrain,
|
|
192
|
-
errors
|
|
193
|
-
} = this; // iterate over all possible triangles, starting from the smallest level
|
|
312
|
+
case 5:
|
|
313
|
+
case "end":
|
|
314
|
+
return _context.stop();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}, _callee);
|
|
318
|
+
}));
|
|
194
319
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const bx = coords[k + 2];
|
|
200
|
-
const by = coords[k + 3];
|
|
201
|
-
const mx = ax + bx >> 1;
|
|
202
|
-
const my = ay + by >> 1;
|
|
203
|
-
const cx = mx + my - ay;
|
|
204
|
-
const cy = my + ax - mx; // calculate error in the middle of the long edge of the triangle
|
|
320
|
+
return function (_x) {
|
|
321
|
+
return _ref.apply(this, arguments);
|
|
322
|
+
};
|
|
323
|
+
}());
|
|
205
324
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
errors[middleIndex] = Math.max(errors[middleIndex], middleError);
|
|
325
|
+
if (opts.url) {
|
|
326
|
+
this.resource = cesium.Resource.createIfNeeded(opts.url);
|
|
327
|
+
}
|
|
210
328
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
+
};
|
|
216
349
|
}
|
|
350
|
+
|
|
351
|
+
return ctx;
|
|
217
352
|
}
|
|
218
|
-
}
|
|
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.
|
|
219
360
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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);
|
|
232
420
|
|
|
233
|
-
|
|
421
|
+
_defineProperty(_assertThisInitialized(_this), "resource", null);
|
|
234
422
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// - processTriangle: fill the allocated vertices & triangles typed arrays
|
|
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
|
|
238
425
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
426
|
+
if (highResolution) {
|
|
427
|
+
if (opts.maxZoom === undefined) {
|
|
428
|
+
_this.maxZoom = 14;
|
|
429
|
+
}
|
|
243
430
|
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
countElements(bx, by, cx, cy, mx, my);
|
|
247
|
-
} else {
|
|
248
|
-
indices[ay * size + ax] = indices[ay * size + ax] || ++numVertices;
|
|
249
|
-
indices[by * size + bx] = indices[by * size + bx] || ++numVertices;
|
|
250
|
-
indices[cy * size + cx] = indices[cy * size + cx] || ++numVertices;
|
|
251
|
-
numTriangles++;
|
|
431
|
+
if (opts.tileSize === undefined) {
|
|
432
|
+
_this.tileSize = 512;
|
|
252
433
|
}
|
|
253
434
|
}
|
|
254
435
|
|
|
255
|
-
|
|
256
|
-
countElements(max, max, 0, 0, 0, max);
|
|
257
|
-
const vertices = new Uint16Array(numVertices * 2);
|
|
258
|
-
const triangles = new Uint32Array(numTriangles * 3);
|
|
259
|
-
let triIndex = 0;
|
|
260
|
-
|
|
261
|
-
function processTriangle(ax, ay, bx, by, cx, cy) {
|
|
262
|
-
const mx = ax + bx >> 1;
|
|
263
|
-
const my = ay + by >> 1;
|
|
264
|
-
const legLength = Math.abs(ax - cx) + Math.abs(ay - cy);
|
|
436
|
+
_this.resource = cesium.Resource.createIfNeeded("https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format));
|
|
265
437
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
} else {
|
|
271
|
-
// add a triangle
|
|
272
|
-
const a = indices[ay * size + ax] - 1;
|
|
273
|
-
const b = indices[by * size + bx] - 1;
|
|
274
|
-
const c = indices[cy * size + cx] - 1;
|
|
275
|
-
vertices[2 * a] = ax;
|
|
276
|
-
vertices[2 * a + 1] = ay;
|
|
277
|
-
vertices[2 * b] = bx;
|
|
278
|
-
vertices[2 * b + 1] = by;
|
|
279
|
-
vertices[2 * c] = cx;
|
|
280
|
-
vertices[2 * c + 1] = cy;
|
|
281
|
-
triangles[triIndex++] = a;
|
|
282
|
-
triangles[triIndex++] = b;
|
|
283
|
-
triangles[triIndex++] = c;
|
|
284
|
-
}
|
|
438
|
+
if (opts.accessToken) {
|
|
439
|
+
_this.resource.setQueryParameters({
|
|
440
|
+
access_token: opts.accessToken
|
|
441
|
+
});
|
|
285
442
|
}
|
|
286
443
|
|
|
287
|
-
|
|
288
|
-
processTriangle(max, max, 0, 0, 0, max);
|
|
289
|
-
return {
|
|
290
|
-
vertices,
|
|
291
|
-
triangles
|
|
292
|
-
};
|
|
444
|
+
return _this;
|
|
293
445
|
}
|
|
294
446
|
|
|
295
|
-
|
|
447
|
+
return MapboxTerrainResource;
|
|
448
|
+
}(DefaultHeightmapResource);
|
|
296
449
|
|
|
297
450
|
function decodeBase64(base64, enableUnicode) {
|
|
298
451
|
var binaryString = atob(base64);
|
|
@@ -324,7 +477,7 @@ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
|
|
|
324
477
|
};
|
|
325
478
|
}
|
|
326
479
|
|
|
327
|
-
var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQoKICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkoYXJyKTsKICB9CgogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikgewogICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICJ1bmRlZmluZWQiICYmIGl0ZXJbU3ltYm9sLml0ZXJhdG9yXSAhPSBudWxsIHx8IGl0ZXJbIkBAaXRlcmF0b3IiXSAhPSBudWxsKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTsKICB9CgogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsKICAgIGlmICghbykgcmV0dXJuOwogICAgaWYgKHR5cGVvZiBvID09PSAic3RyaW5nIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7CiAgICB2YXIgbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKS5zbGljZSg4LCAtMSk7CiAgICBpZiAobiA9PT0gIk9iamVjdCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsKICAgIGlmIChuID09PSAiTWFwIiB8fCBuID09PSAiU2V0IikgcmV0dXJuIEFycmF5LmZyb20obyk7CiAgICBpZiAobiA9PT0gIkFyZ3VtZW50cyIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOwogIH0KCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHsKICAgIGlmIChsZW4gPT0gbnVsbCB8fCBsZW4gPiBhcnIubGVuZ3RoKSBsZW4gPSBhcnIubGVuZ3RoOwoKICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGxlbik7IGkgPCBsZW47IGkrKykgYXJyMltpXSA9IGFycltpXTsKCiAgICByZXR1cm4gYXJyMjsKICB9CgogIGZ1bmN0aW9uIF9ub25JdGVyYWJsZVNwcmVhZCgpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlLlxuSW4gb3JkZXIgdG8gYmUgaXRlcmFibGUsIG5vbi1hcnJheSBvYmplY3RzIG11c3QgaGF2ZSBhIFtTeW1ib2wuaXRlcmF0b3JdKCkgbWV0aG9kLiIpOwogIH0KCiAgLy8gV2Ugc2hvdWxkIHNhdmUgdGhlc2UKICAvL2NvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoMjU2LCAyNTYpOwogIC8vY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgZnVuY3Rpb24gbWFwYm94VGVycmFpblRvR3JpZChwbmcpIHsKICAgIC8vIG1heWJlIHdlIHNob3VsZCBkbyB0aGlzIG9uIHRoZSBHUFUgdXNpbmcgUkVHTD8KICAgIC8vIGJ1dCB0aGF0IHdvdWxkIHJlcXVpcmUgR1BVIC0+IENQVSAtPiBHUFUKICAgIHZhciBncmlkU2l6ZSA9IHBuZy5zaGFwZVswXSArIDE7CiAgICB2YXIgdGVycmFpbiA9IG5ldyBGbG9hdDMyQXJyYXkoZ3JpZFNpemUgKiBncmlkU2l6ZSk7CiAgICB2YXIgdGlsZVNpemUgPSBwbmcuc2hhcGVbMF07IC8vIGRlY29kZSB0ZXJyYWluIHZhbHVlcwoKICAgIGZvciAodmFyIHkgPSAwOyB5IDwgdGlsZVNpemU7IHkrKykgewogICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHRpbGVTaXplOyB4KyspIHsKICAgICAgICB2YXIgeWMgPSB5OwogICAgICAgIHZhciByID0gcG5nLmdldCh4LCB5YywgMCk7CiAgICAgICAgdmFyIGcgPSBwbmcuZ2V0KHgsIHljLCAxKTsKICAgICAgICB2YXIgYiA9IHBuZy5nZXQoeCwgeWMsIDIpOwogICAgICAgIHRlcnJhaW5beSAqIGdyaWRTaXplICsgeF0gPSByICogMjU2ICogMjU2IC8gMTAuMCArIGcgKiAyNTYuMCAvIDEwLjAgKyBiIC8gMTAuMCAtIDEwMDAwLjA7CiAgICAgIH0KICAgIH0gLy8gYmFja2ZpbGwgcmlnaHQgYW5kIGJvdHRvbSBib3JkZXJzCgoKICAgIGZvciAodmFyIF94ID0gMDsgX3ggPCBncmlkU2l6ZSAtIDE7IF94KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDEpICsgX3hdID0gdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDIpICsgX3hdOwogICAgfQoKICAgIGZvciAodmFyIF95ID0gMDsgX3kgPCBncmlkU2l6ZTsgX3krKykgewogICAgICB0ZXJyYWluW2dyaWRTaXplICogX3kgKyBncmlkU2l6ZSAtIDFdID0gdGVycmFpbltncmlkU2l6ZSAqIF95ICsgZ3JpZFNpemUgLSAyXTsKICAgIH0KCiAgICByZXR1cm4gdGVycmFpbjsKICB9CgogIGZ1bmN0aW9uIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gpIHsKICAgIHZhciB0aWxlU2l6ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogMjU2OwogICAgdmFyIHh2YWxzID0gW107CiAgICB2YXIgeXZhbHMgPSBbXTsKICAgIHZhciBoZWlnaHRNZXRlcnMgPSBbXTsKICAgIHZhciBub3J0aEluZGljZXMgPSBbXTsKICAgIHZhciBzb3V0aEluZGljZXMgPSBbXTsKICAgIHZhciBlYXN0SW5kaWNlcyA9IFtdOwogICAgdmFyIHdlc3RJbmRpY2VzID0gW107CgogICAgZm9yICh2YXIgaXggPSAwOyBpeCA8IG1lc2gudmVydGljZXMubGVuZ3RoIC8gMjsgaXgrKykgewogICAgICB2YXIgdmVydGV4SXggPSBpeDsKICAgICAgdmFyIHB4ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDJdOwogICAgICB2YXIgcHkgPSBtZXNoLnZlcnRpY2VzW2l4ICogMiArIDFdOwogICAgICBoZWlnaHRNZXRlcnMucHVzaCh0aWxlLnRlcnJhaW5bcHkgKiAodGlsZVNpemUgKyAxKSArIHB4XSk7CiAgICAgIGlmIChweSA9PSAwKSBub3J0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweSA9PSB0aWxlU2l6ZSkgc291dGhJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICBpZiAocHggPT0gMCkgd2VzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSB0aWxlU2l6ZSkgZWFzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIHZhciBzY2FsYXIgPSAzMjc2OC4wIC8gdGlsZVNpemU7CiAgICAgIHZhciB4diA9IHB4ICogc2NhbGFyOwogICAgICB2YXIgeXYgPSAodGlsZVNpemUgLSBweSkgKiBzY2FsYXI7CiAgICAgIHh2YWxzLnB1c2goeHYpOwogICAgICB5dmFscy5wdXNoKHl2KTsKICAgIH0KCiAgICB2YXIgbWF4SGVpZ2h0ID0gTWF0aC5tYXguYXBwbHkodGhpcywgaGVpZ2h0TWV0ZXJzKTsKICAgIHZhciBtaW5IZWlnaHQgPSBNYXRoLm1pbi5hcHBseSh0aGlzLCBoZWlnaHRNZXRlcnMpOwogICAgdmFyIGhlaWdodHMgPSBoZWlnaHRNZXRlcnMubWFwKGZ1bmN0aW9uIChkKSB7CiAgICAgIGlmIChtYXhIZWlnaHQgLSBtaW5IZWlnaHQgPCAxKSByZXR1cm4gMDsKICAgICAgcmV0dXJuIChkIC0gbWluSGVpZ2h0KSAqICgzMjc2Ny4wIC8gKG1heEhlaWdodCAtIG1pbkhlaWdodCkpOwogICAgfSk7CiAgICB2YXIgdHJpYW5nbGVzID0gbmV3IFVpbnQxNkFycmF5KG1lc2gudHJpYW5nbGVzKTsKICAgIHZhciBxdWFudGl6ZWRWZXJ0aWNlcyA9IG5ldyBVaW50MTZBcnJheSggLy92ZXJ0cwogICAgW10uY29uY2F0KHh2YWxzLCB5dmFscywgX3RvQ29uc3VtYWJsZUFycmF5KGhlaWdodHMpKSk7IC8vIFNFIE5XIE5FCiAgICAvLyBORSBOVyBTRQoKICAgIHJldHVybiB7CiAgICAgIG1pbmltdW1IZWlnaHQ6IG1pbkhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodDogbWF4SGVpZ2h0LAogICAgICBxdWFudGl6ZWRWZXJ0aWNlczogcXVhbnRpemVkVmVydGljZXMsCiAgICAgIGluZGljZXM6IHRyaWFuZ2xlcywKICAgICAgd2VzdEluZGljZXM6IHdlc3RJbmRpY2VzLAogICAgICBzb3V0aEluZGljZXM6IHNvdXRoSW5kaWNlcywKICAgICAgZWFzdEluZGljZXM6IGVhc3RJbmRpY2VzLAogICAgICBub3J0aEluZGljZXM6IG5vcnRoSW5kaWNlcwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGlvdGEobikgewogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKTsKICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkgewogICAgICByZXN1bHRbaV0gPSBpOwogICAgfQogICAgcmV0dXJuIHJlc3VsdAogIH0KCiAgdmFyIGlvdGFfMSA9IGlvdGE7CgogIC8qIQogICAqIERldGVybWluZSBpZiBhbiBvYmplY3QgaXMgYSBCdWZmZXIKICAgKgogICAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+CiAgICogQGxpY2Vuc2UgIE1JVAogICAqLwogIC8vIFRoZSBfaXNCdWZmZXIgY2hlY2sgaXMgZm9yIFNhZmFyaSA1LTcgc3VwcG9ydCwgYmVjYXVzZSBpdCdzIG1pc3NpbmcKICAvLyBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yLiBSZW1vdmUgdGhpcyBldmVudHVhbGx5CiAgdmFyIGlzQnVmZmVyXzEgPSBmdW5jdGlvbiAob2JqKSB7CiAgICByZXR1cm4gb2JqICE9IG51bGwgJiYgKGlzQnVmZmVyKG9iaikgfHwgaXNTbG93QnVmZmVyKG9iaikgfHwgISFvYmouX2lzQnVmZmVyKQogIH07CgogIGZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHsKICAgIHJldHVybiAhIW9iai5jb25zdHJ1Y3RvciAmJiB0eXBlb2Ygb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyID09PSAnZnVuY3Rpb24nICYmIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlcihvYmopCiAgfQoKICAvLyBGb3IgTm9kZSB2MC4xMCBzdXBwb3J0LiBSZW1vdmUgdGhpcyBldmVudHVhbGx5LgogIGZ1bmN0aW9uIGlzU2xvd0J1ZmZlciAob2JqKSB7CiAgICByZXR1cm4gdHlwZW9mIG9iai5yZWFkRmxvYXRMRSA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2Ygb2JqLnNsaWNlID09PSAnZnVuY3Rpb24nICYmIGlzQnVmZmVyKG9iai5zbGljZSgwLCAwKSkKICB9CgogIHZhciBoYXNUeXBlZEFycmF5cyAgPSAoKHR5cGVvZiBGbG9hdDY0QXJyYXkpICE9PSAidW5kZWZpbmVkIik7CgogIGZ1bmN0aW9uIGNvbXBhcmUxc3QoYSwgYikgewogICAgcmV0dXJuIGFbMF0gLSBiWzBdCiAgfQoKICBmdW5jdGlvbiBvcmRlcigpIHsKICAgIHZhciBzdHJpZGUgPSB0aGlzLnN0cmlkZTsKICAgIHZhciB0ZXJtcyA9IG5ldyBBcnJheShzdHJpZGUubGVuZ3RoKTsKICAgIHZhciBpOwogICAgZm9yKGk9MDsgaTx0ZXJtcy5sZW5ndGg7ICsraSkgewogICAgICB0ZXJtc1tpXSA9IFtNYXRoLmFicyhzdHJpZGVbaV0pLCBpXTsKICAgIH0KICAgIHRlcm1zLnNvcnQoY29tcGFyZTFzdCk7CiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KHRlcm1zLmxlbmd0aCk7CiAgICBmb3IoaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkgewogICAgICByZXN1bHRbaV0gPSB0ZXJtc1tpXVsxXTsKICAgIH0KICAgIHJldHVybiByZXN1bHQKICB9CgogIGZ1bmN0aW9uIGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgZGltZW5zaW9uKSB7CiAgICB2YXIgY2xhc3NOYW1lID0gWyJWaWV3IiwgZGltZW5zaW9uLCAiZCIsIGR0eXBlXS5qb2luKCIiKTsKICAgIGlmKGRpbWVuc2lvbiA8IDApIHsKICAgICAgY2xhc3NOYW1lID0gIlZpZXdfTmlsIiArIGR0eXBlOwogICAgfQogICAgdmFyIHVzZUdldHRlcnMgPSAoZHR5cGUgPT09ICJnZW5lcmljIik7CgogICAgaWYoZGltZW5zaW9uID09PSAtMSkgewogICAgICAvL1NwZWNpYWwgY2FzZSBmb3IgdHJpdmlhbCBhcnJheXMKICAgICAgdmFyIGNvZGUgPQogICAgICAgICJmdW5jdGlvbiAiK2NsYXNzTmFtZSsiKGEpe3RoaXMuZGF0YT1hO307XAp2YXIgcHJvdG89IitjbGFzc05hbWUrIi5wcm90b3R5cGU7XApwcm90by5kdHlwZT0nIitkdHlwZSsiJztcCnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIC0xfTtcCnByb3RvLnNpemU9MDtcCnByb3RvLmRpbWVuc2lvbj0tMTtcCnByb3RvLnNoYXBlPXByb3RvLnN0cmlkZT1wcm90by5vcmRlcj1bXTtcCnByb3RvLmxvPXByb3RvLmhpPXByb3RvLnRyYW5zcG9zZT1wcm90by5zdGVwPVwKZnVuY3Rpb24oKXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhKTt9O1wKcHJvdG8uZ2V0PXByb3RvLnNldD1mdW5jdGlvbigpe307XApwcm90by5waWNrPWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9O1wKcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF8iK2NsYXNzTmFtZSsiKGEpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIihhKTt9IjsKICAgICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbihjb2RlKTsKICAgICAgcmV0dXJuIHByb2NlZHVyZSgpCiAgICB9IGVsc2UgaWYoZGltZW5zaW9uID09PSAwKSB7CiAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciAwZCBhcnJheXMKICAgICAgdmFyIGNvZGUgPQogICAgICAgICJmdW5jdGlvbiAiK2NsYXNzTmFtZSsiKGEsZCkge1wKdGhpcy5kYXRhID0gYTtcCnRoaXMub2Zmc2V0ID0gZFwKfTtcCnZhciBwcm90bz0iK2NsYXNzTmFtZSsiLnByb3RvdHlwZTtcCnByb3RvLmR0eXBlPSciK2R0eXBlKyInO1wKcHJvdG8uaW5kZXg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vZmZzZXR9O1wKcHJvdG8uZGltZW5zaW9uPTA7XApwcm90by5zaXplPTE7XApwcm90by5zaGFwZT1cCnByb3RvLnN0cmlkZT1cCnByb3RvLm9yZGVyPVtdO1wKcHJvdG8ubG89XApwcm90by5oaT1cCnByb3RvLnRyYW5zcG9zZT1cCnByb3RvLnN0ZXA9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9jb3B5KCkge1wKcmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSx0aGlzLm9mZnNldClcCn07XApwcm90by5waWNrPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfcGljaygpe1wKcmV0dXJuIFRyaXZpYWxBcnJheSh0aGlzLmRhdGEpO1wKfTtcCnByb3RvLnZhbHVlT2Y9cHJvdG8uZ2V0PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfZ2V0KCl7XApyZXR1cm4gIisodXNlR2V0dGVycyA/ICJ0aGlzLmRhdGEuZ2V0KHRoaXMub2Zmc2V0KSIgOiAidGhpcy5kYXRhW3RoaXMub2Zmc2V0XSIpKwogICJ9O1wKcHJvdG8uc2V0PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfc2V0KHYpe1wKcmV0dXJuICIrKHVzZUdldHRlcnMgPyAidGhpcy5kYXRhLnNldCh0aGlzLm9mZnNldCx2KSIgOiAidGhpcy5kYXRhW3RoaXMub2Zmc2V0XT12IikrIlwKfTtcCnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfIitjbGFzc05hbWUrIihhLGIsYyxkKXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIoYSxkKX0iOwogICAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKCJUcml2aWFsQXJyYXkiLCBjb2RlKTsKICAgICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXVswXSkKICAgIH0KCiAgICB2YXIgY29kZSA9IFsiJ3VzZSBzdHJpY3QnIl07CgogICAgLy9DcmVhdGUgY29uc3RydWN0b3IgZm9yIHZpZXcKICAgIHZhciBpbmRpY2VzID0gaW90YV8xKGRpbWVuc2lvbik7CiAgICB2YXIgYXJncyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuICJpIitpIH0pOwogICAgdmFyIGluZGV4X3N0ciA9ICJ0aGlzLm9mZnNldCsiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgICAgcmV0dXJuICJ0aGlzLnN0cmlkZVsiICsgaSArICJdKmkiICsgaQogICAgICAgIH0pLmpvaW4oIisiKTsKICAgIHZhciBzaGFwZUFyZyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImIiK2kKICAgICAgfSkuam9pbigiLCIpOwogICAgdmFyIHN0cmlkZUFyZyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImMiK2kKICAgICAgfSkuam9pbigiLCIpOwogICAgY29kZS5wdXNoKAogICAgICAiZnVuY3Rpb24gIitjbGFzc05hbWUrIihhLCIgKyBzaGFwZUFyZyArICIsIiArIHN0cmlkZUFyZyArICIsZCl7dGhpcy5kYXRhPWEiLAogICAgICAgICJ0aGlzLnNoYXBlPVsiICsgc2hhcGVBcmcgKyAiXSIsCiAgICAgICAgInRoaXMuc3RyaWRlPVsiICsgc3RyaWRlQXJnICsgIl0iLAogICAgICAgICJ0aGlzLm9mZnNldD1kfDB9IiwKICAgICAgInZhciBwcm90bz0iK2NsYXNzTmFtZSsiLnByb3RvdHlwZSIsCiAgICAgICJwcm90by5kdHlwZT0nIitkdHlwZSsiJyIsCiAgICAgICJwcm90by5kaW1lbnNpb249IitkaW1lbnNpb24pOwoKICAgIC8vdmlldy5zaXplOgogICAgY29kZS5wdXNoKCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ3NpemUnLHtnZXQ6ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9zaXplKCl7XApyZXR1cm4gIitpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAidGhpcy5zaGFwZVsiK2krIl0iIH0pLmpvaW4oIioiKSwKICAifX0pIik7CgogICAgLy92aWV3Lm9yZGVyOgogICAgaWYoZGltZW5zaW9uID09PSAxKSB7CiAgICAgIGNvZGUucHVzaCgicHJvdG8ub3JkZXI9WzBdIik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnb3JkZXInLHtnZXQ6Iik7CiAgICAgIGlmKGRpbWVuc2lvbiA8IDQpIHsKICAgICAgICBjb2RlLnB1c2goImZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfb3JkZXIoKXsiKTsKICAgICAgICBpZihkaW1lbnNpb24gPT09IDIpIHsKICAgICAgICAgIGNvZGUucHVzaCgicmV0dXJuIChNYXRoLmFicyh0aGlzLnN0cmlkZVswXSk+TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pKT9bMSwwXTpbMCwxXX19KSIpOwogICAgICAgIH0gZWxzZSBpZihkaW1lbnNpb24gPT09IDMpIHsKICAgICAgICAgIGNvZGUucHVzaCgKICAidmFyIHMwPU1hdGguYWJzKHRoaXMuc3RyaWRlWzBdKSxzMT1NYXRoLmFicyh0aGlzLnN0cmlkZVsxXSksczI9TWF0aC5hYnModGhpcy5zdHJpZGVbMl0pO1wKaWYoczA+czEpe1wKaWYoczE+czIpe1wKcmV0dXJuIFsyLDEsMF07XAp9ZWxzZSBpZihzMD5zMil7XApyZXR1cm4gWzEsMiwwXTtcCn1lbHNle1wKcmV0dXJuIFsxLDAsMl07XAp9XAp9ZWxzZSBpZihzMD5zMil7XApyZXR1cm4gWzIsMCwxXTtcCn1lbHNlIGlmKHMyPnMxKXtcCnJldHVybiBbMCwxLDJdO1wKfWVsc2V7XApyZXR1cm4gWzAsMiwxXTtcCn19fSkiKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29kZS5wdXNoKCJPUkRFUn0pIik7CiAgICAgIH0KICAgIH0KCiAgICAvL3ZpZXcuc2V0KGkwLCAuLi4sIHYpOgogICAgY29kZS5wdXNoKAogICJwcm90by5zZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9zZXQoIithcmdzLmpvaW4oIiwiKSsiLHYpeyIpOwogICAgaWYodXNlR2V0dGVycykgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGEuc2V0KCIraW5kZXhfc3RyKyIsdil9Iik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGFbIitpbmRleF9zdHIrIl09dn0iKTsKICAgIH0KCiAgICAvL3ZpZXcuZ2V0KGkwLCAuLi4pOgogICAgY29kZS5wdXNoKCJwcm90by5nZXQ9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9nZXQoIithcmdzLmpvaW4oIiwiKSsiKXsiKTsKICAgIGlmKHVzZUdldHRlcnMpIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhLmdldCgiK2luZGV4X3N0cisiKX0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YVsiK2luZGV4X3N0cisiXX0iKTsKICAgIH0KCiAgICAvL3ZpZXcuaW5kZXg6CiAgICBjb2RlLnB1c2goCiAgICAgICJwcm90by5pbmRleD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2luZGV4KCIsIGFyZ3Muam9pbigpLCAiKXtyZXR1cm4gIitpbmRleF9zdHIrIn0iKTsKCiAgICAvL3ZpZXcuaGkoKToKICAgIGNvZGUucHVzaCgicHJvdG8uaGk9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9oaSgiK2FyZ3Muam9pbigiLCIpKyIpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiBbIih0eXBlb2YgaSIsaSwiIT09J251bWJlcid8fGkiLGksIjwwKT90aGlzLnNoYXBlWyIsIGksICJdOmkiLCBpLCJ8MCJdLmpvaW4oIiIpCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gInRoaXMuc3RyaWRlWyIraSArICJdIgogICAgICB9KS5qb2luKCIsIikrIix0aGlzLm9mZnNldCl9Iik7CgogICAgLy92aWV3LmxvKCk6CiAgICB2YXIgYV92YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gImEiK2krIj10aGlzLnNoYXBlWyIraSsiXSIgfSk7CiAgICB2YXIgY192YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gImMiK2krIj10aGlzLnN0cmlkZVsiK2krIl0iIH0pOwogICAgY29kZS5wdXNoKCJwcm90by5sbz1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2xvKCIrYXJncy5qb2luKCIsIikrIil7dmFyIGI9dGhpcy5vZmZzZXQsZD0wLCIrYV92YXJzLmpvaW4oIiwiKSsiLCIrY192YXJzLmpvaW4oIiwiKSk7CiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goCiAgImlmKHR5cGVvZiBpIitpKyI9PT0nbnVtYmVyJyYmaSIraSsiPj0wKXtcCmQ9aSIraSsifDA7XApiKz1jIitpKyIqZDtcCmEiK2krIi09ZH0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgicmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJhIitpCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImMiK2kKICAgICAgfSkuam9pbigiLCIpKyIsYil9Iik7CgogICAgLy92aWV3LnN0ZXAoKToKICAgIGNvZGUucHVzaCgicHJvdG8uc3RlcD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3N0ZXAoIithcmdzLmpvaW4oIiwiKSsiKXt2YXIgIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYSIraSsiPXRoaXMuc2hhcGVbIitpKyJdIgogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJiIitpKyI9dGhpcy5zdHJpZGVbIitpKyJdIgogICAgICB9KS5qb2luKCIsIikrIixjPXRoaXMub2Zmc2V0LGQ9MCxjZWlsPU1hdGguY2VpbCIpOwogICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKAogICJpZih0eXBlb2YgaSIraSsiPT09J251bWJlcicpe1wKZD1pIitpKyJ8MDtcCmlmKGQ8MCl7XApjKz1iIitpKyIqKGEiK2krIi0xKTtcCmEiK2krIj1jZWlsKC1hIitpKyIvZClcCn1lbHNle1wKYSIraSsiPWNlaWwoYSIraSsiL2QpXAp9XApiIitpKyIqPWRcCn0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgicmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJhIiArIGkKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYiIgKyBpCiAgICAgIH0pLmpvaW4oIiwiKSsiLGMpfSIpOwoKICAgIC8vdmlldy50cmFuc3Bvc2UoKToKICAgIHZhciB0U2hhcGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKTsKICAgIHZhciB0U3RyaWRlID0gbmV3IEFycmF5KGRpbWVuc2lvbik7CiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkgewogICAgICB0U2hhcGVbaV0gPSAiYVtpIitpKyJdIjsKICAgICAgdFN0cmlkZVtpXSA9ICJiW2kiK2krIl0iOwogICAgfQogICAgY29kZS5wdXNoKCJwcm90by50cmFuc3Bvc2U9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl90cmFuc3Bvc2UoIithcmdzKyIpeyIrCiAgICAgIGFyZ3MubWFwKGZ1bmN0aW9uKG4saWR4KSB7IHJldHVybiBuICsgIj0oIiArIG4gKyAiPT09dW5kZWZpbmVkPyIgKyBpZHggKyAiOiIgKyBuICsgInwwKSJ9KS5qb2luKCI7IiksCiAgICAgICJ2YXIgYT10aGlzLnNoYXBlLGI9dGhpcy5zdHJpZGU7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSwiK3RTaGFwZS5qb2luKCIsIikrIiwiK3RTdHJpZGUuam9pbigiLCIpKyIsdGhpcy5vZmZzZXQpfSIpOwoKICAgIC8vdmlldy5waWNrKCk6CiAgICBjb2RlLnB1c2goInByb3RvLnBpY2s9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9waWNrKCIrYXJncysiKXt2YXIgYT1bXSxiPVtdLGM9dGhpcy5vZmZzZXQiKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgiaWYodHlwZW9mIGkiK2krIj09PSdudW1iZXInJiZpIitpKyI+PTApe2M9KGMrdGhpcy5zdHJpZGVbIitpKyJdKmkiK2krIil8MH1lbHNle2EucHVzaCh0aGlzLnNoYXBlWyIraSsiXSk7Yi5wdXNoKHRoaXMuc3RyaWRlWyIraSsiXSl9Iik7CiAgICB9CiAgICBjb2RlLnB1c2goInZhciBjdG9yPUNUT1JfTElTVFthLmxlbmd0aCsxXTtyZXR1cm4gY3Rvcih0aGlzLmRhdGEsYSxiLGMpfSIpOwoKICAgIC8vQWRkIHJldHVybiBzdGF0ZW1lbnQKICAgIGNvZGUucHVzaCgicmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF8iK2NsYXNzTmFtZSsiKGRhdGEsc2hhcGUsc3RyaWRlLG9mZnNldCl7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKGRhdGEsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAic2hhcGVbIitpKyJdIgogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJzdHJpZGVbIitpKyJdIgogICAgICB9KS5qb2luKCIsIikrIixvZmZzZXQpfSIpOwoKICAgIC8vQ29tcGlsZSBwcm9jZWR1cmUKICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oIkNUT1JfTElTVCIsICJPUkRFUiIsIGNvZGUuam9pbigiXG4iKSk7CiAgICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdLCBvcmRlcikKICB9CgogIGZ1bmN0aW9uIGFycmF5RFR5cGUoZGF0YSkgewogICAgaWYoaXNCdWZmZXJfMShkYXRhKSkgewogICAgICByZXR1cm4gImJ1ZmZlciIKICAgIH0KICAgIGlmKGhhc1R5cGVkQXJyYXlzKSB7CiAgICAgIHN3aXRjaChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSkpIHsKICAgICAgICBjYXNlICJbb2JqZWN0IEZsb2F0NjRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJmbG9hdDY0IgogICAgICAgIGNhc2UgIltvYmplY3QgRmxvYXQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImZsb2F0MzIiCiAgICAgICAgY2FzZSAiW29iamVjdCBJbnQ4QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiaW50OCIKICAgICAgICBjYXNlICJbb2JqZWN0IEludDE2QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiaW50MTYiCiAgICAgICAgY2FzZSAiW29iamVjdCBJbnQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImludDMyIgogICAgICAgIGNhc2UgIltvYmplY3QgVWludDhBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50OCIKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQxNkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQxNiIKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQzMiIKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQ4X2NsYW1wZWQiCiAgICAgICAgY2FzZSAiW29iamVjdCBCaWdJbnQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImJpZ2ludDY0IgogICAgICAgIGNhc2UgIltvYmplY3QgQmlnVWludDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiYmlndWludDY0IgogICAgICB9CiAgICB9CiAgICBpZihBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgIHJldHVybiAiYXJyYXkiCiAgICB9CiAgICByZXR1cm4gImdlbmVyaWMiCiAgfQoKICB2YXIgQ0FDSEVEX0NPTlNUUlVDVE9SUyA9IHsKICAgICJmbG9hdDMyIjpbXSwKICAgICJmbG9hdDY0IjpbXSwKICAgICJpbnQ4IjpbXSwKICAgICJpbnQxNiI6W10sCiAgICAiaW50MzIiOltdLAogICAgInVpbnQ4IjpbXSwKICAgICJ1aW50MTYiOltdLAogICAgInVpbnQzMiI6W10sCiAgICAiYXJyYXkiOltdLAogICAgInVpbnQ4X2NsYW1wZWQiOltdLAogICAgImJpZ2ludDY0IjogW10sCiAgICAiYmlndWludDY0IjogW10sCiAgICAiYnVmZmVyIjpbXSwKICAgICJnZW5lcmljIjpbXQogIH0KCiAgOwogIGZ1bmN0aW9uIHdyYXBwZWROREFycmF5Q3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpIHsKICAgIGlmKGRhdGEgPT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgY3RvciA9IENBQ0hFRF9DT05TVFJVQ1RPUlMuYXJyYXlbMF07CiAgICAgIHJldHVybiBjdG9yKFtdKQogICAgfSBlbHNlIGlmKHR5cGVvZiBkYXRhID09PSAibnVtYmVyIikgewogICAgICBkYXRhID0gW2RhdGFdOwogICAgfQogICAgaWYoc2hhcGUgPT09IHVuZGVmaW5lZCkgewogICAgICBzaGFwZSA9IFsgZGF0YS5sZW5ndGggXTsKICAgIH0KICAgIHZhciBkID0gc2hhcGUubGVuZ3RoOwogICAgaWYoc3RyaWRlID09PSB1bmRlZmluZWQpIHsKICAgICAgc3RyaWRlID0gbmV3IEFycmF5KGQpOwogICAgICBmb3IodmFyIGk9ZC0xLCBzej0xOyBpPj0wOyAtLWkpIHsKICAgICAgICBzdHJpZGVbaV0gPSBzejsKICAgICAgICBzeiAqPSBzaGFwZVtpXTsKICAgICAgfQogICAgfQogICAgaWYob2Zmc2V0ID09PSB1bmRlZmluZWQpIHsKICAgICAgb2Zmc2V0ID0gMDsKICAgICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7CiAgICAgICAgaWYoc3RyaWRlW2ldIDwgMCkgewogICAgICAgICAgb2Zmc2V0IC09IChzaGFwZVtpXS0xKSpzdHJpZGVbaV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB2YXIgZHR5cGUgPSBhcnJheURUeXBlKGRhdGEpOwogICAgdmFyIGN0b3JfbGlzdCA9IENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdOwogICAgd2hpbGUoY3Rvcl9saXN0Lmxlbmd0aCA8PSBkKzEpIHsKICAgICAgY3Rvcl9saXN0LnB1c2goY29tcGlsZUNvbnN0cnVjdG9yKGR0eXBlLCBjdG9yX2xpc3QubGVuZ3RoLTEpKTsKICAgIH0KICAgIHZhciBjdG9yID0gY3Rvcl9saXN0W2QrMV07CiAgICByZXR1cm4gY3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpCiAgfQoKICB2YXIgbmRhcnJheSA9IHdyYXBwZWROREFycmF5Q3RvcjsKCiAgY2xhc3MgTWFydGluaSB7CiAgICBjb25zdHJ1Y3RvcihncmlkU2l6ZSA9IDI1NykgewogICAgICB0aGlzLmdyaWRTaXplID0gZ3JpZFNpemU7CiAgICAgIGNvbnN0IHRpbGVTaXplID0gZ3JpZFNpemUgLSAxOwogICAgICBpZiAodGlsZVNpemUgJiB0aWxlU2l6ZSAtIDEpIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgZ3JpZCBzaXplIHRvIGJlIDJebisxLCBnb3QgJHtncmlkU2l6ZX0uYCk7CiAgICAgIHRoaXMubnVtVHJpYW5nbGVzID0gdGlsZVNpemUgKiB0aWxlU2l6ZSAqIDIgLSAyOwogICAgICB0aGlzLm51bVBhcmVudFRyaWFuZ2xlcyA9IHRoaXMubnVtVHJpYW5nbGVzIC0gdGlsZVNpemUgKiB0aWxlU2l6ZTsKICAgICAgdGhpcy5pbmRpY2VzID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuZ3JpZFNpemUgKiB0aGlzLmdyaWRTaXplKTsgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCgogICAgICB0aGlzLmNvb3JkcyA9IG5ldyBVaW50MTZBcnJheSh0aGlzLm51bVRyaWFuZ2xlcyAqIDQpOyAvLyBnZXQgdHJpYW5nbGUgY29vcmRpbmF0ZXMgZnJvbSBpdHMgaW5kZXggaW4gYW4gaW1wbGljaXQgYmluYXJ5IHRyZWUKCiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1UcmlhbmdsZXM7IGkrKykgewogICAgICAgIGxldCBpZCA9IGkgKyAyOwogICAgICAgIGxldCBheCA9IDAsCiAgICAgICAgICAgIGF5ID0gMCwKICAgICAgICAgICAgYnggPSAwLAogICAgICAgICAgICBieSA9IDAsCiAgICAgICAgICAgIGN4ID0gMCwKICAgICAgICAgICAgY3kgPSAwOwoKICAgICAgICBpZiAoaWQgJiAxKSB7CiAgICAgICAgICBieCA9IGJ5ID0gY3ggPSB0aWxlU2l6ZTsgLy8gYm90dG9tLWxlZnQgdHJpYW5nbGUKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYXggPSBheSA9IGN5ID0gdGlsZVNpemU7IC8vIHRvcC1yaWdodCB0cmlhbmdsZQogICAgICAgIH0KCiAgICAgICAgd2hpbGUgKChpZCA+Pj0gMSkgPiAxKSB7CiAgICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwoKICAgICAgICAgIGlmIChpZCAmIDEpIHsKICAgICAgICAgICAgLy8gbGVmdCBoYWxmCiAgICAgICAgICAgIGJ4ID0gYXg7CiAgICAgICAgICAgIGJ5ID0gYXk7CiAgICAgICAgICAgIGF4ID0gY3g7CiAgICAgICAgICAgIGF5ID0gY3k7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyByaWdodCBoYWxmCiAgICAgICAgICAgIGF4ID0gYng7CiAgICAgICAgICAgIGF5ID0gYnk7CiAgICAgICAgICAgIGJ4ID0gY3g7CiAgICAgICAgICAgIGJ5ID0gY3k7CiAgICAgICAgICB9CgogICAgICAgICAgY3ggPSBteDsKICAgICAgICAgIGN5ID0gbXk7CiAgICAgICAgfQoKICAgICAgICBjb25zdCBrID0gaSAqIDQ7CiAgICAgICAgdGhpcy5jb29yZHNbayArIDBdID0gYXg7CiAgICAgICAgdGhpcy5jb29yZHNbayArIDFdID0gYXk7CiAgICAgICAgdGhpcy5jb29yZHNbayArIDJdID0gYng7CiAgICAgICAgdGhpcy5jb29yZHNbayArIDNdID0gYnk7CiAgICAgIH0KICAgIH0KCiAgICBjcmVhdGVUaWxlKHRlcnJhaW4pIHsKICAgICAgcmV0dXJuIG5ldyBUaWxlKHRlcnJhaW4sIHRoaXMpOwogICAgfQoKICB9CgogIGNsYXNzIFRpbGUgewogICAgY29uc3RydWN0b3IodGVycmFpbiwgbWFydGluaSkgewogICAgICBjb25zdCBzaXplID0gbWFydGluaS5ncmlkU2l6ZTsKICAgICAgaWYgKHRlcnJhaW4ubGVuZ3RoICE9PSBzaXplICogc2l6ZSkgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCB0ZXJyYWluIGRhdGEgb2YgbGVuZ3RoICR7c2l6ZSAqIHNpemV9ICgke3NpemV9IHggJHtzaXplfSksIGdvdCAke3RlcnJhaW4ubGVuZ3RofS5gKTsKICAgICAgdGhpcy50ZXJyYWluID0gdGVycmFpbjsKICAgICAgdGhpcy5tYXJ0aW5pID0gbWFydGluaTsKICAgICAgdGhpcy5lcnJvcnMgPSBuZXcgRmxvYXQzMkFycmF5KHRlcnJhaW4ubGVuZ3RoKTsKICAgICAgdGhpcy51cGRhdGUoKTsKICAgIH0KCiAgICB1cGRhdGUoKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBudW1UcmlhbmdsZXMsCiAgICAgICAgbnVtUGFyZW50VHJpYW5nbGVzLAogICAgICAgIGNvb3JkcywKICAgICAgICBncmlkU2l6ZTogc2l6ZQogICAgICB9ID0gdGhpcy5tYXJ0aW5pOwogICAgICBjb25zdCB7CiAgICAgICAgdGVycmFpbiwKICAgICAgICBlcnJvcnMKICAgICAgfSA9IHRoaXM7IC8vIGl0ZXJhdGUgb3ZlciBhbGwgcG9zc2libGUgdHJpYW5nbGVzLCBzdGFydGluZyBmcm9tIHRoZSBzbWFsbGVzdCBsZXZlbAoKICAgICAgZm9yIChsZXQgaSA9IG51bVRyaWFuZ2xlcyAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgIGNvbnN0IGF4ID0gY29vcmRzW2sgKyAwXTsKICAgICAgICBjb25zdCBheSA9IGNvb3Jkc1trICsgMV07CiAgICAgICAgY29uc3QgYnggPSBjb29yZHNbayArIDJdOwogICAgICAgIGNvbnN0IGJ5ID0gY29vcmRzW2sgKyAzXTsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBjeCA9IG14ICsgbXkgLSBheTsKICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsgLy8gY2FsY3VsYXRlIGVycm9yIGluIHRoZSBtaWRkbGUgb2YgdGhlIGxvbmcgZWRnZSBvZiB0aGUgdHJpYW5nbGUKCiAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkSGVpZ2h0ID0gKHRlcnJhaW5bYXkgKiBzaXplICsgYXhdICsgdGVycmFpbltieSAqIHNpemUgKyBieF0pIC8gMjsKICAgICAgICBjb25zdCBtaWRkbGVJbmRleCA9IG15ICogc2l6ZSArIG14OwogICAgICAgIGNvbnN0IG1pZGRsZUVycm9yID0gTWF0aC5hYnMoaW50ZXJwb2xhdGVkSGVpZ2h0IC0gdGVycmFpblttaWRkbGVJbmRleF0pOwogICAgICAgIGVycm9yc1ttaWRkbGVJbmRleF0gPSBNYXRoLm1heChlcnJvcnNbbWlkZGxlSW5kZXhdLCBtaWRkbGVFcnJvcik7CgogICAgICAgIGlmIChpIDwgbnVtUGFyZW50VHJpYW5nbGVzKSB7CiAgICAgICAgICAvLyBiaWdnZXIgdHJpYW5nbGVzOyBhY2N1bXVsYXRlIGVycm9yIHdpdGggY2hpbGRyZW4KICAgICAgICAgIGNvbnN0IGxlZnRDaGlsZEluZGV4ID0gKGF5ICsgY3kgPj4gMSkgKiBzaXplICsgKGF4ICsgY3ggPj4gMSk7CiAgICAgICAgICBjb25zdCByaWdodENoaWxkSW5kZXggPSAoYnkgKyBjeSA+PiAxKSAqIHNpemUgKyAoYnggKyBjeCA+PiAxKTsKICAgICAgICAgIGVycm9yc1ttaWRkbGVJbmRleF0gPSBNYXRoLm1heChlcnJvcnNbbWlkZGxlSW5kZXhdLCBlcnJvcnNbbGVmdENoaWxkSW5kZXhdLCBlcnJvcnNbcmlnaHRDaGlsZEluZGV4XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgZ2V0TWVzaChtYXhFcnJvciA9IDAsIG1heExlbmd0aCA9IG51bGwpIHsKICAgICAgY29uc3QgewogICAgICAgIGdyaWRTaXplOiBzaXplLAogICAgICAgIGluZGljZXMKICAgICAgfSA9IHRoaXMubWFydGluaTsKICAgICAgY29uc3QgewogICAgICAgIGVycm9ycwogICAgICB9ID0gdGhpczsKICAgICAgbGV0IG51bVZlcnRpY2VzID0gMDsKICAgICAgbGV0IG51bVRyaWFuZ2xlcyA9IDA7CiAgICAgIGNvbnN0IG1heCA9IHNpemUgLSAxOyAvLyBUaGUgbWF4TGVuZ3RoIHBhcmFtZXRlciB3aWxsIGNhdXNlIHRyaWFuZ2xlcyB0byBiZSBnZW5lcmF0ZWQgdW50aWwgdGhlIGxlZ3MgYXJlIGJlbG93IHRoaXMgbGVuZ3RoCiAgICAgIC8vIEl0IGlzIG1lYW50IHRvIHN1cHBvcnQgY2FzZXMgd2hlcmUgYSBjZXJ0YWluIG1lc2ggZGVuc2l0eSBpcyByZXF1aXJlZCB0byBkbyBzcGhlcmljYWwgbWF0aCBvbiBkaWdpdGFsIGdsb2JlcwoKICAgICAgY29uc3QgbWF4U2NhbGUgPSBtYXhMZW5ndGggfHwgc2l6ZTsgLy8gdXNlIGFuIGluZGV4IGdyaWQgdG8ga2VlcCB0cmFjayBvZiB2ZXJ0aWNlcyB0aGF0IHdlcmUgYWxyZWFkeSB1c2VkIHRvIGF2b2lkIGR1cGxpY2F0aW9uCgogICAgICBpbmRpY2VzLmZpbGwoMCk7IC8vIHJldHJpZXZlIG1lc2ggaW4gdHdvIHN0YWdlcyB0aGF0IGJvdGggdHJhdmVyc2UgdGhlIGVycm9yIG1hcDoKICAgICAgLy8gLSBjb3VudEVsZW1lbnRzOiBmaW5kIHVzZWQgdmVydGljZXMgKGFuZCBhc3NpZ24gZWFjaCBhbiBpbmRleCksIGFuZCBjb3VudCB0cmlhbmdsZXMgKGZvciBtaW5pbXVtIGFsbG9jYXRpb24pCiAgICAgIC8vIC0gcHJvY2Vzc1RyaWFuZ2xlOiBmaWxsIHRoZSBhbGxvY2F0ZWQgdmVydGljZXMgJiB0cmlhbmdsZXMgdHlwZWQgYXJyYXlzCgogICAgICBmdW5jdGlvbiBjb3VudEVsZW1lbnRzKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwoKICAgICAgICBpZiAobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IgfHwgbGVnTGVuZ3RoID4gbWF4U2NhbGUpIHsKICAgICAgICAgIGNvdW50RWxlbWVudHMoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSA9IGluZGljZXNbYnkgKiBzaXplICsgYnhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBpbmRpY2VzW2N5ICogc2l6ZSArIGN4XSA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBudW1UcmlhbmdsZXMrKzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGNvdW50RWxlbWVudHMoMCwgMCwgbWF4LCBtYXgsIG1heCwgMCk7CiAgICAgIGNvdW50RWxlbWVudHMobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CiAgICAgIGNvbnN0IHZlcnRpY2VzID0gbmV3IFVpbnQxNkFycmF5KG51bVZlcnRpY2VzICogMik7CiAgICAgIGNvbnN0IHRyaWFuZ2xlcyA9IG5ldyBVaW50MzJBcnJheShudW1UcmlhbmdsZXMgKiAzKTsKICAgICAgbGV0IHRyaUluZGV4ID0gMDsKCiAgICAgIGZ1bmN0aW9uIHByb2Nlc3NUcmlhbmdsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgY29uc3QgbXggPSBheCArIGJ4ID4+IDE7CiAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CiAgICAgICAgY29uc3QgbGVnTGVuZ3RoID0gTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KTsKCiAgICAgICAgaWYgKGxlZ0xlbmd0aCA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yIHx8IGxlZ0xlbmd0aCA+IG1heFNjYWxlKSB7CiAgICAgICAgICAvLyB0cmlhbmdsZSBkb2Vzbid0IGFwcHJveGltYXRlIHRoZSBzdXJmYWNlIHdlbGwgZW5vdWdoOyBkcmlsbCBkb3duIGZ1cnRoZXIKICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShieCwgYnksIGN4LCBjeSwgbXgsIG15KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgIGNvbnN0IGEgPSBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSAtIDE7CiAgICAgICAgICBjb25zdCBiID0gaW5kaWNlc1tieSAqIHNpemUgKyBieF0gLSAxOwogICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBhXSA9IGF4OwogICAgICAgICAgdmVydGljZXNbMiAqIGEgKyAxXSA9IGF5OwogICAgICAgICAgdmVydGljZXNbMiAqIGJdID0gYng7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CiAgICAgICAgICB2ZXJ0aWNlc1syICogY10gPSBjeDsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGE7CiAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBiOwogICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHByb2Nlc3NUcmlhbmdsZSgwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgcHJvY2Vzc1RyaWFuZ2xlKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwogICAgICByZXR1cm4gewogICAgICAgIHZlcnRpY2VzLAogICAgICAgIHRyaWFuZ2xlcwogICAgICB9OwogICAgfQoKICB9CgogIGZ1bmN0aW9uIGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZuKSB7CiAgICB2YXIgbW9kdWxlID0geyBleHBvcnRzOiB7fSB9OwogIAlyZXR1cm4gZm4obW9kdWxlLCBtb2R1bGUuZXhwb3J0cyksIG1vZHVsZS5leHBvcnRzOwogIH0KCiAgLyoqCiAgICogQ29weXJpZ2h0IChjKSAyMDE0LXByZXNlbnQsIEZhY2Vib29rLCBJbmMuCiAgICoKICAgKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGUKICAgKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuCiAgICovCgogIGNyZWF0ZUNvbW1vbmpzTW9kdWxlKGZ1bmN0aW9uIChtb2R1bGUpIHsKICB2YXIgcnVudGltZSA9IChmdW5jdGlvbiAoZXhwb3J0cykgewoKICAgIHZhciBPcCA9IE9iamVjdC5wcm90b3R5cGU7CiAgICB2YXIgaGFzT3duID0gT3AuaGFzT3duUHJvcGVydHk7CiAgICB2YXIgdW5kZWZpbmVkJDE7IC8vIE1vcmUgY29tcHJlc3NpYmxlIHRoYW4gdm9pZCAwLgogICAgdmFyICRTeW1ib2wgPSB0eXBlb2YgU3ltYm9sID09PSAiZnVuY3Rpb24iID8gU3ltYm9sIDoge307CiAgICB2YXIgaXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLml0ZXJhdG9yIHx8ICJAQGl0ZXJhdG9yIjsKICAgIHZhciBhc3luY0l0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5hc3luY0l0ZXJhdG9yIHx8ICJAQGFzeW5jSXRlcmF0b3IiOwogICAgdmFyIHRvU3RyaW5nVGFnU3ltYm9sID0gJFN5bWJvbC50b1N0cmluZ1RhZyB8fCAiQEB0b1N0cmluZ1RhZyI7CgogICAgZnVuY3Rpb24gZGVmaW5lKG9iaiwga2V5LCB2YWx1ZSkgewogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHsKICAgICAgICB2YWx1ZTogdmFsdWUsCiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgd3JpdGFibGU6IHRydWUKICAgICAgfSk7CiAgICAgIHJldHVybiBvYmpba2V5XTsKICAgIH0KICAgIHRyeSB7CiAgICAgIC8vIElFIDggaGFzIGEgYnJva2VuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSB0aGF0IG9ubHkgd29ya3Mgb24gRE9NIG9iamVjdHMuCiAgICAgIGRlZmluZSh7fSwgIiIpOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIGRlZmluZSA9IGZ1bmN0aW9uKG9iaiwga2V5LCB2YWx1ZSkgewogICAgICAgIHJldHVybiBvYmpba2V5XSA9IHZhbHVlOwogICAgICB9OwogICAgfQoKICAgIGZ1bmN0aW9uIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHsKICAgICAgLy8gSWYgb3V0ZXJGbiBwcm92aWRlZCBhbmQgb3V0ZXJGbi5wcm90b3R5cGUgaXMgYSBHZW5lcmF0b3IsIHRoZW4gb3V0ZXJGbi5wcm90b3R5cGUgaW5zdGFuY2VvZiBHZW5lcmF0b3IuCiAgICAgIHZhciBwcm90b0dlbmVyYXRvciA9IG91dGVyRm4gJiYgb3V0ZXJGbi5wcm90b3R5cGUgaW5zdGFuY2VvZiBHZW5lcmF0b3IgPyBvdXRlckZuIDogR2VuZXJhdG9yOwogICAgICB2YXIgZ2VuZXJhdG9yID0gT2JqZWN0LmNyZWF0ZShwcm90b0dlbmVyYXRvci5wcm90b3R5cGUpOwogICAgICB2YXIgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTsKCiAgICAgIC8vIFRoZSAuX2ludm9rZSBtZXRob2QgdW5pZmllcyB0aGUgaW1wbGVtZW50YXRpb25zIG9mIHRoZSAubmV4dCwKICAgICAgLy8gLnRocm93LCBhbmQgLnJldHVybiBtZXRob2RzLgogICAgICBnZW5lcmF0b3IuX2ludm9rZSA9IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7CgogICAgICByZXR1cm4gZ2VuZXJhdG9yOwogICAgfQogICAgZXhwb3J0cy53cmFwID0gd3JhcDsKCiAgICAvLyBUcnkvY2F0Y2ggaGVscGVyIHRvIG1pbmltaXplIGRlb3B0aW1pemF0aW9ucy4gUmV0dXJucyBhIGNvbXBsZXRpb24KICAgIC8vIHJlY29yZCBsaWtlIGNvbnRleHQudHJ5RW50cmllc1tpXS5jb21wbGV0aW9uLiBUaGlzIGludGVyZmFjZSBjb3VsZAogICAgLy8gaGF2ZSBiZWVuIChhbmQgd2FzIHByZXZpb3VzbHkpIGRlc2lnbmVkIHRvIHRha2UgYSBjbG9zdXJlIHRvIGJlCiAgICAvLyBpbnZva2VkIHdpdGhvdXQgYXJndW1lbnRzLCBidXQgaW4gYWxsIHRoZSBjYXNlcyB3ZSBjYXJlIGFib3V0IHdlCiAgICAvLyBhbHJlYWR5IGhhdmUgYW4gZXhpc3RpbmcgbWV0aG9kIHdlIHdhbnQgdG8gY2FsbCwgc28gdGhlcmUncyBubyBuZWVkCiAgICAvLyB0byBjcmVhdGUgYSBuZXcgZnVuY3Rpb24gb2JqZWN0LiBXZSBjYW4gZXZlbiBnZXQgYXdheSB3aXRoIGFzc3VtaW5nCiAgICAvLyB0aGUgbWV0aG9kIHRha2VzIGV4YWN0bHkgb25lIGFyZ3VtZW50LCBzaW5jZSB0aGF0IGhhcHBlbnMgdG8gYmUgdHJ1ZQogICAgLy8gaW4gZXZlcnkgY2FzZSwgc28gd2UgZG9uJ3QgaGF2ZSB0byB0b3VjaCB0aGUgYXJndW1lbnRzIG9iamVjdC4gVGhlCiAgICAvLyBvbmx5IGFkZGl0aW9uYWwgYWxsb2NhdGlvbiByZXF1aXJlZCBpcyB0aGUgY29tcGxldGlvbiByZWNvcmQsIHdoaWNoCiAgICAvLyBoYXMgYSBzdGFibGUgc2hhcGUgYW5kIHNvIGhvcGVmdWxseSBzaG91bGQgYmUgY2hlYXAgdG8gYWxsb2NhdGUuCiAgICBmdW5jdGlvbiB0cnlDYXRjaChmbiwgb2JqLCBhcmcpIHsKICAgICAgdHJ5IHsKICAgICAgICByZXR1cm4geyB0eXBlOiAibm9ybWFsIiwgYXJnOiBmbi5jYWxsKG9iaiwgYXJnKSB9OwogICAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgICByZXR1cm4geyB0eXBlOiAidGhyb3ciLCBhcmc6IGVyciB9OwogICAgICB9CiAgICB9CgogICAgdmFyIEdlblN0YXRlU3VzcGVuZGVkU3RhcnQgPSAic3VzcGVuZGVkU3RhcnQiOwogICAgdmFyIEdlblN0YXRlU3VzcGVuZGVkWWllbGQgPSAic3VzcGVuZGVkWWllbGQiOwogICAgdmFyIEdlblN0YXRlRXhlY3V0aW5nID0gImV4ZWN1dGluZyI7CiAgICB2YXIgR2VuU3RhdGVDb21wbGV0ZWQgPSAiY29tcGxldGVkIjsKCiAgICAvLyBSZXR1cm5pbmcgdGhpcyBvYmplY3QgZnJvbSB0aGUgaW5uZXJGbiBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzCiAgICAvLyBicmVha2luZyBvdXQgb2YgdGhlIGRpc3BhdGNoIHN3aXRjaCBzdGF0ZW1lbnQuCiAgICB2YXIgQ29udGludWVTZW50aW5lbCA9IHt9OwoKICAgIC8vIER1bW15IGNvbnN0cnVjdG9yIGZ1bmN0aW9ucyB0aGF0IHdlIHVzZSBhcyB0aGUgLmNvbnN0cnVjdG9yIGFuZAogICAgLy8gLmNvbnN0cnVjdG9yLnByb3RvdHlwZSBwcm9wZXJ0aWVzIGZvciBmdW5jdGlvbnMgdGhhdCByZXR1cm4gR2VuZXJhdG9yCiAgICAvLyBvYmplY3RzLiBGb3IgZnVsbCBzcGVjIGNvbXBsaWFuY2UsIHlvdSBtYXkgd2lzaCB0byBjb25maWd1cmUgeW91cgogICAgLy8gbWluaWZpZXIgbm90IHRvIG1hbmdsZSB0aGUgbmFtZXMgb2YgdGhlc2UgdHdvIGZ1bmN0aW9ucy4KICAgIGZ1bmN0aW9uIEdlbmVyYXRvcigpIHt9CiAgICBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9CiAgICBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSgpIHt9CgogICAgLy8gVGhpcyBpcyBhIHBvbHlmaWxsIGZvciAlSXRlcmF0b3JQcm90b3R5cGUlIGZvciBlbnZpcm9ubWVudHMgdGhhdAogICAgLy8gZG9uJ3QgbmF0aXZlbHkgc3VwcG9ydCBpdC4KICAgIHZhciBJdGVyYXRvclByb3RvdHlwZSA9IHt9OwogICAgSXRlcmF0b3JQcm90b3R5cGVbaXRlcmF0b3JTeW1ib2xdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgdmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mOwogICAgdmFyIE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG8gJiYgZ2V0UHJvdG8oZ2V0UHJvdG8odmFsdWVzKFtdKSkpOwogICAgaWYgKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlICYmCiAgICAgICAgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgIT09IE9wICYmCiAgICAgICAgaGFzT3duLmNhbGwoTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sKSkgewogICAgICAvLyBUaGlzIGVudmlyb25tZW50IGhhcyBhIG5hdGl2ZSAlSXRlcmF0b3JQcm90b3R5cGUlOyB1c2UgaXQgaW5zdGVhZAogICAgICAvLyBvZiB0aGUgcG9seWZpbGwuCiAgICAgIEl0ZXJhdG9yUHJvdG90eXBlID0gTmF0aXZlSXRlcmF0b3JQcm90b3R5cGU7CiAgICB9CgogICAgdmFyIEdwID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUucHJvdG90eXBlID0KICAgICAgR2VuZXJhdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUpOwogICAgR2VuZXJhdG9yRnVuY3Rpb24ucHJvdG90eXBlID0gR3AuY29uc3RydWN0b3IgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZTsKICAgIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLmNvbnN0cnVjdG9yID0gR2VuZXJhdG9yRnVuY3Rpb247CiAgICBHZW5lcmF0b3JGdW5jdGlvbi5kaXNwbGF5TmFtZSA9IGRlZmluZSgKICAgICAgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsCiAgICAgIHRvU3RyaW5nVGFnU3ltYm9sLAogICAgICAiR2VuZXJhdG9yRnVuY3Rpb24iCiAgICApOwoKICAgIC8vIEhlbHBlciBmb3IgZGVmaW5pbmcgdGhlIC5uZXh0LCAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMgb2YgdGhlCiAgICAvLyBJdGVyYXRvciBpbnRlcmZhY2UgaW4gdGVybXMgb2YgYSBzaW5nbGUgLl9pbnZva2UgbWV0aG9kLgogICAgZnVuY3Rpb24gZGVmaW5lSXRlcmF0b3JNZXRob2RzKHByb3RvdHlwZSkgewogICAgICBbIm5leHQiLCAidGhyb3ciLCAicmV0dXJuIl0uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHsKICAgICAgICBkZWZpbmUocHJvdG90eXBlLCBtZXRob2QsIGZ1bmN0aW9uKGFyZykgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2ludm9rZShtZXRob2QsIGFyZyk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfQoKICAgIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbiA9IGZ1bmN0aW9uKGdlbkZ1bikgewogICAgICB2YXIgY3RvciA9IHR5cGVvZiBnZW5GdW4gPT09ICJmdW5jdGlvbiIgJiYgZ2VuRnVuLmNvbnN0cnVjdG9yOwogICAgICByZXR1cm4gY3RvcgogICAgICAgID8gY3RvciA9PT0gR2VuZXJhdG9yRnVuY3Rpb24gfHwKICAgICAgICAgIC8vIEZvciB0aGUgbmF0aXZlIEdlbmVyYXRvckZ1bmN0aW9uIGNvbnN0cnVjdG9yLCB0aGUgYmVzdCB3ZSBjYW4KICAgICAgICAgIC8vIGRvIGlzIHRvIGNoZWNrIGl0cyAubmFtZSBwcm9wZXJ0eS4KICAgICAgICAgIChjdG9yLmRpc3BsYXlOYW1lIHx8IGN0b3IubmFtZSkgPT09ICJHZW5lcmF0b3JGdW5jdGlvbiIKICAgICAgICA6IGZhbHNlOwogICAgfTsKCiAgICBleHBvcnRzLm1hcmsgPSBmdW5jdGlvbihnZW5GdW4pIHsKICAgICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihnZW5GdW4sIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgICAgICAgZGVmaW5lKGdlbkZ1biwgdG9TdHJpbmdUYWdTeW1ib2wsICJHZW5lcmF0b3JGdW5jdGlvbiIpOwogICAgICB9CiAgICAgIGdlbkZ1bi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEdwKTsKICAgICAgcmV0dXJuIGdlbkZ1bjsKICAgIH07CgogICAgLy8gV2l0aGluIHRoZSBib2R5IG9mIGFueSBhc3luYyBmdW5jdGlvbiwgYGF3YWl0IHhgIGlzIHRyYW5zZm9ybWVkIHRvCiAgICAvLyBgeWllbGQgcmVnZW5lcmF0b3JSdW50aW1lLmF3cmFwKHgpYCwgc28gdGhhdCB0aGUgcnVudGltZSBjYW4gdGVzdAogICAgLy8gYGhhc093bi5jYWxsKHZhbHVlLCAiX19hd2FpdCIpYCB0byBkZXRlcm1pbmUgaWYgdGhlIHlpZWxkZWQgdmFsdWUgaXMKICAgIC8vIG1lYW50IHRvIGJlIGF3YWl0ZWQuCiAgICBleHBvcnRzLmF3cmFwID0gZnVuY3Rpb24oYXJnKSB7CiAgICAgIHJldHVybiB7IF9fYXdhaXQ6IGFyZyB9OwogICAgfTsKCiAgICBmdW5jdGlvbiBBc3luY0l0ZXJhdG9yKGdlbmVyYXRvciwgUHJvbWlzZUltcGwpIHsKICAgICAgZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpIHsKICAgICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTsKICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIHJlamVjdChyZWNvcmQuYXJnKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIHJlc3VsdCA9IHJlY29yZC5hcmc7CiAgICAgICAgICB2YXIgdmFsdWUgPSByZXN1bHQudmFsdWU7CiAgICAgICAgICBpZiAodmFsdWUgJiYKICAgICAgICAgICAgICB0eXBlb2YgdmFsdWUgPT09ICJvYmplY3QiICYmCiAgICAgICAgICAgICAgaGFzT3duLmNhbGwodmFsdWUsICJfX2F3YWl0IikpIHsKICAgICAgICAgICAgcmV0dXJuIFByb21pc2VJbXBsLnJlc29sdmUodmFsdWUuX19hd2FpdCkudGhlbihmdW5jdGlvbih2YWx1ZSkgewogICAgICAgICAgICAgIGludm9rZSgibmV4dCIsIHZhbHVlLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihlcnIpIHsKICAgICAgICAgICAgICBpbnZva2UoInRocm93IiwgZXJyLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZSkudGhlbihmdW5jdGlvbih1bndyYXBwZWQpIHsKICAgICAgICAgICAgLy8gV2hlbiBhIHlpZWxkZWQgUHJvbWlzZSBpcyByZXNvbHZlZCwgaXRzIGZpbmFsIHZhbHVlIGJlY29tZXMKICAgICAgICAgICAgLy8gdGhlIC52YWx1ZSBvZiB0aGUgUHJvbWlzZTx7dmFsdWUsZG9uZX0+IHJlc3VsdCBmb3IgdGhlCiAgICAgICAgICAgIC8vIGN1cnJlbnQgaXRlcmF0aW9uLgogICAgICAgICAgICByZXN1bHQudmFsdWUgPSB1bndyYXBwZWQ7CiAgICAgICAgICAgIHJlc29sdmUocmVzdWx0KTsKICAgICAgICAgIH0sIGZ1bmN0aW9uKGVycm9yKSB7CiAgICAgICAgICAgIC8vIElmIGEgcmVqZWN0ZWQgUHJvbWlzZSB3YXMgeWllbGRlZCwgdGhyb3cgdGhlIHJlamVjdGlvbiBiYWNrCiAgICAgICAgICAgIC8vIGludG8gdGhlIGFzeW5jIGdlbmVyYXRvciBmdW5jdGlvbiBzbyBpdCBjYW4gYmUgaGFuZGxlZCB0aGVyZS4KICAgICAgICAgICAgcmV0dXJuIGludm9rZSgidGhyb3ciLCBlcnJvciwgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIHByZXZpb3VzUHJvbWlzZTsKCiAgICAgIGZ1bmN0aW9uIGVucXVldWUobWV0aG9kLCBhcmcpIHsKICAgICAgICBmdW5jdGlvbiBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZygpIHsKICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZUltcGwoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICAgIGludm9rZShtZXRob2QsIGFyZywgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHByZXZpb3VzUHJvbWlzZSA9CiAgICAgICAgICAvLyBJZiBlbnF1ZXVlIGhhcyBiZWVuIGNhbGxlZCBiZWZvcmUsIHRoZW4gd2Ugd2FudCB0byB3YWl0IHVudGlsCiAgICAgICAgICAvLyBhbGwgcHJldmlvdXMgUHJvbWlzZXMgaGF2ZSBiZWVuIHJlc29sdmVkIGJlZm9yZSBjYWxsaW5nIGludm9rZSwKICAgICAgICAgIC8vIHNvIHRoYXQgcmVzdWx0cyBhcmUgYWx3YXlzIGRlbGl2ZXJlZCBpbiB0aGUgY29ycmVjdCBvcmRlci4gSWYKICAgICAgICAgIC8vIGVucXVldWUgaGFzIG5vdCBiZWVuIGNhbGxlZCBiZWZvcmUsIHRoZW4gaXQgaXMgaW1wb3J0YW50IHRvCiAgICAgICAgICAvLyBjYWxsIGludm9rZSBpbW1lZGlhdGVseSwgd2l0aG91dCB3YWl0aW5nIG9uIGEgY2FsbGJhY2sgdG8gZmlyZSwKICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIGFzeW5jIGdlbmVyYXRvciBmdW5jdGlvbiBoYXMgdGhlIG9wcG9ydHVuaXR5IHRvIGRvCiAgICAgICAgICAvLyBhbnkgbmVjZXNzYXJ5IHNldHVwIGluIGEgcHJlZGljdGFibGUgd2F5LiBUaGlzIHByZWRpY3RhYmlsaXR5CiAgICAgICAgICAvLyBpcyB3aHkgdGhlIFByb21pc2UgY29uc3RydWN0b3Igc3luY2hyb25vdXNseSBpbnZva2VzIGl0cwogICAgICAgICAgLy8gZXhlY3V0b3IgY2FsbGJhY2ssIGFuZCB3aHkgYXN5bmMgZnVuY3Rpb25zIHN5bmNocm9ub3VzbHkKICAgICAgICAgIC8vIGV4ZWN1dGUgY29kZSBiZWZvcmUgdGhlIGZpcnN0IGF3YWl0LiBTaW5jZSB3ZSBpbXBsZW1lbnQgc2ltcGxlCiAgICAgICAgICAvLyBhc3luYyBmdW5jdGlvbnMgaW4gdGVybXMgb2YgYXN5bmMgZ2VuZXJhdG9ycywgaXQgaXMgZXNwZWNpYWxseQogICAgICAgICAgLy8gaW1wb3J0YW50IHRvIGdldCB0aGlzIHJpZ2h0LCBldmVuIHRob3VnaCBpdCByZXF1aXJlcyBjYXJlLgogICAgICAgICAgcHJldmlvdXNQcm9taXNlID8gcHJldmlvdXNQcm9taXNlLnRoZW4oCiAgICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnLAogICAgICAgICAgICAvLyBBdm9pZCBwcm9wYWdhdGluZyBmYWlsdXJlcyB0byBQcm9taXNlcyByZXR1cm5lZCBieSBsYXRlcgogICAgICAgICAgICAvLyBpbnZvY2F0aW9ucyBvZiB0aGUgaXRlcmF0b3IuCiAgICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnCiAgICAgICAgICApIDogY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKTsKICAgICAgfQoKICAgICAgLy8gRGVmaW5lIHRoZSB1bmlmaWVkIGhlbHBlciBtZXRob2QgdGhhdCBpcyB1c2VkIHRvIGltcGxlbWVudCAubmV4dCwKICAgICAgLy8gLnRocm93LCBhbmQgLnJldHVybiAoc2VlIGRlZmluZUl0ZXJhdG9yTWV0aG9kcykuCiAgICAgIHRoaXMuX2ludm9rZSA9IGVucXVldWU7CiAgICB9CgogICAgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEFzeW5jSXRlcmF0b3IucHJvdG90eXBlKTsKICAgIEFzeW5jSXRlcmF0b3IucHJvdG90eXBlW2FzeW5jSXRlcmF0b3JTeW1ib2xdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH07CiAgICBleHBvcnRzLkFzeW5jSXRlcmF0b3IgPSBBc3luY0l0ZXJhdG9yOwoKICAgIC8vIE5vdGUgdGhhdCBzaW1wbGUgYXN5bmMgZnVuY3Rpb25zIGFyZSBpbXBsZW1lbnRlZCBvbiB0b3Agb2YKICAgIC8vIEFzeW5jSXRlcmF0b3Igb2JqZWN0czsgdGhleSBqdXN0IHJldHVybiBhIFByb21pc2UgZm9yIHRoZSB2YWx1ZSBvZgogICAgLy8gdGhlIGZpbmFsIHJlc3VsdCBwcm9kdWNlZCBieSB0aGUgaXRlcmF0b3IuCiAgICBleHBvcnRzLmFzeW5jID0gZnVuY3Rpb24oaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QsIFByb21pc2VJbXBsKSB7CiAgICAgIGlmIChQcm9taXNlSW1wbCA9PT0gdm9pZCAwKSBQcm9taXNlSW1wbCA9IFByb21pc2U7CgogICAgICB2YXIgaXRlciA9IG5ldyBBc3luY0l0ZXJhdG9yKAogICAgICAgIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpLAogICAgICAgIFByb21pc2VJbXBsCiAgICAgICk7CgogICAgICByZXR1cm4gZXhwb3J0cy5pc0dlbmVyYXRvckZ1bmN0aW9uKG91dGVyRm4pCiAgICAgICAgPyBpdGVyIC8vIElmIG91dGVyRm4gaXMgYSBnZW5lcmF0b3IsIHJldHVybiB0aGUgZnVsbCBpdGVyYXRvci4KICAgICAgICA6IGl0ZXIubmV4dCgpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQuZG9uZSA/IHJlc3VsdC52YWx1ZSA6IGl0ZXIubmV4dCgpOwogICAgICAgICAgfSk7CiAgICB9OwoKICAgIGZ1bmN0aW9uIG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCkgewogICAgICB2YXIgc3RhdGUgPSBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0OwoKICAgICAgcmV0dXJuIGZ1bmN0aW9uIGludm9rZShtZXRob2QsIGFyZykgewogICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVFeGVjdXRpbmcpIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiR2VuZXJhdG9yIGlzIGFscmVhZHkgcnVubmluZyIpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZUNvbXBsZXRlZCkgewogICAgICAgICAgaWYgKG1ldGhvZCA9PT0gInRocm93IikgewogICAgICAgICAgICB0aHJvdyBhcmc7CiAgICAgICAgICB9CgogICAgICAgICAgLy8gQmUgZm9yZ2l2aW5nLCBwZXIgMjUuMy4zLjMuMyBvZiB0aGUgc3BlYzoKICAgICAgICAgIC8vIGh0dHBzOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy1nZW5lcmF0b3JyZXN1bWUKICAgICAgICAgIHJldHVybiBkb25lUmVzdWx0KCk7CiAgICAgICAgfQoKICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IG1ldGhvZDsKICAgICAgICBjb250ZXh0LmFyZyA9IGFyZzsKCiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIHZhciBkZWxlZ2F0ZSA9IGNvbnRleHQuZGVsZWdhdGU7CiAgICAgICAgICBpZiAoZGVsZWdhdGUpIHsKICAgICAgICAgICAgdmFyIGRlbGVnYXRlUmVzdWx0ID0gbWF5YmVJbnZva2VEZWxlZ2F0ZShkZWxlZ2F0ZSwgY29udGV4dCk7CiAgICAgICAgICAgIGlmIChkZWxlZ2F0ZVJlc3VsdCkgewogICAgICAgICAgICAgIGlmIChkZWxlZ2F0ZVJlc3VsdCA9PT0gQ29udGludWVTZW50aW5lbCkgY29udGludWU7CiAgICAgICAgICAgICAgcmV0dXJuIGRlbGVnYXRlUmVzdWx0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSAibmV4dCIpIHsKICAgICAgICAgICAgLy8gU2V0dGluZyBjb250ZXh0Ll9zZW50IGZvciBsZWdhY3kgc3VwcG9ydCBvZiBCYWJlbCdzCiAgICAgICAgICAgIC8vIGZ1bmN0aW9uLnNlbnQgaW1wbGVtZW50YXRpb24uCiAgICAgICAgICAgIGNvbnRleHQuc2VudCA9IGNvbnRleHQuX3NlbnQgPSBjb250ZXh0LmFyZzsKCiAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRleHQubWV0aG9kID09PSAidGhyb3ciKSB7CiAgICAgICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVTdXNwZW5kZWRTdGFydCkgewogICAgICAgICAgICAgIHN0YXRlID0gR2VuU3RhdGVDb21wbGV0ZWQ7CiAgICAgICAgICAgICAgdGhyb3cgY29udGV4dC5hcmc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpOwoKICAgICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICAgIGNvbnRleHQuYWJydXB0KCJyZXR1cm4iLCBjb250ZXh0LmFyZyk7CiAgICAgICAgICB9CgogICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUV4ZWN1dGluZzsKCiAgICAgICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7CiAgICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJub3JtYWwiKSB7CiAgICAgICAgICAgIC8vIElmIGFuIGV4Y2VwdGlvbiBpcyB0aHJvd24gZnJvbSBpbm5lckZuLCB3ZSBsZWF2ZSBzdGF0ZSA9PT0KICAgICAgICAgICAgLy8gR2VuU3RhdGVFeGVjdXRpbmcgYW5kIGxvb3AgYmFjayBmb3IgYW5vdGhlciBpbnZvY2F0aW9uLgogICAgICAgICAgICBzdGF0ZSA9IGNvbnRleHQuZG9uZQogICAgICAgICAgICAgID8gR2VuU3RhdGVDb21wbGV0ZWQKICAgICAgICAgICAgICA6IEdlblN0YXRlU3VzcGVuZGVkWWllbGQ7CgogICAgICAgICAgICBpZiAocmVjb3JkLmFyZyA9PT0gQ29udGludWVTZW50aW5lbCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgIHZhbHVlOiByZWNvcmQuYXJnLAogICAgICAgICAgICAgIGRvbmU6IGNvbnRleHQuZG9uZQogICAgICAgICAgICB9OwoKICAgICAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDsKICAgICAgICAgICAgLy8gRGlzcGF0Y2ggdGhlIGV4Y2VwdGlvbiBieSBsb29waW5nIGJhY2sgYXJvdW5kIHRvIHRoZQogICAgICAgICAgICAvLyBjb250ZXh0LmRpc3BhdGNoRXhjZXB0aW9uKGNvbnRleHQuYXJnKSBjYWxsIGFib3ZlLgogICAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJ0aHJvdyI7CiAgICAgICAgICAgIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICB9CgogICAgLy8gQ2FsbCBkZWxlZ2F0ZS5pdGVyYXRvcltjb250ZXh0Lm1ldGhvZF0oY29udGV4dC5hcmcpIGFuZCBoYW5kbGUgdGhlCiAgICAvLyByZXN1bHQsIGVpdGhlciBieSByZXR1cm5pbmcgYSB7IHZhbHVlLCBkb25lIH0gcmVzdWx0IGZyb20gdGhlCiAgICAvLyBkZWxlZ2F0ZSBpdGVyYXRvciwgb3IgYnkgbW9kaWZ5aW5nIGNvbnRleHQubWV0aG9kIGFuZCBjb250ZXh0LmFyZywKICAgIC8vIHNldHRpbmcgY29udGV4dC5kZWxlZ2F0ZSB0byBudWxsLCBhbmQgcmV0dXJuaW5nIHRoZSBDb250aW51ZVNlbnRpbmVsLgogICAgZnVuY3Rpb24gbWF5YmVJbnZva2VEZWxlZ2F0ZShkZWxlZ2F0ZSwgY29udGV4dCkgewogICAgICB2YXIgbWV0aG9kID0gZGVsZWdhdGUuaXRlcmF0b3JbY29udGV4dC5tZXRob2RdOwogICAgICBpZiAobWV0aG9kID09PSB1bmRlZmluZWQkMSkgewogICAgICAgIC8vIEEgLnRocm93IG9yIC5yZXR1cm4gd2hlbiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIG5vIC50aHJvdwogICAgICAgIC8vIG1ldGhvZCBhbHdheXMgdGVybWluYXRlcyB0aGUgeWllbGQqIGxvb3AuCiAgICAgICAgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICAgIGlmIChjb250ZXh0Lm1ldGhvZCA9PT0gInRocm93IikgewogICAgICAgICAgLy8gTm90ZTogWyJyZXR1cm4iXSBtdXN0IGJlIHVzZWQgZm9yIEVTMyBwYXJzaW5nIGNvbXBhdGliaWxpdHkuCiAgICAgICAgICBpZiAoZGVsZWdhdGUuaXRlcmF0b3JbInJldHVybiJdKSB7CiAgICAgICAgICAgIC8vIElmIHRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBoYXMgYSByZXR1cm4gbWV0aG9kLCBnaXZlIGl0IGEKICAgICAgICAgICAgLy8gY2hhbmNlIHRvIGNsZWFuIHVwLgogICAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJyZXR1cm4iOwogICAgICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCQxOwogICAgICAgICAgICBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTsKCiAgICAgICAgICAgIGlmIChjb250ZXh0Lm1ldGhvZCA9PT0gInRocm93IikgewogICAgICAgICAgICAgIC8vIElmIG1heWJlSW52b2tlRGVsZWdhdGUoY29udGV4dCkgY2hhbmdlZCBjb250ZXh0Lm1ldGhvZCBmcm9tCiAgICAgICAgICAgICAgLy8gInJldHVybiIgdG8gInRocm93IiwgbGV0IHRoYXQgb3ZlcnJpZGUgdGhlIFR5cGVFcnJvciBiZWxvdy4KICAgICAgICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gInRocm93IjsKICAgICAgICAgIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcigKICAgICAgICAgICAgIlRoZSBpdGVyYXRvciBkb2VzIG5vdCBwcm92aWRlIGEgJ3Rocm93JyBtZXRob2QiKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICB9CgogICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2gobWV0aG9kLCBkZWxlZ2F0ZS5pdGVyYXRvciwgY29udGV4dC5hcmcpOwoKICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgY29udGV4dC5tZXRob2QgPSAidGhyb3ciOwogICAgICAgIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZzsKICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgfQoKICAgICAgdmFyIGluZm8gPSByZWNvcmQuYXJnOwoKICAgICAgaWYgKCEgaW5mbykgewogICAgICAgIGNvbnRleHQubWV0aG9kID0gInRocm93IjsKICAgICAgICBjb250ZXh0LmFyZyA9IG5ldyBUeXBlRXJyb3IoIml0ZXJhdG9yIHJlc3VsdCBpcyBub3QgYW4gb2JqZWN0Iik7CiAgICAgICAgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGw7CiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgIH0KCiAgICAgIGlmIChpbmZvLmRvbmUpIHsKICAgICAgICAvLyBBc3NpZ24gdGhlIHJlc3VsdCBvZiB0aGUgZmluaXNoZWQgZGVsZWdhdGUgdG8gdGhlIHRlbXBvcmFyeQogICAgICAgIC8vIHZhcmlhYmxlIHNwZWNpZmllZCBieSBkZWxlZ2F0ZS5yZXN1bHROYW1lIChzZWUgZGVsZWdhdGVZaWVsZCkuCiAgICAgICAgY29udGV4dFtkZWxlZ2F0ZS5yZXN1bHROYW1lXSA9IGluZm8udmFsdWU7CgogICAgICAgIC8vIFJlc3VtZSBleGVjdXRpb24gYXQgdGhlIGRlc2lyZWQgbG9jYXRpb24gKHNlZSBkZWxlZ2F0ZVlpZWxkKS4KICAgICAgICBjb250ZXh0Lm5leHQgPSBkZWxlZ2F0ZS5uZXh0TG9jOwoKICAgICAgICAvLyBJZiBjb250ZXh0Lm1ldGhvZCB3YXMgInRocm93IiBidXQgdGhlIGRlbGVnYXRlIGhhbmRsZWQgdGhlCiAgICAgICAgLy8gZXhjZXB0aW9uLCBsZXQgdGhlIG91dGVyIGdlbmVyYXRvciBwcm9jZWVkIG5vcm1hbGx5LiBJZgogICAgICAgIC8vIGNvbnRleHQubWV0aG9kIHdhcyAibmV4dCIsIGZvcmdldCBjb250ZXh0LmFyZyBzaW5jZSBpdCBoYXMgYmVlbgogICAgICAgIC8vICJjb25zdW1lZCIgYnkgdGhlIGRlbGVnYXRlIGl0ZXJhdG9yLiBJZiBjb250ZXh0Lm1ldGhvZCB3YXMKICAgICAgICAvLyAicmV0dXJuIiwgYWxsb3cgdGhlIG9yaWdpbmFsIC5yZXR1cm4gY2FsbCB0byBjb250aW51ZSBpbiB0aGUKICAgICAgICAvLyBvdXRlciBnZW5lcmF0b3IuCiAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kICE9PSAicmV0dXJuIikgewogICAgICAgICAgY29udGV4dC5tZXRob2QgPSAibmV4dCI7CiAgICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCQxOwogICAgICAgIH0KCiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gUmUteWllbGQgdGhlIHJlc3VsdCByZXR1cm5lZCBieSB0aGUgZGVsZWdhdGUgbWV0aG9kLgogICAgICAgIHJldHVybiBpbmZvOwogICAgICB9CgogICAgICAvLyBUaGUgZGVsZWdhdGUgaXRlcmF0b3IgaXMgZmluaXNoZWQsIHNvIGZvcmdldCBpdCBhbmQgY29udGludWUgd2l0aAogICAgICAvLyB0aGUgb3V0ZXIgZ2VuZXJhdG9yLgogICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICB9CgogICAgLy8gRGVmaW5lIEdlbmVyYXRvci5wcm90b3R5cGUue25leHQsdGhyb3cscmV0dXJufSBpbiB0ZXJtcyBvZiB0aGUKICAgIC8vIHVuaWZpZWQgLl9pbnZva2UgaGVscGVyIG1ldGhvZC4KICAgIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhHcCk7CgogICAgZGVmaW5lKEdwLCB0b1N0cmluZ1RhZ1N5bWJvbCwgIkdlbmVyYXRvciIpOwoKICAgIC8vIEEgR2VuZXJhdG9yIHNob3VsZCBhbHdheXMgcmV0dXJuIGl0c2VsZiBhcyB0aGUgaXRlcmF0b3Igb2JqZWN0IHdoZW4gdGhlCiAgICAvLyBAQGl0ZXJhdG9yIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBpdC4gU29tZSBicm93c2VycycgaW1wbGVtZW50YXRpb25zIG9mIHRoZQogICAgLy8gaXRlcmF0b3IgcHJvdG90eXBlIGNoYWluIGluY29ycmVjdGx5IGltcGxlbWVudCB0aGlzLCBjYXVzaW5nIHRoZSBHZW5lcmF0b3IKICAgIC8vIG9iamVjdCB0byBub3QgYmUgcmV0dXJuZWQgZnJvbSB0aGlzIGNhbGwuIFRoaXMgZW5zdXJlcyB0aGF0IGRvZXNuJ3QgaGFwcGVuLgogICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWdlbmVyYXRvci9pc3N1ZXMvMjc0IGZvciBtb3JlIGRldGFpbHMuCiAgICBHcFtpdGVyYXRvclN5bWJvbF0gPSBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9OwoKICAgIEdwLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiAiW29iamVjdCBHZW5lcmF0b3JdIjsKICAgIH07CgogICAgZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHsKICAgICAgdmFyIGVudHJ5ID0geyB0cnlMb2M6IGxvY3NbMF0gfTsKCiAgICAgIGlmICgxIGluIGxvY3MpIHsKICAgICAgICBlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV07CiAgICAgIH0KCiAgICAgIGlmICgyIGluIGxvY3MpIHsKICAgICAgICBlbnRyeS5maW5hbGx5TG9jID0gbG9jc1syXTsKICAgICAgICBlbnRyeS5hZnRlckxvYyA9IGxvY3NbM107CiAgICAgIH0KCiAgICAgIHRoaXMudHJ5RW50cmllcy5wdXNoKGVudHJ5KTsKICAgIH0KCiAgICBmdW5jdGlvbiByZXNldFRyeUVudHJ5KGVudHJ5KSB7CiAgICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uIHx8IHt9OwogICAgICByZWNvcmQudHlwZSA9ICJub3JtYWwiOwogICAgICBkZWxldGUgcmVjb3JkLmFyZzsKICAgICAgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDsKICAgIH0KCiAgICBmdW5jdGlvbiBDb250ZXh0KHRyeUxvY3NMaXN0KSB7CiAgICAgIC8vIFRoZSByb290IGVudHJ5IG9iamVjdCAoZWZmZWN0aXZlbHkgYSB0cnkgc3RhdGVtZW50IHdpdGhvdXQgYSBjYXRjaAogICAgICAvLyBvciBhIGZpbmFsbHkgYmxvY2spIGdpdmVzIHVzIGEgcGxhY2UgdG8gc3RvcmUgdmFsdWVzIHRocm93biBmcm9tCiAgICAgIC8vIGxvY2F0aW9ucyB3aGVyZSB0aGVyZSBpcyBubyBlbmNsb3NpbmcgdHJ5IHN0YXRlbWVudC4KICAgICAgdGhpcy50cnlFbnRyaWVzID0gW3sgdHJ5TG9jOiAicm9vdCIgfV07CiAgICAgIHRyeUxvY3NMaXN0LmZvckVhY2gocHVzaFRyeUVudHJ5LCB0aGlzKTsKICAgICAgdGhpcy5yZXNldCh0cnVlKTsKICAgIH0KCiAgICBleHBvcnRzLmtleXMgPSBmdW5jdGlvbihvYmplY3QpIHsKICAgICAgdmFyIGtleXMgPSBbXTsKICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkgewogICAgICAgIGtleXMucHVzaChrZXkpOwogICAgICB9CiAgICAgIGtleXMucmV2ZXJzZSgpOwoKICAgICAgLy8gUmF0aGVyIHRoYW4gcmV0dXJuaW5nIGFuIG9iamVjdCB3aXRoIGEgbmV4dCBtZXRob2QsIHdlIGtlZXAKICAgICAgLy8gdGhpbmdzIHNpbXBsZSBhbmQgcmV0dXJuIHRoZSBuZXh0IGZ1bmN0aW9uIGl0c2VsZi4KICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgICAgd2hpbGUgKGtleXMubGVuZ3RoKSB7CiAgICAgICAgICB2YXIga2V5ID0ga2V5cy5wb3AoKTsKICAgICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7CiAgICAgICAgICAgIG5leHQudmFsdWUgPSBrZXk7CiAgICAgICAgICAgIG5leHQuZG9uZSA9IGZhbHNlOwogICAgICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIFRvIGF2b2lkIGNyZWF0aW5nIGFuIGFkZGl0aW9uYWwgb2JqZWN0LCB3ZSBqdXN0IGhhbmcgdGhlIC52YWx1ZQogICAgICAgIC8vIGFuZCAuZG9uZSBwcm9wZXJ0aWVzIG9mZiB0aGUgbmV4dCBmdW5jdGlvbiBvYmplY3QgaXRzZWxmLiBUaGlzCiAgICAgICAgLy8gYWxzbyBlbnN1cmVzIHRoYXQgdGhlIG1pbmlmaWVyIHdpbGwgbm90IGFub255bWl6ZSB0aGUgZnVuY3Rpb24uCiAgICAgICAgbmV4dC5kb25lID0gdHJ1ZTsKICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgfTsKICAgIH07CgogICAgZnVuY3Rpb24gdmFsdWVzKGl0ZXJhYmxlKSB7CiAgICAgIGlmIChpdGVyYWJsZSkgewogICAgICAgIHZhciBpdGVyYXRvck1ldGhvZCA9IGl0ZXJhYmxlW2l0ZXJhdG9yU3ltYm9sXTsKICAgICAgICBpZiAoaXRlcmF0b3JNZXRob2QpIHsKICAgICAgICAgIHJldHVybiBpdGVyYXRvck1ldGhvZC5jYWxsKGl0ZXJhYmxlKTsKICAgICAgICB9CgogICAgICAgIGlmICh0eXBlb2YgaXRlcmFibGUubmV4dCA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgcmV0dXJuIGl0ZXJhYmxlOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFpc05hTihpdGVyYWJsZS5sZW5ndGgpKSB7CiAgICAgICAgICB2YXIgaSA9IC0xLCBuZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHsKICAgICAgICAgICAgd2hpbGUgKCsraSA8IGl0ZXJhYmxlLmxlbmd0aCkgewogICAgICAgICAgICAgIGlmIChoYXNPd24uY2FsbChpdGVyYWJsZSwgaSkpIHsKICAgICAgICAgICAgICAgIG5leHQudmFsdWUgPSBpdGVyYWJsZVtpXTsKICAgICAgICAgICAgICAgIG5leHQuZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBuZXh0LnZhbHVlID0gdW5kZWZpbmVkJDE7CiAgICAgICAgICAgIG5leHQuZG9uZSA9IHRydWU7CgogICAgICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgICAgIH07CgogICAgICAgICAgcmV0dXJuIG5leHQubmV4dCA9IG5leHQ7CiAgICAgICAgfQogICAgICB9CgogICAgICAvLyBSZXR1cm4gYW4gaXRlcmF0b3Igd2l0aCBubyB2YWx1ZXMuCiAgICAgIHJldHVybiB7IG5leHQ6IGRvbmVSZXN1bHQgfTsKICAgIH0KICAgIGV4cG9ydHMudmFsdWVzID0gdmFsdWVzOwoKICAgIGZ1bmN0aW9uIGRvbmVSZXN1bHQoKSB7CiAgICAgIHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQkMSwgZG9uZTogdHJ1ZSB9OwogICAgfQoKICAgIENvbnRleHQucHJvdG90eXBlID0gewogICAgICBjb25zdHJ1Y3RvcjogQ29udGV4dCwKCiAgICAgIHJlc2V0OiBmdW5jdGlvbihza2lwVGVtcFJlc2V0KSB7CiAgICAgICAgdGhpcy5wcmV2ID0gMDsKICAgICAgICB0aGlzLm5leHQgPSAwOwogICAgICAgIC8vIFJlc2V0dGluZyBjb250ZXh0Ll9zZW50IGZvciBsZWdhY3kgc3VwcG9ydCBvZiBCYWJlbCdzCiAgICAgICAgLy8gZnVuY3Rpb24uc2VudCBpbXBsZW1lbnRhdGlvbi4KICAgICAgICB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkJDE7CiAgICAgICAgdGhpcy5kb25lID0gZmFsc2U7CiAgICAgICAgdGhpcy5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICAgIHRoaXMubWV0aG9kID0gIm5leHQiOwogICAgICAgIHRoaXMuYXJnID0gdW5kZWZpbmVkJDE7CgogICAgICAgIHRoaXMudHJ5RW50cmllcy5mb3JFYWNoKHJlc2V0VHJ5RW50cnkpOwoKICAgICAgICBpZiAoIXNraXBUZW1wUmVzZXQpIHsKICAgICAgICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcykgewogICAgICAgICAgICAvLyBOb3Qgc3VyZSBhYm91dCB0aGUgb3B0aW1hbCBvcmRlciBvZiB0aGVzZSBjb25kaXRpb25zOgogICAgICAgICAgICBpZiAobmFtZS5jaGFyQXQoMCkgPT09ICJ0IiAmJgogICAgICAgICAgICAgICAgaGFzT3duLmNhbGwodGhpcywgbmFtZSkgJiYKICAgICAgICAgICAgICAgICFpc05hTigrbmFtZS5zbGljZSgxKSkpIHsKICAgICAgICAgICAgICB0aGlzW25hbWVdID0gdW5kZWZpbmVkJDE7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCgogICAgICBzdG9wOiBmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLmRvbmUgPSB0cnVlOwoKICAgICAgICB2YXIgcm9vdEVudHJ5ID0gdGhpcy50cnlFbnRyaWVzWzBdOwogICAgICAgIHZhciByb290UmVjb3JkID0gcm9vdEVudHJ5LmNvbXBsZXRpb247CiAgICAgICAgaWYgKHJvb3RSZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgdGhyb3cgcm9vdFJlY29yZC5hcmc7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5ydmFsOwogICAgICB9LAoKICAgICAgZGlzcGF0Y2hFeGNlcHRpb246IGZ1bmN0aW9uKGV4Y2VwdGlvbikgewogICAgICAgIGlmICh0aGlzLmRvbmUpIHsKICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjsKICAgICAgICB9CgogICAgICAgIHZhciBjb250ZXh0ID0gdGhpczsKICAgICAgICBmdW5jdGlvbiBoYW5kbGUobG9jLCBjYXVnaHQpIHsKICAgICAgICAgIHJlY29yZC50eXBlID0gInRocm93IjsKICAgICAgICAgIHJlY29yZC5hcmcgPSBleGNlcHRpb247CiAgICAgICAgICBjb250ZXh0Lm5leHQgPSBsb2M7CgogICAgICAgICAgaWYgKGNhdWdodCkgewogICAgICAgICAgICAvLyBJZiB0aGUgZGlzcGF0Y2hlZCBleGNlcHRpb24gd2FzIGNhdWdodCBieSBhIGNhdGNoIGJsb2NrLAogICAgICAgICAgICAvLyB0aGVuIGxldCB0aGF0IGNhdGNoIGJsb2NrIGhhbmRsZSB0aGUgZXhjZXB0aW9uIG5vcm1hbGx5LgogICAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgICAgY29udGV4dC5hcmcgPSB1bmRlZmluZWQkMTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gISEgY2F1Z2h0OwogICAgICAgIH0KCiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgICAgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247CgogICAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA9PT0gInJvb3QiKSB7CiAgICAgICAgICAgIC8vIEV4Y2VwdGlvbiB0aHJvd24gb3V0c2lkZSBvZiBhbnkgdHJ5IGJsb2NrIHRoYXQgY291bGQgaGFuZGxlCiAgICAgICAgICAgIC8vIGl0LCBzbyBzZXQgdGhlIGNvbXBsZXRpb24gdmFsdWUgb2YgdGhlIGVudGlyZSBmdW5jdGlvbiB0bwogICAgICAgICAgICAvLyB0aHJvdyB0aGUgZXhjZXB0aW9uLgogICAgICAgICAgICByZXR1cm4gaGFuZGxlKCJlbmQiKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikgewogICAgICAgICAgICB2YXIgaGFzQ2F0Y2ggPSBoYXNPd24uY2FsbChlbnRyeSwgImNhdGNoTG9jIik7CiAgICAgICAgICAgIHZhciBoYXNGaW5hbGx5ID0gaGFzT3duLmNhbGwoZW50cnksICJmaW5hbGx5TG9jIik7CgogICAgICAgICAgICBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkgewogICAgICAgICAgICAgIGlmICh0aGlzLnByZXYgPCBlbnRyeS5jYXRjaExvYykgewogICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHsKICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsIHRydWUpOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzRmluYWxseSkgewogICAgICAgICAgICAgIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseSIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAoKICAgICAgYWJydXB0OiBmdW5jdGlvbih0eXBlLCBhcmcpIHsKICAgICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07CiAgICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldiAmJgogICAgICAgICAgICAgIGhhc093bi5jYWxsKGVudHJ5LCAiZmluYWxseUxvYyIpICYmCiAgICAgICAgICAgICAgdGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgewogICAgICAgICAgICB2YXIgZmluYWxseUVudHJ5ID0gZW50cnk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKGZpbmFsbHlFbnRyeSAmJgogICAgICAgICAgICAodHlwZSA9PT0gImJyZWFrIiB8fAogICAgICAgICAgICAgdHlwZSA9PT0gImNvbnRpbnVlIikgJiYKICAgICAgICAgICAgZmluYWxseUVudHJ5LnRyeUxvYyA8PSBhcmcgJiYKICAgICAgICAgICAgYXJnIDw9IGZpbmFsbHlFbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAvLyBJZ25vcmUgdGhlIGZpbmFsbHkgZW50cnkgaWYgY29udHJvbCBpcyBub3QganVtcGluZyB0byBhCiAgICAgICAgICAvLyBsb2NhdGlvbiBvdXRzaWRlIHRoZSB0cnkvY2F0Y2ggYmxvY2suCiAgICAgICAgICBmaW5hbGx5RW50cnkgPSBudWxsOwogICAgICAgIH0KCiAgICAgICAgdmFyIHJlY29yZCA9IGZpbmFsbHlFbnRyeSA/IGZpbmFsbHlFbnRyeS5jb21wbGV0aW9uIDoge307CiAgICAgICAgcmVjb3JkLnR5cGUgPSB0eXBlOwogICAgICAgIHJlY29yZC5hcmcgPSBhcmc7CgogICAgICAgIGlmIChmaW5hbGx5RW50cnkpIHsKICAgICAgICAgIHRoaXMubWV0aG9kID0gIm5leHQiOwogICAgICAgICAgdGhpcy5uZXh0ID0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2M7CiAgICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLmNvbXBsZXRlKHJlY29yZCk7CiAgICAgIH0sCgogICAgICBjb21wbGV0ZTogZnVuY3Rpb24ocmVjb3JkLCBhZnRlckxvYykgewogICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgdGhyb3cgcmVjb3JkLmFyZzsKICAgICAgICB9CgogICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gImJyZWFrIiB8fAogICAgICAgICAgICByZWNvcmQudHlwZSA9PT0gImNvbnRpbnVlIikgewogICAgICAgICAgdGhpcy5uZXh0ID0gcmVjb3JkLmFyZzsKICAgICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSAicmV0dXJuIikgewogICAgICAgICAgdGhpcy5ydmFsID0gdGhpcy5hcmcgPSByZWNvcmQuYXJnOwogICAgICAgICAgdGhpcy5tZXRob2QgPSAicmV0dXJuIjsKICAgICAgICAgIHRoaXMubmV4dCA9ICJlbmQiOwogICAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09ICJub3JtYWwiICYmIGFmdGVyTG9jKSB7CiAgICAgICAgICB0aGlzLm5leHQgPSBhZnRlckxvYzsKICAgICAgICB9CgogICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgICB9LAoKICAgICAgZmluaXNoOiBmdW5jdGlvbihmaW5hbGx5TG9jKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgICAgaWYgKGVudHJ5LmZpbmFsbHlMb2MgPT09IGZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgdGhpcy5jb21wbGV0ZShlbnRyeS5jb21wbGV0aW9uLCBlbnRyeS5hZnRlckxvYyk7CiAgICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCgogICAgICAiY2F0Y2giOiBmdW5jdGlvbih0cnlMb2MpIHsKICAgICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07CiAgICAgICAgICBpZiAoZW50cnkudHJ5TG9jID09PSB0cnlMb2MpIHsKICAgICAgICAgICAgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247CiAgICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICAgIHZhciB0aHJvd24gPSByZWNvcmQuYXJnOwogICAgICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aHJvd247CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBUaGUgY29udGV4dC5jYXRjaCBtZXRob2QgbXVzdCBvbmx5IGJlIGNhbGxlZCB3aXRoIGEgbG9jYXRpb24KICAgICAgICAvLyBhcmd1bWVudCB0aGF0IGNvcnJlc3BvbmRzIHRvIGEga25vd24gY2F0Y2ggYmxvY2suCiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJpbGxlZ2FsIGNhdGNoIGF0dGVtcHQiKTsKICAgICAgfSwKCiAgICAgIGRlbGVnYXRlWWllbGQ6IGZ1bmN0aW9uKGl0ZXJhYmxlLCByZXN1bHROYW1lLCBuZXh0TG9jKSB7CiAgICAgICAgdGhpcy5kZWxlZ2F0ZSA9IHsKICAgICAgICAgIGl0ZXJhdG9yOiB2YWx1ZXMoaXRlcmFibGUpLAogICAgICAgICAgcmVzdWx0TmFtZTogcmVzdWx0TmFtZSwKICAgICAgICAgIG5leHRMb2M6IG5leHRMb2MKICAgICAgICB9OwoKICAgICAgICBpZiAodGhpcy5tZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgLy8gRGVsaWJlcmF0ZWx5IGZvcmdldCB0aGUgbGFzdCBzZW50IHZhbHVlIHNvIHRoYXQgd2UgZG9uJ3QKICAgICAgICAgIC8vIGFjY2lkZW50YWxseSBwYXNzIGl0IG9uIHRvIHRoZSBkZWxlZ2F0ZS4KICAgICAgICAgIHRoaXMuYXJnID0gdW5kZWZpbmVkJDE7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgICAgfQogICAgfTsKCiAgICAvLyBSZWdhcmRsZXNzIG9mIHdoZXRoZXIgdGhpcyBzY3JpcHQgaXMgZXhlY3V0aW5nIGFzIGEgQ29tbW9uSlMgbW9kdWxlCiAgICAvLyBvciBub3QsIHJldHVybiB0aGUgcnVudGltZSBvYmplY3Qgc28gdGhhdCB3ZSBjYW4gZGVjbGFyZSB0aGUgdmFyaWFibGUKICAgIC8vIHJlZ2VuZXJhdG9yUnVudGltZSBpbiB0aGUgb3V0ZXIgc2NvcGUsIHdoaWNoIGFsbG93cyB0aGlzIG1vZHVsZSB0byBiZQogICAgLy8gaW5qZWN0ZWQgZWFzaWx5IGJ5IGBiaW4vcmVnZW5lcmF0b3IgLS1pbmNsdWRlLXJ1bnRpbWUgc2NyaXB0LmpzYC4KICAgIHJldHVybiBleHBvcnRzOwoKICB9KAogICAgLy8gSWYgdGhpcyBzY3JpcHQgaXMgZXhlY3V0aW5nIGFzIGEgQ29tbW9uSlMgbW9kdWxlLCB1c2UgbW9kdWxlLmV4cG9ydHMKICAgIC8vIGFzIHRoZSByZWdlbmVyYXRvclJ1bnRpbWUgbmFtZXNwYWNlLiBPdGhlcndpc2UgY3JlYXRlIGEgbmV3IGVtcHR5CiAgICAvLyBvYmplY3QuIEVpdGhlciB3YXksIHRoZSByZXN1bHRpbmcgb2JqZWN0IHdpbGwgYmUgdXNlZCB0byBpbml0aWFsaXplCiAgICAvLyB0aGUgcmVnZW5lcmF0b3JSdW50aW1lIHZhcmlhYmxlIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlLgogICAgbW9kdWxlLmV4cG9ydHMgCiAgKSk7CgogIHRyeSB7CiAgICByZWdlbmVyYXRvclJ1bnRpbWUgPSBydW50aW1lOwogIH0gY2F0Y2ggKGFjY2lkZW50YWxTdHJpY3RNb2RlKSB7CiAgICAvLyBUaGlzIG1vZHVsZSBzaG91bGQgbm90IGJlIHJ1bm5pbmcgaW4gc3RyaWN0IG1vZGUsIHNvIHRoZSBhYm92ZQogICAgLy8gYXNzaWdubWVudCBzaG91bGQgYWx3YXlzIHdvcmsgdW5sZXNzIHNvbWV0aGluZyBpcyBtaXNjb25maWd1cmVkLiBKdXN0CiAgICAvLyBpbiBjYXNlIHJ1bnRpbWUuanMgYWNjaWRlbnRhbGx5IHJ1bnMgaW4gc3RyaWN0IG1vZGUsIHdlIGNhbiBlc2NhcGUKICAgIC8vIHN0cmljdCBtb2RlIHVzaW5nIGEgZ2xvYmFsIEZ1bmN0aW9uIGNhbGwuIFRoaXMgY291bGQgY29uY2VpdmFibHkgZmFpbAogICAgLy8gaWYgYSBDb250ZW50IFNlY3VyaXR5IFBvbGljeSBmb3JiaWRzIHVzaW5nIEZ1bmN0aW9uLCBidXQgaW4gdGhhdCBjYXNlCiAgICAvLyB0aGUgcHJvcGVyIHNvbHV0aW9uIGlzIHRvIGZpeCB0aGUgYWNjaWRlbnRhbCBzdHJpY3QgbW9kZSBwcm9ibGVtLiBJZgogICAgLy8geW91J3ZlIG1pc2NvbmZpZ3VyZWQgeW91ciBidW5kbGVyIHRvIGZvcmNlIHN0cmljdCBtb2RlIGFuZCBhcHBsaWVkIGEKICAgIC8vIENTUCB0byBmb3JiaWQgRnVuY3Rpb24sIGFuZCB5b3UncmUgbm90IHdpbGxpbmcgdG8gZml4IGVpdGhlciBvZiB0aG9zZQogICAgLy8gcHJvYmxlbXMsIHBsZWFzZSBkZXRhaWwgeW91ciB1bmlxdWUgcHJlZGljYW1lbnQgaW4gYSBHaXRIdWIgaXNzdWUuCiAgICBGdW5jdGlvbigiciIsICJyZWdlbmVyYXRvclJ1bnRpbWUgPSByIikocnVudGltZSk7CiAgfQogIH0pOwoKICBmdW5jdGlvbiBkZWNvZGVUZXJyYWluKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHZhciBpbWFnZURhdGEgPSBwYXJhbWV0ZXJzLmltYWdlRGF0YSwKICAgICAgICBfcGFyYW1ldGVycyR0aWxlU2l6ZSA9IHBhcmFtZXRlcnMudGlsZVNpemUsCiAgICAgICAgdGlsZVNpemUgPSBfcGFyYW1ldGVycyR0aWxlU2l6ZSA9PT0gdm9pZCAwID8gMjU2IDogX3BhcmFtZXRlcnMkdGlsZVNpemUsCiAgICAgICAgZXJyb3JMZXZlbCA9IHBhcmFtZXRlcnMuZXJyb3JMZXZlbDsKICAgIHZhciBwaXhlbHMgPSBuZGFycmF5KG5ldyBVaW50OEFycmF5KGltYWdlRGF0YSksIFt0aWxlU2l6ZSwgdGlsZVNpemUsIDRdLCBbNCwgNCAqIHRpbGVTaXplLCAxXSwgMCk7CiAgICB2YXIgbWFydGluaSA9IG5ldyBNYXJ0aW5pKHRpbGVTaXplICsgMSk7CiAgICB2YXIgdGVycmFpbiA9IG1hcGJveFRlcnJhaW5Ub0dyaWQocGl4ZWxzKTsKICAgIHZhciB0aWxlID0gbWFydGluaS5jcmVhdGVUaWxlKHRlcnJhaW4pOyAvLyBnZXQgYSBtZXNoICh2ZXJ0aWNlcyBhbmQgdHJpYW5nbGVzIGluZGljZXMpIGZvciBhIDEwbSBlcnJvcgoKICAgIGNvbnNvbGUubG9nKCJFcnJvciBsZXZlbDogIi5jb25jYXQoZXJyb3JMZXZlbCkpOwogICAgdmFyIG1lc2ggPSB0aWxlLmdldE1lc2goZXJyb3JMZXZlbCwgcGFyYW1ldGVycy5tYXhMZW5ndGgpOwogICAgcmV0dXJuIGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplKTsKICB9CgogIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKG1zZykgewogICAgdmFyIF9tc2ckZGF0YSA9IG1zZy5kYXRhLAogICAgICAgIGlkID0gX21zZyRkYXRhLmlkLAogICAgICAgIHBheWxvYWQgPSBfbXNnJGRhdGEucGF5bG9hZDsKICAgIGlmIChpZCA9PSBudWxsKSByZXR1cm47CiAgICBjb25zb2xlLmxvZygiV29ya2VyIHJlY2lldmVkIG1lc3NhZ2UiLCBtc2cuZGF0YSk7CiAgICB2YXIgb2JqZWN0cyA9IFtdOwoKICAgIHRyeSB7CiAgICAgIHZhciByZXMgPSBkZWNvZGVUZXJyYWluKHBheWxvYWQpOwogICAgICBvYmplY3RzLnB1c2gocmVzLmluZGljZXMuYnVmZmVyKTsKICAgICAgb2JqZWN0cy5wdXNoKHJlcy5xdWFudGl6ZWRWZXJ0aWNlcy5idWZmZXIpOwogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogaWQsCiAgICAgICAgcGF5bG9hZDogcmVzCiAgICAgIH0sIG9iamVjdHMpOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIHNlbGYucG9zdE1lc3NhZ2UoewogICAgICAgIGlkOiBpZCwKICAgICAgICBlcnI6IGVyci50b1N0cmluZygpCiAgICAgIH0pOwogICAgfSBmaW5hbGx5IHsKICAgICAgb2JqZWN0cyA9IG51bGw7CiAgICB9CiAgfTsKCiAgZXhwb3J0cy5kZWNvZGVUZXJyYWluID0gZGVjb2RlVGVycmFpbjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTsKCiAgcmV0dXJuIGV4cG9ydHM7Cgp9KHt9KSk7Cgo=', 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);
|
|
328
481
|
/* eslint-enable */
|
|
329
482
|
|
|
330
483
|
var resolves = {};
|
|
@@ -409,20 +562,17 @@ var WorkerFarm = /*#__PURE__*/function () {
|
|
|
409
562
|
key: "scheduleTask",
|
|
410
563
|
value: function () {
|
|
411
564
|
var _scheduleTask = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(params, transferableObjects) {
|
|
412
|
-
var res;
|
|
413
565
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
414
566
|
while (1) {
|
|
415
567
|
switch (_context.prev = _context.next) {
|
|
416
568
|
case 0:
|
|
417
|
-
|
|
418
|
-
_context.next = 3;
|
|
569
|
+
_context.next = 2;
|
|
419
570
|
return sendMessage(this.worker, params, transferableObjects);
|
|
420
571
|
|
|
421
|
-
case
|
|
422
|
-
|
|
423
|
-
return _context.abrupt("return", res);
|
|
572
|
+
case 2:
|
|
573
|
+
return _context.abrupt("return", _context.sent);
|
|
424
574
|
|
|
425
|
-
case
|
|
575
|
+
case 3:
|
|
426
576
|
case "end":
|
|
427
577
|
return _context.stop();
|
|
428
578
|
}
|
|
@@ -444,12 +594,16 @@ var WorkerFarm = /*#__PURE__*/function () {
|
|
|
444
594
|
// We should save these
|
|
445
595
|
//const canvas = new OffscreenCanvas(256, 256);
|
|
446
596
|
//const ctx = canvas.getContext("2d");
|
|
447
|
-
function mapboxTerrainToGrid(png) {
|
|
597
|
+
function mapboxTerrainToGrid(png, interval, offset) {
|
|
598
|
+
var _interval, _offset;
|
|
599
|
+
|
|
448
600
|
// maybe we should do this on the GPU using REGL?
|
|
449
601
|
// but that would require GPU -> CPU -> GPU
|
|
450
602
|
var gridSize = png.shape[0] + 1;
|
|
451
603
|
var terrain = new Float32Array(gridSize * gridSize);
|
|
452
|
-
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
|
|
453
607
|
|
|
454
608
|
for (var y = 0; y < tileSize; y++) {
|
|
455
609
|
for (var x = 0; x < tileSize; x++) {
|
|
@@ -457,7 +611,7 @@ function mapboxTerrainToGrid(png) {
|
|
|
457
611
|
var r = png.get(x, yc, 0);
|
|
458
612
|
var g = png.get(x, yc, 1);
|
|
459
613
|
var b = png.get(x, yc, 2);
|
|
460
|
-
terrain[y * gridSize + x] = r * 256 * 256
|
|
614
|
+
terrain[y * gridSize + x] = r * 256 * 256 * interval + g * 256.0 * interval + b * interval + offset;
|
|
461
615
|
}
|
|
462
616
|
} // backfill right and bottom borders
|
|
463
617
|
|
|
@@ -473,8 +627,75 @@ function mapboxTerrainToGrid(png) {
|
|
|
473
627
|
return terrain;
|
|
474
628
|
}
|
|
475
629
|
|
|
476
|
-
function
|
|
477
|
-
|
|
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
|
+
|
|
698
|
+
function createQuantizedMeshData(tile, mesh, tileSize) {
|
|
478
699
|
var xvals = [];
|
|
479
700
|
var yvals = [];
|
|
480
701
|
var heightMeters = [];
|
|
@@ -482,28 +703,32 @@ function createQuantizedMeshData(tile, mesh) {
|
|
|
482
703
|
var southIndices = [];
|
|
483
704
|
var eastIndices = [];
|
|
484
705
|
var westIndices = [];
|
|
706
|
+
var minimumHeight = Infinity;
|
|
707
|
+
var maximumHeight = -Infinity;
|
|
708
|
+
var scalar = 32768.0 / tileSize;
|
|
485
709
|
|
|
486
710
|
for (var ix = 0; ix < mesh.vertices.length / 2; ix++) {
|
|
487
711
|
var vertexIx = ix;
|
|
488
712
|
var px = mesh.vertices[ix * 2];
|
|
489
713
|
var py = mesh.vertices[ix * 2 + 1];
|
|
490
|
-
|
|
714
|
+
var height = tile.terrain[py * (tileSize + 1) + px];
|
|
715
|
+
if (height > maximumHeight) maximumHeight = height;
|
|
716
|
+
if (height < minimumHeight) minimumHeight = height;
|
|
717
|
+
heightMeters.push(height);
|
|
491
718
|
if (py == 0) northIndices.push(vertexIx);
|
|
492
719
|
if (py == tileSize) southIndices.push(vertexIx);
|
|
493
720
|
if (px == 0) westIndices.push(vertexIx);
|
|
494
721
|
if (px == tileSize) eastIndices.push(vertexIx);
|
|
495
|
-
var scalar = 32768.0 / tileSize;
|
|
496
722
|
var xv = px * scalar;
|
|
497
723
|
var yv = (tileSize - py) * scalar;
|
|
498
724
|
xvals.push(xv);
|
|
499
725
|
yvals.push(yv);
|
|
500
726
|
}
|
|
501
727
|
|
|
502
|
-
var
|
|
503
|
-
var minHeight = Math.min.apply(this, heightMeters);
|
|
728
|
+
var heightRange = maximumHeight - minimumHeight;
|
|
504
729
|
var heights = heightMeters.map(function (d) {
|
|
505
|
-
if (
|
|
506
|
-
return (d -
|
|
730
|
+
if (heightRange < 1) return 0;
|
|
731
|
+
return (d - minimumHeight) * (32767.0 / heightRange);
|
|
507
732
|
});
|
|
508
733
|
var triangles = new Uint16Array(mesh.triangles);
|
|
509
734
|
var quantizedVertices = new Uint16Array( //verts
|
|
@@ -511,8 +736,8 @@ function createQuantizedMeshData(tile, mesh) {
|
|
|
511
736
|
// NE NW SE
|
|
512
737
|
|
|
513
738
|
return {
|
|
514
|
-
minimumHeight:
|
|
515
|
-
maximumHeight:
|
|
739
|
+
minimumHeight: minimumHeight,
|
|
740
|
+
maximumHeight: maximumHeight,
|
|
516
741
|
quantizedVertices: quantizedVertices,
|
|
517
742
|
indices: triangles,
|
|
518
743
|
westIndices: westIndices,
|
|
@@ -834,66 +1059,252 @@ function arrayDType(data) {
|
|
|
834
1059
|
return "biguint64"
|
|
835
1060
|
}
|
|
836
1061
|
}
|
|
837
|
-
if(Array.isArray(data)) {
|
|
838
|
-
return "array"
|
|
839
|
-
}
|
|
840
|
-
return "generic"
|
|
841
|
-
}
|
|
1062
|
+
if(Array.isArray(data)) {
|
|
1063
|
+
return "array"
|
|
1064
|
+
}
|
|
1065
|
+
return "generic"
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
var CACHED_CONSTRUCTORS = {
|
|
1069
|
+
"float32":[],
|
|
1070
|
+
"float64":[],
|
|
1071
|
+
"int8":[],
|
|
1072
|
+
"int16":[],
|
|
1073
|
+
"int32":[],
|
|
1074
|
+
"uint8":[],
|
|
1075
|
+
"uint16":[],
|
|
1076
|
+
"uint32":[],
|
|
1077
|
+
"array":[],
|
|
1078
|
+
"uint8_clamped":[],
|
|
1079
|
+
"bigint64": [],
|
|
1080
|
+
"biguint64": [],
|
|
1081
|
+
"buffer":[],
|
|
1082
|
+
"generic":[]
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
;
|
|
1086
|
+
function wrappedNDArrayCtor(data, shape, stride, offset) {
|
|
1087
|
+
if(data === undefined) {
|
|
1088
|
+
var ctor = CACHED_CONSTRUCTORS.array[0];
|
|
1089
|
+
return ctor([])
|
|
1090
|
+
} else if(typeof data === "number") {
|
|
1091
|
+
data = [data];
|
|
1092
|
+
}
|
|
1093
|
+
if(shape === undefined) {
|
|
1094
|
+
shape = [ data.length ];
|
|
1095
|
+
}
|
|
1096
|
+
var d = shape.length;
|
|
1097
|
+
if(stride === undefined) {
|
|
1098
|
+
stride = new Array(d);
|
|
1099
|
+
for(var i=d-1, sz=1; i>=0; --i) {
|
|
1100
|
+
stride[i] = sz;
|
|
1101
|
+
sz *= shape[i];
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if(offset === undefined) {
|
|
1105
|
+
offset = 0;
|
|
1106
|
+
for(var i=0; i<d; ++i) {
|
|
1107
|
+
if(stride[i] < 0) {
|
|
1108
|
+
offset -= (shape[i]-1)*stride[i];
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
var dtype = arrayDType(data);
|
|
1113
|
+
var ctor_list = CACHED_CONSTRUCTORS[dtype];
|
|
1114
|
+
while(ctor_list.length <= d+1) {
|
|
1115
|
+
ctor_list.push(compileConstructor(dtype, ctor_list.length-1));
|
|
1116
|
+
}
|
|
1117
|
+
var ctor = ctor_list[d+1];
|
|
1118
|
+
return ctor(data, shape, stride, offset)
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
var ndarray = wrappedNDArrayCtor;
|
|
1122
|
+
|
|
1123
|
+
class Martini {
|
|
1124
|
+
constructor(gridSize = 257) {
|
|
1125
|
+
this.gridSize = gridSize;
|
|
1126
|
+
const tileSize = gridSize - 1;
|
|
1127
|
+
if (tileSize & tileSize - 1) throw new Error(`Expected grid size to be 2^n+1, got ${gridSize}.`);
|
|
1128
|
+
this.numTriangles = tileSize * tileSize * 2 - 2;
|
|
1129
|
+
this.numParentTriangles = this.numTriangles - tileSize * tileSize;
|
|
1130
|
+
this.indices = new Uint32Array(this.gridSize * this.gridSize); // coordinates for all possible triangles in an RTIN tile
|
|
1131
|
+
|
|
1132
|
+
this.coords = new Uint16Array(this.numTriangles * 4); // get triangle coordinates from its index in an implicit binary tree
|
|
1133
|
+
|
|
1134
|
+
for (let i = 0; i < this.numTriangles; i++) {
|
|
1135
|
+
let id = i + 2;
|
|
1136
|
+
let ax = 0,
|
|
1137
|
+
ay = 0,
|
|
1138
|
+
bx = 0,
|
|
1139
|
+
by = 0,
|
|
1140
|
+
cx = 0,
|
|
1141
|
+
cy = 0;
|
|
1142
|
+
|
|
1143
|
+
if (id & 1) {
|
|
1144
|
+
bx = by = cx = tileSize; // bottom-left triangle
|
|
1145
|
+
} else {
|
|
1146
|
+
ax = ay = cy = tileSize; // top-right triangle
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
while ((id >>= 1) > 1) {
|
|
1150
|
+
const mx = ax + bx >> 1;
|
|
1151
|
+
const my = ay + by >> 1;
|
|
1152
|
+
|
|
1153
|
+
if (id & 1) {
|
|
1154
|
+
// left half
|
|
1155
|
+
bx = ax;
|
|
1156
|
+
by = ay;
|
|
1157
|
+
ax = cx;
|
|
1158
|
+
ay = cy;
|
|
1159
|
+
} else {
|
|
1160
|
+
// right half
|
|
1161
|
+
ax = bx;
|
|
1162
|
+
ay = by;
|
|
1163
|
+
bx = cx;
|
|
1164
|
+
by = cy;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
cx = mx;
|
|
1168
|
+
cy = my;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const k = i * 4;
|
|
1172
|
+
this.coords[k + 0] = ax;
|
|
1173
|
+
this.coords[k + 1] = ay;
|
|
1174
|
+
this.coords[k + 2] = bx;
|
|
1175
|
+
this.coords[k + 3] = by;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
createTile(terrain) {
|
|
1180
|
+
return new Tile(terrain, this);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
class Tile {
|
|
1186
|
+
constructor(terrain, martini) {
|
|
1187
|
+
const size = martini.gridSize;
|
|
1188
|
+
if (terrain.length !== size * size) throw new Error(`Expected terrain data of length ${size * size} (${size} x ${size}), got ${terrain.length}.`);
|
|
1189
|
+
this.terrain = terrain;
|
|
1190
|
+
this.martini = martini;
|
|
1191
|
+
this.errors = new Float32Array(terrain.length);
|
|
1192
|
+
this.update();
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
update() {
|
|
1196
|
+
const {
|
|
1197
|
+
numTriangles,
|
|
1198
|
+
numParentTriangles,
|
|
1199
|
+
coords,
|
|
1200
|
+
gridSize: size
|
|
1201
|
+
} = this.martini;
|
|
1202
|
+
const {
|
|
1203
|
+
terrain,
|
|
1204
|
+
errors
|
|
1205
|
+
} = this; // iterate over all possible triangles, starting from the smallest level
|
|
1206
|
+
|
|
1207
|
+
for (let i = numTriangles - 1; i >= 0; i--) {
|
|
1208
|
+
const k = i * 4;
|
|
1209
|
+
const ax = coords[k + 0];
|
|
1210
|
+
const ay = coords[k + 1];
|
|
1211
|
+
const bx = coords[k + 2];
|
|
1212
|
+
const by = coords[k + 3];
|
|
1213
|
+
const mx = ax + bx >> 1;
|
|
1214
|
+
const my = ay + by >> 1;
|
|
1215
|
+
const cx = mx + my - ay;
|
|
1216
|
+
const cy = my + ax - mx; // calculate error in the middle of the long edge of the triangle
|
|
1217
|
+
|
|
1218
|
+
const interpolatedHeight = (terrain[ay * size + ax] + terrain[by * size + bx]) / 2;
|
|
1219
|
+
const middleIndex = my * size + mx;
|
|
1220
|
+
const middleError = Math.abs(interpolatedHeight - terrain[middleIndex]);
|
|
1221
|
+
errors[middleIndex] = Math.max(errors[middleIndex], middleError);
|
|
1222
|
+
|
|
1223
|
+
if (i < numParentTriangles) {
|
|
1224
|
+
// bigger triangles; accumulate error with children
|
|
1225
|
+
const leftChildIndex = (ay + cy >> 1) * size + (ax + cx >> 1);
|
|
1226
|
+
const rightChildIndex = (by + cy >> 1) * size + (bx + cx >> 1);
|
|
1227
|
+
errors[middleIndex] = Math.max(errors[middleIndex], errors[leftChildIndex], errors[rightChildIndex]);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
842
1231
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
"biguint64": [],
|
|
856
|
-
"buffer":[],
|
|
857
|
-
"generic":[]
|
|
858
|
-
}
|
|
1232
|
+
getMesh(maxError = 0, maxLength = null) {
|
|
1233
|
+
const {
|
|
1234
|
+
gridSize: size,
|
|
1235
|
+
indices
|
|
1236
|
+
} = this.martini;
|
|
1237
|
+
const {
|
|
1238
|
+
errors
|
|
1239
|
+
} = this;
|
|
1240
|
+
let numVertices = 0;
|
|
1241
|
+
let numTriangles = 0;
|
|
1242
|
+
const max = size - 1; // The maxLength parameter will cause triangles to be generated until the legs are below this length
|
|
1243
|
+
// It is meant to support cases where a certain mesh density is required to do spherical math on digital globes
|
|
859
1244
|
|
|
860
|
-
;
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1245
|
+
const maxScale = maxLength || size; // use an index grid to keep track of vertices that were already used to avoid duplication
|
|
1246
|
+
|
|
1247
|
+
indices.fill(0); // retrieve mesh in two stages that both traverse the error map:
|
|
1248
|
+
// - countElements: find used vertices (and assign each an index), and count triangles (for minimum allocation)
|
|
1249
|
+
// - processTriangle: fill the allocated vertices & triangles typed arrays
|
|
1250
|
+
|
|
1251
|
+
function countElements(ax, ay, bx, by, cx, cy) {
|
|
1252
|
+
const mx = ax + bx >> 1;
|
|
1253
|
+
const my = ay + by >> 1;
|
|
1254
|
+
const legLength = Math.abs(ax - cx) + Math.abs(ay - cy);
|
|
1255
|
+
|
|
1256
|
+
if (legLength > 1 && errors[my * size + mx] > maxError || legLength > maxScale) {
|
|
1257
|
+
countElements(cx, cy, ax, ay, mx, my);
|
|
1258
|
+
countElements(bx, by, cx, cy, mx, my);
|
|
1259
|
+
} else {
|
|
1260
|
+
indices[ay * size + ax] = indices[ay * size + ax] || ++numVertices;
|
|
1261
|
+
indices[by * size + bx] = indices[by * size + bx] || ++numVertices;
|
|
1262
|
+
indices[cy * size + cx] = indices[cy * size + cx] || ++numVertices;
|
|
1263
|
+
numTriangles++;
|
|
1264
|
+
}
|
|
877
1265
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1266
|
+
|
|
1267
|
+
countElements(0, 0, max, max, max, 0);
|
|
1268
|
+
countElements(max, max, 0, 0, 0, max);
|
|
1269
|
+
const vertices = new Uint16Array(numVertices * 2);
|
|
1270
|
+
const triangles = new Uint32Array(numTriangles * 3);
|
|
1271
|
+
let triIndex = 0;
|
|
1272
|
+
|
|
1273
|
+
function processTriangle(ax, ay, bx, by, cx, cy) {
|
|
1274
|
+
const mx = ax + bx >> 1;
|
|
1275
|
+
const my = ay + by >> 1;
|
|
1276
|
+
const legLength = Math.abs(ax - cx) + Math.abs(ay - cy);
|
|
1277
|
+
|
|
1278
|
+
if (legLength > 1 && errors[my * size + mx] > maxError || legLength > maxScale) {
|
|
1279
|
+
// triangle doesn't approximate the surface well enough; drill down further
|
|
1280
|
+
processTriangle(cx, cy, ax, ay, mx, my);
|
|
1281
|
+
processTriangle(bx, by, cx, cy, mx, my);
|
|
1282
|
+
} else {
|
|
1283
|
+
// add a triangle
|
|
1284
|
+
const a = indices[ay * size + ax] - 1;
|
|
1285
|
+
const b = indices[by * size + bx] - 1;
|
|
1286
|
+
const c = indices[cy * size + cx] - 1;
|
|
1287
|
+
vertices[2 * a] = ax;
|
|
1288
|
+
vertices[2 * a + 1] = ay;
|
|
1289
|
+
vertices[2 * b] = bx;
|
|
1290
|
+
vertices[2 * b + 1] = by;
|
|
1291
|
+
vertices[2 * c] = cx;
|
|
1292
|
+
vertices[2 * c + 1] = cy;
|
|
1293
|
+
triangles[triIndex++] = a;
|
|
1294
|
+
triangles[triIndex++] = b;
|
|
1295
|
+
triangles[triIndex++] = c;
|
|
884
1296
|
}
|
|
885
1297
|
}
|
|
1298
|
+
|
|
1299
|
+
processTriangle(0, 0, max, max, max, 0);
|
|
1300
|
+
processTriangle(max, max, 0, 0, 0, max);
|
|
1301
|
+
return {
|
|
1302
|
+
vertices,
|
|
1303
|
+
triangles
|
|
1304
|
+
};
|
|
886
1305
|
}
|
|
887
|
-
var dtype = arrayDType(data);
|
|
888
|
-
var ctor_list = CACHED_CONSTRUCTORS[dtype];
|
|
889
|
-
while(ctor_list.length <= d+1) {
|
|
890
|
-
ctor_list.push(compileConstructor(dtype, ctor_list.length-1));
|
|
891
|
-
}
|
|
892
|
-
var ctor = ctor_list[d+1];
|
|
893
|
-
return ctor(data, shape, stride, offset)
|
|
894
|
-
}
|
|
895
1306
|
|
|
896
|
-
|
|
1307
|
+
}
|
|
897
1308
|
|
|
898
1309
|
function createCommonjsModule(fn) {
|
|
899
1310
|
var module = { exports: {} };
|
|
@@ -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,28 +2051,39 @@ 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
|
|
|
2070
|
+
var martini = null;
|
|
2071
|
+
|
|
1653
2072
|
function decodeTerrain(parameters, transferableObjects) {
|
|
2073
|
+
var _martini;
|
|
2074
|
+
|
|
1654
2075
|
var imageData = parameters.imageData,
|
|
1655
2076
|
_parameters$tileSize = parameters.tileSize,
|
|
1656
2077
|
tileSize = _parameters$tileSize === void 0 ? 256 : _parameters$tileSize,
|
|
1657
|
-
errorLevel = parameters.errorLevel
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
var
|
|
2078
|
+
errorLevel = parameters.errorLevel,
|
|
2079
|
+
interval = parameters.interval,
|
|
2080
|
+
offset = parameters.offset;
|
|
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
|
|
2082
|
+
|
|
2083
|
+
(_martini = martini) !== null && _martini !== void 0 ? _martini : martini = new Martini(tileSize + 1);
|
|
2084
|
+
var terrain = mapboxTerrainToGrid(pixels, interval, offset);
|
|
1661
2085
|
var tile = martini.createTile(terrain); // get a mesh (vertices and triangles indices) for a 10m error
|
|
1662
2086
|
|
|
1663
|
-
console.log("Error level: ".concat(errorLevel));
|
|
1664
2087
|
var mesh = tile.getMesh(errorLevel, parameters.maxLength);
|
|
1665
2088
|
return createQuantizedMeshData(tile, mesh, tileSize);
|
|
1666
2089
|
}
|
|
@@ -1670,11 +2093,11 @@ self.onmessage = function (msg) {
|
|
|
1670
2093
|
id = _msg$data.id,
|
|
1671
2094
|
payload = _msg$data.payload;
|
|
1672
2095
|
if (id == null) return;
|
|
1673
|
-
console.log("Worker recieved message", msg.data);
|
|
1674
2096
|
var objects = [];
|
|
2097
|
+
var res = null;
|
|
1675
2098
|
|
|
1676
2099
|
try {
|
|
1677
|
-
|
|
2100
|
+
res = decodeTerrain(payload);
|
|
1678
2101
|
objects.push(res.indices.buffer);
|
|
1679
2102
|
objects.push(res.quantizedVertices.buffer);
|
|
1680
2103
|
self.postMessage({
|
|
@@ -1687,45 +2110,52 @@ self.onmessage = function (msg) {
|
|
|
1687
2110
|
err: err.toString()
|
|
1688
2111
|
});
|
|
1689
2112
|
} finally {
|
|
2113
|
+
res = null;
|
|
1690
2114
|
objects = null;
|
|
1691
2115
|
}
|
|
1692
2116
|
};
|
|
1693
2117
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
var ImageFormat;
|
|
2118
|
+
var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
|
|
2119
|
+
_inherits(StretchedTilingScheme, _WebMercatorTilingSch);
|
|
1697
2120
|
|
|
1698
|
-
|
|
1699
|
-
ImageFormat["WEBP"] = "webp";
|
|
1700
|
-
ImageFormat["PNG"] = "png";
|
|
1701
|
-
ImageFormat["PNGRAW"] = "pngraw";
|
|
1702
|
-
})(ImageFormat || (ImageFormat = {}));
|
|
2121
|
+
var _super = _createSuper(StretchedTilingScheme);
|
|
1703
2122
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
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);
|
|
1717
2149
|
|
|
1718
2150
|
var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
1719
2151
|
// @ts-ignore
|
|
1720
2152
|
function MartiniTerrainProvider() {
|
|
1721
|
-
var _opts$
|
|
2153
|
+
var _opts$interval, _opts$offset, _opts$maxWorkers, _opts$minZoomLevel, _opts$fillPoles, _opts$detailScalar, _opts$minimumErrorLev, _opts$ellipsoid;
|
|
1722
2154
|
|
|
1723
2155
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1724
2156
|
|
|
1725
2157
|
_classCallCheck(this, MartiniTerrainProvider);
|
|
1726
2158
|
|
|
1727
|
-
_defineProperty(this, "martini", void 0);
|
|
1728
|
-
|
|
1729
2159
|
_defineProperty(this, "hasWaterMask", false);
|
|
1730
2160
|
|
|
1731
2161
|
_defineProperty(this, "hasVertexNormals", false);
|
|
@@ -1744,98 +2174,75 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1744
2174
|
|
|
1745
2175
|
_defineProperty(this, "ellipsoid", void 0);
|
|
1746
2176
|
|
|
1747
|
-
_defineProperty(this, "
|
|
2177
|
+
_defineProperty(this, "workerFarm", null);
|
|
1748
2178
|
|
|
1749
|
-
_defineProperty(this, "
|
|
2179
|
+
_defineProperty(this, "inProgressWorkers", 0);
|
|
1750
2180
|
|
|
1751
|
-
_defineProperty(this, "
|
|
2181
|
+
_defineProperty(this, "levelOfDetailScalar", null);
|
|
1752
2182
|
|
|
1753
|
-
_defineProperty(this, "
|
|
2183
|
+
_defineProperty(this, "maxWorkers", 5);
|
|
1754
2184
|
|
|
1755
|
-
_defineProperty(this, "
|
|
2185
|
+
_defineProperty(this, "minError", 0.1);
|
|
1756
2186
|
|
|
1757
|
-
_defineProperty(this, "
|
|
2187
|
+
_defineProperty(this, "minZoomLevel", void 0);
|
|
1758
2188
|
|
|
1759
|
-
_defineProperty(this, "
|
|
2189
|
+
_defineProperty(this, "fillPoles", true);
|
|
1760
2190
|
|
|
1761
|
-
_defineProperty(this, "
|
|
2191
|
+
_defineProperty(this, "_errorAtMinZoom", 1000);
|
|
1762
2192
|
|
|
1763
|
-
_defineProperty(this, "
|
|
2193
|
+
_defineProperty(this, "resource", null);
|
|
1764
2194
|
|
|
1765
|
-
_defineProperty(this, "
|
|
2195
|
+
_defineProperty(this, "interval", void 0);
|
|
2196
|
+
|
|
2197
|
+
_defineProperty(this, "offset", void 0);
|
|
1766
2198
|
|
|
1767
2199
|
_defineProperty(this, "RADIUS_SCALAR", 1.0);
|
|
1768
2200
|
|
|
1769
2201
|
//this.martini = new Martini(257);
|
|
1770
|
-
this.
|
|
1771
|
-
this.
|
|
1772
|
-
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;
|
|
1773
2208
|
this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 4.0) + cesium.Math.EPSILON5;
|
|
1774
|
-
this.martini = new Martini(this.tileSize + 1);
|
|
1775
2209
|
this.ready = true;
|
|
1776
2210
|
this.readyPromise = Promise.resolve(true);
|
|
1777
|
-
this.accessToken = opts.accessToken;
|
|
1778
2211
|
this.minError = (_opts$minimumErrorLev = opts.minimumErrorLevel) !== null && _opts$minimumErrorLev !== void 0 ? _opts$minimumErrorLev : 0.1;
|
|
1779
2212
|
this.errorEvent.addEventListener(console.log, this);
|
|
1780
2213
|
this.ellipsoid = (_opts$ellipsoid = opts.ellipsoid) !== null && _opts$ellipsoid !== void 0 ? _opts$ellipsoid : cesium.Ellipsoid.WGS84;
|
|
1781
|
-
|
|
1782
|
-
this.
|
|
1783
|
-
|
|
2214
|
+
|
|
2215
|
+
if (this.maxWorkers > 0) {
|
|
2216
|
+
this.workerFarm = new WorkerFarm();
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
var scheme = cesium.WebMercatorTilingScheme;
|
|
2220
|
+
|
|
2221
|
+
if (this.fillPoles) {
|
|
2222
|
+
scheme = StretchedTilingScheme;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
this.tilingScheme = new scheme({
|
|
1784
2226
|
numberOfLevelZeroTilesX: 1,
|
|
1785
2227
|
numberOfLevelZeroTilesY: 1,
|
|
1786
2228
|
ellipsoid: this.ellipsoid
|
|
1787
2229
|
});
|
|
2230
|
+
this._errorAtMinZoom = this.errorAtZoom(this.minZoomLevel);
|
|
1788
2231
|
}
|
|
1789
2232
|
|
|
1790
2233
|
_createClass(MartiniTerrainProvider, [{
|
|
1791
|
-
key: "getCanvas",
|
|
1792
|
-
value: function getCanvas() {
|
|
1793
|
-
var ctx = this.contextQueue.pop();
|
|
1794
|
-
|
|
1795
|
-
if (ctx == null) {
|
|
1796
|
-
//console.log("Creating new canvas element");
|
|
1797
|
-
var canvas = document.createElement("canvas");
|
|
1798
|
-
canvas.width = this.tileSize;
|
|
1799
|
-
canvas.height = this.tileSize;
|
|
1800
|
-
var context = canvas.getContext("2d");
|
|
1801
|
-
ctx = {
|
|
1802
|
-
canvas: canvas,
|
|
1803
|
-
context: context
|
|
1804
|
-
};
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
return ctx;
|
|
1808
|
-
}
|
|
1809
|
-
}, {
|
|
1810
|
-
key: "getPixels",
|
|
1811
|
-
value: function getPixels(img) {
|
|
1812
|
-
var canvasRef = this.getCanvas();
|
|
1813
|
-
var context = canvasRef.context; //context.scale(1, -1);
|
|
1814
|
-
// Chrome appears to vertically flip the image for reasons that are unclear
|
|
1815
|
-
// We can make it work in Chrome by drawing the image upside-down at this step.
|
|
1816
|
-
|
|
1817
|
-
context.drawImage(img, 0, 0, this.tileSize, this.tileSize);
|
|
1818
|
-
var pixels = context.getImageData(0, 0, this.tileSize, this.tileSize);
|
|
1819
|
-
context.clearRect(0, 0, this.tileSize, this.tileSize);
|
|
1820
|
-
this.contextQueue.push(canvasRef);
|
|
1821
|
-
return pixels;
|
|
1822
|
-
}
|
|
1823
|
-
}, {
|
|
1824
|
-
key: "buildTileURL",
|
|
1825
|
-
value: function buildTileURL(tileCoords) {
|
|
1826
|
-
var z = tileCoords.z,
|
|
1827
|
-
x = tileCoords.x,
|
|
1828
|
-
y = tileCoords.y;
|
|
1829
|
-
var hires = this.highResolution ? "@2x" : ""; // https://api.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}&sku=101EX9Btybqbj
|
|
1830
|
-
|
|
1831
|
-
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);
|
|
1832
|
-
}
|
|
1833
|
-
}, {
|
|
1834
2234
|
key: "requestTileGeometry",
|
|
1835
2235
|
value: function requestTileGeometry(x, y, z, request) {
|
|
1836
2236
|
var _this = this;
|
|
1837
2237
|
|
|
1838
|
-
|
|
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;
|
|
1839
2246
|
this.inProgressWorkers += 1;
|
|
1840
2247
|
return this.processTile(x, y, z)["finally"](function () {
|
|
1841
2248
|
_this.inProgressWorkers -= 1;
|
|
@@ -1845,37 +2252,28 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1845
2252
|
key: "processTile",
|
|
1846
2253
|
value: function () {
|
|
1847
2254
|
var _processTile = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(x, y, z) {
|
|
1848
|
-
var
|
|
2255
|
+
var _this$resource, tileSize, getTilePixels, px, pixelData, tileRect, err, maxLength, params, res;
|
|
2256
|
+
|
|
1849
2257
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
1850
2258
|
while (1) {
|
|
1851
2259
|
switch (_context.prev = _context.next) {
|
|
1852
2260
|
case 0:
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
this.highResolution ? "@2x" : "";
|
|
1858
|
-
_context.prev = 2;
|
|
1859
|
-
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({
|
|
1860
2265
|
x: x,
|
|
1861
2266
|
y: y,
|
|
1862
2267
|
z: z
|
|
1863
2268
|
});
|
|
1864
|
-
_context.next = 6;
|
|
1865
|
-
return loadImage(url);
|
|
1866
2269
|
|
|
1867
|
-
case
|
|
1868
|
-
|
|
1869
|
-
px = this.getPixels(image);
|
|
2270
|
+
case 4:
|
|
2271
|
+
px = _context.sent;
|
|
1870
2272
|
pixelData = px.data;
|
|
1871
|
-
tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
|
|
1872
|
-
maxLength = null; // More than a degree or so
|
|
1873
|
-
|
|
1874
|
-
if (tileRect.height > 0.01) {
|
|
1875
|
-
// We need to be able to specify a minimum number of triangles...
|
|
1876
|
-
maxLength = 20 * (z + 1);
|
|
1877
|
-
}
|
|
2273
|
+
tileRect = this.tilingScheme.tileXYToRectangle(x, y, z); ///const center = Rectangle.center(tileRect);
|
|
1878
2274
|
|
|
2275
|
+
err = this.errorAtZoom(z);
|
|
2276
|
+
maxLength = this.maxVertexDistance(tileRect);
|
|
1879
2277
|
params = {
|
|
1880
2278
|
imageData: pixelData,
|
|
1881
2279
|
maxLength: maxLength,
|
|
@@ -1884,43 +2282,44 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1884
2282
|
z: z,
|
|
1885
2283
|
errorLevel: err,
|
|
1886
2284
|
ellipsoidRadius: this.ellipsoid.maximumRadius,
|
|
1887
|
-
tileSize:
|
|
2285
|
+
tileSize: tileSize,
|
|
2286
|
+
interval: this.interval,
|
|
2287
|
+
offset: this.offset
|
|
1888
2288
|
};
|
|
1889
2289
|
|
|
1890
|
-
if (!this.
|
|
1891
|
-
_context.next =
|
|
2290
|
+
if (!(this.workerFarm != null)) {
|
|
2291
|
+
_context.next = 16;
|
|
1892
2292
|
break;
|
|
1893
2293
|
}
|
|
1894
2294
|
|
|
1895
|
-
_context.next =
|
|
2295
|
+
_context.next = 13;
|
|
1896
2296
|
return this.workerFarm.scheduleTask(params, [pixelData.buffer]);
|
|
1897
2297
|
|
|
1898
|
-
case
|
|
2298
|
+
case 13:
|
|
1899
2299
|
res = _context.sent;
|
|
1900
|
-
_context.next =
|
|
2300
|
+
_context.next = 17;
|
|
1901
2301
|
break;
|
|
1902
2302
|
|
|
1903
|
-
case
|
|
2303
|
+
case 16:
|
|
1904
2304
|
res = decodeTerrain(params);
|
|
1905
2305
|
|
|
1906
|
-
case
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
case 24:
|
|
1911
|
-
_context.prev = 24;
|
|
1912
|
-
_context.t0 = _context["catch"](2);
|
|
1913
|
-
console.log(_context.t0); // return undefined
|
|
2306
|
+
case 17:
|
|
2307
|
+
pixelData = undefined;
|
|
2308
|
+
px = undefined;
|
|
2309
|
+
return _context.abrupt("return", this.createQuantizedMeshData(tileRect, err, res));
|
|
1914
2310
|
|
|
1915
|
-
|
|
1916
|
-
|
|
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));
|
|
1917
2316
|
|
|
1918
|
-
case
|
|
2317
|
+
case 26:
|
|
1919
2318
|
case "end":
|
|
1920
2319
|
return _context.stop();
|
|
1921
2320
|
}
|
|
1922
2321
|
}
|
|
1923
|
-
}, _callee, this, [[
|
|
2322
|
+
}, _callee, this, [[0, 22]]);
|
|
1924
2323
|
}));
|
|
1925
2324
|
|
|
1926
2325
|
function processTile(_x, _x2, _x3) {
|
|
@@ -1930,58 +2329,69 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1930
2329
|
return processTile;
|
|
1931
2330
|
}()
|
|
1932
2331
|
}, {
|
|
1933
|
-
key: "
|
|
1934
|
-
value: function
|
|
2332
|
+
key: "errorAtZoom",
|
|
2333
|
+
value: function errorAtZoom(zoom) {
|
|
1935
2334
|
return Math.max(this.getLevelMaximumGeometricError(zoom) / this.levelOfDetailScalar, this.minError);
|
|
1936
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
|
+
}
|
|
1937
2359
|
}, {
|
|
1938
2360
|
key: "createQuantizedMeshData",
|
|
1939
2361
|
value: function createQuantizedMeshData(tileRect, errorLevel, workerOutput) {
|
|
1940
|
-
var
|
|
1941
|
-
|
|
2362
|
+
var minimumHeight = workerOutput.minimumHeight,
|
|
2363
|
+
maximumHeight = workerOutput.maximumHeight,
|
|
1942
2364
|
quantizedVertices = workerOutput.quantizedVertices,
|
|
1943
|
-
|
|
2365
|
+
indices = workerOutput.indices,
|
|
1944
2366
|
westIndices = workerOutput.westIndices,
|
|
1945
2367
|
southIndices = workerOutput.southIndices,
|
|
1946
2368
|
eastIndices = workerOutput.eastIndices,
|
|
1947
2369
|
northIndices = workerOutput.northIndices;
|
|
1948
2370
|
var err = errorLevel;
|
|
1949
|
-
var skirtHeight = err *
|
|
1950
|
-
var
|
|
1951
|
-
// tileRect.width is given in radians
|
|
1952
|
-
// cos of half-tile-width allows us to use right-triangle relationship
|
|
2371
|
+
var skirtHeight = err * 20;
|
|
2372
|
+
var center = cesium.Rectangle.center(tileRect); // Calculating occlusion height is kind of messy currently, but it definitely works
|
|
1953
2373
|
|
|
1954
|
-
var
|
|
1955
|
-
//
|
|
1956
|
-
// ... it might be better to use the radius of the entire
|
|
2374
|
+
var halfAngle = tileRect.width / 2;
|
|
2375
|
+
var dr = Math.cos(halfAngle); // half tile width since our ref point is at the center
|
|
1957
2376
|
|
|
1958
|
-
var
|
|
2377
|
+
var occlusionHeight = dr * this.ellipsoid.maximumRadius + maximumHeight;
|
|
1959
2378
|
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
var horizonOcclusionPoint = new cesium.Cartesian3(scaledCenter.x, scaledCenter.y, occlusionHeight * Math.sign(tileCenter.z));
|
|
1963
|
-
var orientedBoundingBox = null;
|
|
1964
|
-
var boundingSphere;
|
|
1965
|
-
|
|
1966
|
-
if (tileRect.width < cesium.Math.PI_OVER_TWO + cesium.Math.EPSILON5) {
|
|
1967
|
-
// @ts-ignore
|
|
1968
|
-
orientedBoundingBox = cesium.OrientedBoundingBox.fromRectangle(tileRect, minHeight, maxHeight); // @ts-ignore
|
|
1969
|
-
|
|
1970
|
-
boundingSphere = cesium.BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox);
|
|
1971
|
-
} else {
|
|
1972
|
-
// If our bounding rectangle spans >= 90º, we should use the entire globe as a bounding sphere.
|
|
1973
|
-
boundingSphere = new cesium.BoundingSphere(cesium.Cartesian3.ZERO, // radius (seems to be max height of Earth terrain?)
|
|
1974
|
-
6379792.481506292);
|
|
2379
|
+
if (halfAngle > Math.PI / 4) {
|
|
2380
|
+
occlusionHeight = (1 + halfAngle) * this.ellipsoid.maximumRadius;
|
|
1975
2381
|
}
|
|
1976
2382
|
|
|
1977
|
-
|
|
2383
|
+
var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude, occlusionHeight // Scaling factor of two just to be sure.
|
|
2384
|
+
);
|
|
2385
|
+
var horizonOcclusionPoint = this.ellipsoid.transformPositionToScaledSpace(cesium.Cartographic.toCartesian(occlusionPoint));
|
|
2386
|
+
var orientedBoundingBox = cesium.OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, this.tilingScheme.ellipsoid);
|
|
2387
|
+
var boundingSphere = cesium.BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox); // SE NW NE
|
|
1978
2388
|
// NE NW SE
|
|
1979
2389
|
|
|
1980
|
-
|
|
1981
|
-
minimumHeight:
|
|
1982
|
-
maximumHeight:
|
|
2390
|
+
var result = new cesium.QuantizedMeshTerrainData({
|
|
2391
|
+
minimumHeight: minimumHeight,
|
|
2392
|
+
maximumHeight: maximumHeight,
|
|
1983
2393
|
quantizedVertices: quantizedVertices,
|
|
1984
|
-
indices:
|
|
2394
|
+
indices: indices,
|
|
1985
2395
|
boundingSphere: boundingSphere,
|
|
1986
2396
|
orientedBoundingBox: orientedBoundingBox,
|
|
1987
2397
|
horizonOcclusionPoint: horizonOcclusionPoint,
|
|
@@ -1995,15 +2405,7 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
1995
2405
|
northSkirtHeight: skirtHeight,
|
|
1996
2406
|
childTileMask: 15
|
|
1997
2407
|
});
|
|
1998
|
-
|
|
1999
|
-
}, {
|
|
2000
|
-
key: "emptyHeightmap",
|
|
2001
|
-
value: function emptyHeightmap(samples) {
|
|
2002
|
-
return new cesium.HeightmapTerrainData({
|
|
2003
|
-
buffer: new Uint8Array(Array(samples * samples).fill(0)),
|
|
2004
|
-
width: samples,
|
|
2005
|
-
height: samples
|
|
2006
|
-
});
|
|
2408
|
+
return result;
|
|
2007
2409
|
}
|
|
2008
2410
|
}, {
|
|
2009
2411
|
key: "getLevelMaximumGeometricError",
|
|
@@ -2011,19 +2413,44 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
|
|
|
2011
2413
|
var levelZeroMaximumGeometricError = cesium.TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this.tilingScheme.ellipsoid, 65, this.tilingScheme.getNumberOfXTilesAtLevel(0)); // Scalar to control overzooming
|
|
2012
2414
|
// also seems to control zooming for imagery layers
|
|
2013
2415
|
|
|
2014
|
-
var scalar =
|
|
2015
|
-
|
|
2416
|
+
var scalar = this.resource.tileSize / 256;
|
|
2016
2417
|
return levelZeroMaximumGeometricError / scalar / (1 << level);
|
|
2017
2418
|
}
|
|
2018
2419
|
}, {
|
|
2019
2420
|
key: "getTileDataAvailable",
|
|
2020
2421
|
value: function getTileDataAvailable(x, y, z) {
|
|
2021
|
-
return
|
|
2422
|
+
return this.resource.getTileDataAvailable({
|
|
2423
|
+
x: x,
|
|
2424
|
+
y: y,
|
|
2425
|
+
z: z
|
|
2426
|
+
});
|
|
2022
2427
|
}
|
|
2023
2428
|
}]);
|
|
2024
2429
|
|
|
2025
2430
|
return MartiniTerrainProvider;
|
|
2026
2431
|
}();
|
|
2027
2432
|
|
|
2028
|
-
|
|
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;
|
|
2029
2456
|
//# sourceMappingURL=index.js.map
|