@macrostrat/cesium-martini 1.3.0 → 1.5.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/dist/index.js CHANGED
@@ -1,6 +1,107 @@
1
- import { Resource, Credit, Event, Math as Math$1, Ellipsoid, Rectangle, Cartographic, OrientedBoundingBox, BoundingSphere, QuantizedMeshTerrainData, TerrainProvider, WebMercatorTilingScheme } from 'cesium';
2
- import ndarray from 'ndarray';
1
+ import { Resource, Credit, Rectangle, Cartographic, OrientedBoundingBox, BoundingSphere, QuantizedMeshTerrainData, WebMercatorTilingScheme, TerrainProvider, Event, Ellipsoid, Math as Math$1 } from 'cesium';
3
2
 
3
+ function _arrayLikeToArray(r, a) {
4
+ (null == a || a > r.length) && (a = r.length);
5
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
6
+ return n;
7
+ }
8
+ function _arrayWithoutHoles(r) {
9
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
10
+ }
11
+ function _assertThisInitialized(e) {
12
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
13
+ return e;
14
+ }
15
+ function asyncGeneratorStep(n, t, e, r, o, a, c) {
16
+ try {
17
+ var i = n[a](c),
18
+ u = i.value;
19
+ } catch (n) {
20
+ return void e(n);
21
+ }
22
+ i.done ? t(u) : Promise.resolve(u).then(r, o);
23
+ }
24
+ function _asyncToGenerator(n) {
25
+ return function () {
26
+ var t = this,
27
+ e = arguments;
28
+ return new Promise(function (r, o) {
29
+ var a = n.apply(t, e);
30
+ function _next(n) {
31
+ asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
32
+ }
33
+ function _throw(n) {
34
+ asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
35
+ }
36
+ _next(void 0);
37
+ });
38
+ };
39
+ }
40
+ function _callSuper(t, o, e) {
41
+ return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
42
+ }
43
+ function _classCallCheck(a, n) {
44
+ if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
45
+ }
46
+ function _defineProperties(e, r) {
47
+ for (var t = 0; t < r.length; t++) {
48
+ var o = r[t];
49
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
50
+ }
51
+ }
52
+ function _createClass(e, r, t) {
53
+ return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
54
+ writable: !1
55
+ }), e;
56
+ }
57
+ function _defineProperty(e, r, t) {
58
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
59
+ value: t,
60
+ enumerable: !0,
61
+ configurable: !0,
62
+ writable: !0
63
+ }) : e[r] = t, e;
64
+ }
65
+ function _get() {
66
+ return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
67
+ var p = _superPropBase(e, t);
68
+ if (p) {
69
+ var n = Object.getOwnPropertyDescriptor(p, t);
70
+ return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
71
+ }
72
+ }, _get.apply(null, arguments);
73
+ }
74
+ function _getPrototypeOf(t) {
75
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
76
+ return t.__proto__ || Object.getPrototypeOf(t);
77
+ }, _getPrototypeOf(t);
78
+ }
79
+ function _inherits(t, e) {
80
+ if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
81
+ t.prototype = Object.create(e && e.prototype, {
82
+ constructor: {
83
+ value: t,
84
+ writable: !0,
85
+ configurable: !0
86
+ }
87
+ }), Object.defineProperty(t, "prototype", {
88
+ writable: !1
89
+ }), e && _setPrototypeOf(t, e);
90
+ }
91
+ function _isNativeReflectConstruct() {
92
+ try {
93
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
94
+ } catch (t) {}
95
+ return (_isNativeReflectConstruct = function () {
96
+ return !!t;
97
+ })();
98
+ }
99
+ function _iterableToArray(r) {
100
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
101
+ }
102
+ function _nonIterableSpread() {
103
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
104
+ }
4
105
  function ownKeys(e, r) {
5
106
  var t = Object.keys(e);
6
107
  if (Object.getOwnPropertySymbols) {
@@ -22,6 +123,31 @@ function _objectSpread2(e) {
22
123
  }
23
124
  return e;
24
125
  }
126
+ function _objectWithoutProperties(e, t) {
127
+ if (null == e) return {};
128
+ var o,
129
+ r,
130
+ i = _objectWithoutPropertiesLoose(e, t);
131
+ if (Object.getOwnPropertySymbols) {
132
+ var n = Object.getOwnPropertySymbols(e);
133
+ for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
134
+ }
135
+ return i;
136
+ }
137
+ function _objectWithoutPropertiesLoose(r, e) {
138
+ if (null == r) return {};
139
+ var t = {};
140
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
141
+ if (-1 !== e.indexOf(n)) continue;
142
+ t[n] = r[n];
143
+ }
144
+ return t;
145
+ }
146
+ function _possibleConstructorReturn(t, e) {
147
+ if (e && ("object" == typeof e || "function" == typeof e)) return e;
148
+ if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
149
+ return _assertThisInitialized(t);
150
+ }
25
151
  function _regeneratorRuntime() {
26
152
  _regeneratorRuntime = function () {
27
153
  return e;
@@ -130,7 +256,7 @@ function _regeneratorRuntime() {
130
256
  function makeInvokeMethod(e, r, n) {
131
257
  var o = h;
132
258
  return function (i, a) {
133
- if (o === f) throw new Error("Generator is already running");
259
+ if (o === f) throw Error("Generator is already running");
134
260
  if (o === s) {
135
261
  if ("throw" === i) throw a;
136
262
  return {
@@ -272,7 +398,7 @@ function _regeneratorRuntime() {
272
398
  } else if (c) {
273
399
  if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
274
400
  } else {
275
- if (!u) throw new Error("try statement without catch or finally");
401
+ if (!u) throw Error("try statement without catch or finally");
276
402
  if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
277
403
  }
278
404
  }
@@ -312,7 +438,7 @@ function _regeneratorRuntime() {
312
438
  return o;
313
439
  }
314
440
  }
315
- throw new Error("illegal catch attempt");
441
+ throw Error("illegal catch attempt");
316
442
  },
317
443
  delegateYield: function (e, r, n) {
318
444
  return this.delegate = {
@@ -323,258 +449,80 @@ function _regeneratorRuntime() {
323
449
  }
324
450
  }, e;
325
451
  }
326
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
327
- try {
328
- var info = gen[key](arg);
329
- var value = info.value;
330
- } catch (error) {
331
- reject(error);
332
- return;
333
- }
334
- if (info.done) {
335
- resolve(value);
336
- } else {
337
- Promise.resolve(value).then(_next, _throw);
338
- }
452
+ function _setPrototypeOf(t, e) {
453
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
454
+ return t.__proto__ = e, t;
455
+ }, _setPrototypeOf(t, e);
339
456
  }
340
- function _asyncToGenerator(fn) {
341
- return function () {
342
- var self = this,
343
- args = arguments;
344
- return new Promise(function (resolve, reject) {
345
- var gen = fn.apply(self, args);
346
- function _next(value) {
347
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
348
- }
349
- function _throw(err) {
350
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
351
- }
352
- _next(undefined);
353
- });
354
- };
355
- }
356
- function _classCallCheck(instance, Constructor) {
357
- if (!(instance instanceof Constructor)) {
358
- throw new TypeError("Cannot call a class as a function");
359
- }
360
- }
361
- function _defineProperties(target, props) {
362
- for (var i = 0; i < props.length; i++) {
363
- var descriptor = props[i];
364
- descriptor.enumerable = descriptor.enumerable || false;
365
- descriptor.configurable = true;
366
- if ("value" in descriptor) descriptor.writable = true;
367
- Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
368
- }
369
- }
370
- function _createClass(Constructor, protoProps, staticProps) {
371
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
372
- if (staticProps) _defineProperties(Constructor, staticProps);
373
- Object.defineProperty(Constructor, "prototype", {
374
- writable: false
375
- });
376
- return Constructor;
377
- }
378
- function _defineProperty(obj, key, value) {
379
- key = _toPropertyKey(key);
380
- if (key in obj) {
381
- Object.defineProperty(obj, key, {
382
- value: value,
383
- enumerable: true,
384
- configurable: true,
385
- writable: true
386
- });
387
- } else {
388
- obj[key] = value;
389
- }
390
- return obj;
391
- }
392
- function _inherits(subClass, superClass) {
393
- if (typeof superClass !== "function" && superClass !== null) {
394
- throw new TypeError("Super expression must either be null or a function");
395
- }
396
- subClass.prototype = Object.create(superClass && superClass.prototype, {
397
- constructor: {
398
- value: subClass,
399
- writable: true,
400
- configurable: true
401
- }
402
- });
403
- Object.defineProperty(subClass, "prototype", {
404
- writable: false
405
- });
406
- if (superClass) _setPrototypeOf(subClass, superClass);
407
- }
408
- function _getPrototypeOf(o) {
409
- _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
410
- return o.__proto__ || Object.getPrototypeOf(o);
411
- };
412
- return _getPrototypeOf(o);
413
- }
414
- function _setPrototypeOf(o, p) {
415
- _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
416
- o.__proto__ = p;
417
- return o;
418
- };
419
- return _setPrototypeOf(o, p);
420
- }
421
- function _isNativeReflectConstruct() {
422
- if (typeof Reflect === "undefined" || !Reflect.construct) return false;
423
- if (Reflect.construct.sham) return false;
424
- if (typeof Proxy === "function") return true;
425
- try {
426
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
427
- return true;
428
- } catch (e) {
429
- return false;
430
- }
431
- }
432
- function _assertThisInitialized(self) {
433
- if (self === void 0) {
434
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
435
- }
436
- return self;
437
- }
438
- function _possibleConstructorReturn(self, call) {
439
- if (call && (typeof call === "object" || typeof call === "function")) {
440
- return call;
441
- } else if (call !== void 0) {
442
- throw new TypeError("Derived constructors may only return object or undefined");
443
- }
444
- return _assertThisInitialized(self);
457
+ function _superPropBase(t, o) {
458
+ for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t)););
459
+ return t;
445
460
  }
446
- function _createSuper(Derived) {
447
- var hasNativeReflectConstruct = _isNativeReflectConstruct();
448
- return function _createSuperInternal() {
449
- var Super = _getPrototypeOf(Derived),
450
- result;
451
- if (hasNativeReflectConstruct) {
452
- var NewTarget = _getPrototypeOf(this).constructor;
453
- result = Reflect.construct(Super, arguments, NewTarget);
454
- } else {
455
- result = Super.apply(this, arguments);
456
- }
457
- return _possibleConstructorReturn(this, result);
458
- };
461
+ function _superPropGet(t, o, e, r) {
462
+ var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e);
463
+ return 2 & r && "function" == typeof p ? function (t) {
464
+ return p.apply(e, t);
465
+ } : p;
459
466
  }
460
- function _superPropBase(object, property) {
461
- while (!Object.prototype.hasOwnProperty.call(object, property)) {
462
- object = _getPrototypeOf(object);
463
- if (object === null) break;
464
- }
465
- return object;
467
+ function _toConsumableArray(r) {
468
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
466
469
  }
467
- function _get() {
468
- if (typeof Reflect !== "undefined" && Reflect.get) {
469
- _get = Reflect.get.bind();
470
- } else {
471
- _get = function _get(target, property, receiver) {
472
- var base = _superPropBase(target, property);
473
- if (!base) return;
474
- var desc = Object.getOwnPropertyDescriptor(base, property);
475
- if (desc.get) {
476
- return desc.get.call(arguments.length < 3 ? target : receiver);
477
- }
478
- return desc.value;
479
- };
470
+ function _toPrimitive(t, r) {
471
+ if ("object" != typeof t || !t) return t;
472
+ var e = t[Symbol.toPrimitive];
473
+ if (void 0 !== e) {
474
+ var i = e.call(t, r || "default");
475
+ if ("object" != typeof i) return i;
476
+ throw new TypeError("@@toPrimitive must return a primitive value.");
480
477
  }
481
- return _get.apply(this, arguments);
482
- }
483
- function _toConsumableArray(arr) {
484
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
478
+ return ("string" === r ? String : Number)(t);
485
479
  }
486
- function _arrayWithoutHoles(arr) {
487
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
480
+ function _toPropertyKey(t) {
481
+ var i = _toPrimitive(t, "string");
482
+ return "symbol" == typeof i ? i : i + "";
488
483
  }
489
- function _iterableToArray(iter) {
490
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
491
- }
492
- function _unsupportedIterableToArray(o, minLen) {
493
- if (!o) return;
494
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
495
- var n = Object.prototype.toString.call(o).slice(8, -1);
496
- if (n === "Object" && o.constructor) n = o.constructor.name;
497
- if (n === "Map" || n === "Set") return Array.from(o);
498
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
499
- }
500
- function _arrayLikeToArray(arr, len) {
501
- if (len == null || len > arr.length) len = arr.length;
502
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
503
- return arr2;
504
- }
505
- function _nonIterableSpread() {
506
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
507
- }
508
- function _toPrimitive(input, hint) {
509
- if (typeof input !== "object" || input === null) return input;
510
- var prim = input[Symbol.toPrimitive];
511
- if (prim !== undefined) {
512
- var res = prim.call(input, hint || "default");
513
- if (typeof res !== "object") return res;
514
- throw new TypeError("@@toPrimitive must return a primitive value.");
484
+ function _unsupportedIterableToArray(r, a) {
485
+ if (r) {
486
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
487
+ var t = {}.toString.call(r).slice(8, -1);
488
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
515
489
  }
516
- return (hint === "string" ? String : Number)(input);
517
- }
518
- function _toPropertyKey(arg) {
519
- var key = _toPrimitive(arg, "string");
520
- return typeof key === "symbol" ? key : String(key);
521
490
  }
522
491
 
523
- var loadImage = function loadImage(url) {
524
- return new Promise(function (resolve, reject) {
525
- var img = new Image();
526
- img.addEventListener("load", function () {
527
- return resolve(img);
528
- });
529
- img.addEventListener("error", function (err) {
530
- return reject(err);
531
- });
532
- img.crossOrigin = "anonymous";
533
- img.src = url;
534
- });
535
- };
536
492
  var DefaultHeightmapResource = /*#__PURE__*/function () {
537
493
  function DefaultHeightmapResource() {
538
- var _this = this,
539
- _opts$skipOddLevels,
540
- _opts$tileSize,
541
- _opts$maxZoom;
494
+ var _opts$tileSize, _opts$maxZoom;
542
495
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
543
496
  _classCallCheck(this, DefaultHeightmapResource);
544
497
  _defineProperty(this, "resource", null);
545
498
  _defineProperty(this, "tileSize", 256);
546
- _defineProperty(this, "skipOddLevels", false);
547
- _defineProperty(this, "getTilePixels", /*#__PURE__*/function () {
548
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(coords) {
549
- var url, img;
550
- return _regeneratorRuntime().wrap(function _callee$(_context) {
551
- while (1) switch (_context.prev = _context.next) {
552
- case 0:
553
- url = _this.buildTileURL(coords);
554
- _context.next = 3;
555
- return loadImage(url);
556
- case 3:
557
- img = _context.sent;
558
- return _context.abrupt("return", _this.getPixels(img));
559
- case 5:
560
- case "end":
561
- return _context.stop();
562
- }
563
- }, _callee);
564
- }));
565
- return function (_x) {
566
- return _ref.apply(this, arguments);
567
- };
568
- }());
569
499
  if (opts.url) {
570
- this.resource = Resource.createIfNeeded(opts.url);
500
+ this.resource = new Resource({
501
+ url: opts.url
502
+ });
503
+ }
504
+ this.skipZoomLevel = function () {
505
+ return false;
506
+ };
507
+ if (opts.skipZoomLevels) {
508
+ if (Array.isArray(opts.skipZoomLevels)) {
509
+ var _skipZoomLevels = opts.skipZoomLevels;
510
+ this.skipZoomLevel = function (z) {
511
+ return _skipZoomLevels.includes(z);
512
+ };
513
+ } else {
514
+ this.skipZoomLevel = opts.skipZoomLevels;
515
+ }
516
+ } else if (opts.skipOddLevels) {
517
+ this.skipZoomLevel = function (z) {
518
+ return z % 2 == 1;
519
+ };
571
520
  }
572
- this.skipOddLevels = (_opts$skipOddLevels = opts.skipOddLevels) !== null && _opts$skipOddLevels !== void 0 ? _opts$skipOddLevels : false;
573
521
  this.tileSize = (_opts$tileSize = opts.tileSize) !== null && _opts$tileSize !== void 0 ? _opts$tileSize : 256;
574
522
  this.maxZoom = (_opts$maxZoom = opts.maxZoom) !== null && _opts$maxZoom !== void 0 ? _opts$maxZoom : 15;
575
523
  this.contextQueue = [];
576
524
  }
577
- _createClass(DefaultHeightmapResource, [{
525
+ return _createClass(DefaultHeightmapResource, [{
578
526
  key: "getCanvas",
579
527
  value: function getCanvas() {
580
528
  var ctx = this.contextQueue.pop();
@@ -605,31 +553,52 @@ var DefaultHeightmapResource = /*#__PURE__*/function () {
605
553
  return pixels;
606
554
  }
607
555
  }, {
608
- key: "buildTileURL",
609
- value: function buildTileURL(tileCoords) {
610
- var _this$resource;
556
+ key: "getTileResource",
557
+ value: function getTileResource(tileCoords) {
611
558
  // reverseY for TMS tiling (https://gist.github.com/tmcw/4954720)
612
559
  // See tiling schemes here: https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/
613
560
  var z = tileCoords.z,
614
561
  y = tileCoords.y;
615
- return (_this$resource = this.resource) === null || _this$resource === void 0 ? void 0 : _this$resource.getDerivedResource({
562
+ return this.resource.getDerivedResource({
616
563
  templateValues: _objectSpread2(_objectSpread2({}, tileCoords), {}, {
617
564
  reverseY: Math.pow(2, z) - y - 1
618
565
  }),
619
566
  preserveQueryParameters: true
620
- }).getUrlComponent(true);
567
+ });
568
+ }
569
+ }, {
570
+ key: "getTilePixels",
571
+ value: function getTilePixels(coords) {
572
+ var _this = this;
573
+ var resource = this.getTileResource(coords);
574
+ var request = resource.fetchImage({
575
+ preferImageBitmap: false,
576
+ // @ts-ignore
577
+ retryAttempts: 3
578
+ });
579
+ if (request == null) return undefined;
580
+ return request.then(function (img) {
581
+ return (
582
+ // @ts-ignore
583
+ _this.getPixels(img)
584
+ );
585
+ });
621
586
  }
622
587
  }, {
623
588
  key: "getTileDataAvailable",
624
- value: function getTileDataAvailable(_ref2) {
625
- var z = _ref2.z;
589
+ value: function getTileDataAvailable(_ref) {
590
+ var z = _ref.z;
626
591
  if (z == this.maxZoom) return true;
627
- if (z % 2 == 1 && this.skipOddLevels) return false;
592
+ /* Weird hack:
593
+ For some reason, request render mode breaks if zoom 1 tiles are disabled.
594
+ So we have to make sure that we always report zoom 1 tiles as available.
595
+ */
596
+ if (z < 2) return true;
597
+ if (this.skipZoomLevel(z)) return false;
628
598
  if (z > this.maxZoom) return false;
629
599
  return true;
630
600
  }
631
601
  }]);
632
- return DefaultHeightmapResource;
633
602
  }();
634
603
 
635
604
  var ImageFormat = /*#__PURE__*/function (ImageFormat) {
@@ -639,17 +608,17 @@ var ImageFormat = /*#__PURE__*/function (ImageFormat) {
639
608
  return ImageFormat;
640
609
  }({});
641
610
  var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
642
- _inherits(MapboxTerrainResource, _DefaultHeightmapReso);
643
- var _super = _createSuper(MapboxTerrainResource);
644
611
  function MapboxTerrainResource() {
645
612
  var _opts$highResolution, _opts$imageFormat;
646
613
  var _this;
647
614
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
648
615
  _classCallCheck(this, MapboxTerrainResource);
649
- _this = _super.call(this, opts);
650
- _defineProperty(_assertThisInitialized(_this), "resource", null);
616
+ _this = _callSuper(this, MapboxTerrainResource, [opts]);
617
+ _defineProperty(_this, "resource", null);
618
+ _defineProperty(_this, "credit", new Credit("Mapbox"));
651
619
  var highResolution = (_opts$highResolution = opts.highResolution) !== null && _opts$highResolution !== void 0 ? _opts$highResolution : false;
652
620
  var format = (_opts$imageFormat = opts.imageFormat) !== null && _opts$imageFormat !== void 0 ? _opts$imageFormat : ImageFormat.WEBP;
621
+ var urlTemplate = opts.urlTemplate;
653
622
 
654
623
  // overrides based on highResolution flag
655
624
  if (highResolution) {
@@ -660,7 +629,10 @@ var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
660
629
  _this.tileSize = 512;
661
630
  }
662
631
  }
663
- _this.resource = Resource.createIfNeeded("https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format));
632
+ var defaultURL = "https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format);
633
+ _this.resource = new Resource({
634
+ url: urlTemplate !== null && urlTemplate !== void 0 ? urlTemplate : defaultURL
635
+ });
664
636
  if (opts.accessToken) {
665
637
  _this.resource.setQueryParameters({
666
638
  access_token: opts.accessToken
@@ -668,153 +640,33 @@ var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
668
640
  }
669
641
  return _this;
670
642
  }
643
+ _inherits(MapboxTerrainResource, _DefaultHeightmapReso);
671
644
  return _createClass(MapboxTerrainResource);
672
645
  }(DefaultHeightmapResource);
673
646
 
674
- function decodeBase64(base64, enableUnicode) {
675
- var binaryString = atob(base64);
676
- if (enableUnicode) {
677
- var binaryView = new Uint8Array(binaryString.length);
678
- for (var i = 0, n = binaryString.length; i < n; ++i) {
679
- binaryView[i] = binaryString.charCodeAt(i);
680
- }
681
- return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));
682
- }
683
- return binaryString;
684
- }
685
-
686
- function createURL(base64, sourcemapArg, enableUnicodeArg) {
687
- var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
688
- var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
689
- var source = decodeBase64(base64, enableUnicode);
690
- var start = source.indexOf('\n', 10) + 1;
691
- var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
692
- var blob = new Blob([body], { type: 'application/javascript' });
693
- return URL.createObjectURL(blob);
694
- }
695
-
696
- function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
697
- var url;
698
- return function WorkerFactory(options) {
699
- url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
700
- return new Worker(url, options);
701
- };
702
- }
703
-
704
- var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwp2YXIgd29ya2VyX2NvZGUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQogIGZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KGFycikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShhcnIpOwogIH0KICBmdW5jdGlvbiBfaXRlcmFibGVUb0FycmF5KGl0ZXIpIHsKICAgIGlmICh0eXBlb2YgU3ltYm9sICE9PSAidW5kZWZpbmVkIiAmJiBpdGVyW1N5bWJvbC5pdGVyYXRvcl0gIT0gbnVsbCB8fCBpdGVyWyJAQGl0ZXJhdG9yIl0gIT0gbnVsbCkgcmV0dXJuIEFycmF5LmZyb20oaXRlcik7CiAgfQogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShvLCBtaW5MZW4pIHsKICAgIGlmICghbykgcmV0dXJuOwogICAgaWYgKHR5cGVvZiBvID09PSAic3RyaW5nIikgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7CiAgICB2YXIgbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKS5zbGljZSg4LCAtMSk7CiAgICBpZiAobiA9PT0gIk9iamVjdCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTsKICAgIGlmIChuID09PSAiTWFwIiB8fCBuID09PSAiU2V0IikgcmV0dXJuIEFycmF5LmZyb20obyk7CiAgICBpZiAobiA9PT0gIkFyZ3VtZW50cyIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOwogIH0KICBmdW5jdGlvbiBfYXJyYXlMaWtlVG9BcnJheShhcnIsIGxlbikgewogICAgaWYgKGxlbiA9PSBudWxsIHx8IGxlbiA+IGFyci5sZW5ndGgpIGxlbiA9IGFyci5sZW5ndGg7CiAgICBmb3IgKHZhciBpID0gMCwgYXJyMiA9IG5ldyBBcnJheShsZW4pOyBpIDwgbGVuOyBpKyspIGFycjJbaV0gPSBhcnJbaV07CiAgICByZXR1cm4gYXJyMjsKICB9CiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkgewogICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiSW52YWxpZCBhdHRlbXB0IHRvIHNwcmVhZCBub24taXRlcmFibGUgaW5zdGFuY2UuXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuIik7CiAgfQoKICAvLyBXZSBzaG91bGQgc2F2ZSB0aGVzZQogIC8vY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcygyNTYsIDI1Nik7CiAgLy9jb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKCiAgZnVuY3Rpb24gbWFwYm94VGVycmFpblRvR3JpZChwbmcsIGludGVydmFsLCBvZmZzZXQpIHsKICAgIHZhciBfaW50ZXJ2YWwsIF9vZmZzZXQ7CiAgICAvLyBtYXliZSB3ZSBzaG91bGQgZG8gdGhpcyBvbiB0aGUgR1BVIHVzaW5nIFJFR0w/CiAgICAvLyBidXQgdGhhdCB3b3VsZCByZXF1aXJlIEdQVSAtPiBDUFUgLT4gR1BVCiAgICB2YXIgZ3JpZFNpemUgPSBwbmcuc2hhcGVbMF0gKyAxOwogICAgdmFyIHRlcnJhaW4gPSBuZXcgRmxvYXQzMkFycmF5KGdyaWRTaXplICogZ3JpZFNpemUpOwogICAgdmFyIHRpbGVTaXplID0gcG5nLnNoYXBlWzBdOwogICAgaW50ZXJ2YWwgPSAoX2ludGVydmFsID0gaW50ZXJ2YWwpICE9PSBudWxsICYmIF9pbnRlcnZhbCAhPT0gdm9pZCAwID8gX2ludGVydmFsIDogMC4xOwogICAgb2Zmc2V0ID0gKF9vZmZzZXQgPSBvZmZzZXQpICE9PSBudWxsICYmIF9vZmZzZXQgIT09IHZvaWQgMCA/IF9vZmZzZXQgOiAtMTAwMDA7CgogICAgLy8gZGVjb2RlIHRlcnJhaW4gdmFsdWVzCiAgICBmb3IgKHZhciB5ID0gMDsgeSA8IHRpbGVTaXplOyB5KyspIHsKICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCB0aWxlU2l6ZTsgeCsrKSB7CiAgICAgICAgdmFyIHljID0geTsKICAgICAgICB2YXIgciA9IHBuZy5nZXQoeCwgeWMsIDApOwogICAgICAgIHZhciBnID0gcG5nLmdldCh4LCB5YywgMSk7CiAgICAgICAgdmFyIGIgPSBwbmcuZ2V0KHgsIHljLCAyKTsKICAgICAgICB0ZXJyYWluW3kgKiBncmlkU2l6ZSArIHhdID0gciAqIDI1NiAqIDI1NiAqIGludGVydmFsICsgZyAqIDI1Ni4wICogaW50ZXJ2YWwgKyBiICogaW50ZXJ2YWwgKyBvZmZzZXQ7CiAgICAgIH0KICAgIH0KICAgIC8vIGJhY2tmaWxsIHJpZ2h0IGFuZCBib3R0b20gYm9yZGVycwogICAgZm9yICh2YXIgX3ggPSAwOyBfeCA8IGdyaWRTaXplIC0gMTsgX3grKykgewogICAgICB0ZXJyYWluW2dyaWRTaXplICogKGdyaWRTaXplIC0gMSkgKyBfeF0gPSB0ZXJyYWluW2dyaWRTaXplICogKGdyaWRTaXplIC0gMikgKyBfeF07CiAgICB9CiAgICBmb3IgKHZhciBfeSA9IDA7IF95IDwgZ3JpZFNpemU7IF95KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIF95ICsgZ3JpZFNpemUgLSAxXSA9IHRlcnJhaW5bZ3JpZFNpemUgKiBfeSArIGdyaWRTaXplIC0gMl07CiAgICB9CiAgICByZXR1cm4gdGVycmFpbjsKICB9CiAgZnVuY3Rpb24gY3JlYXRlUXVhbnRpemVkTWVzaERhdGEodGlsZSwgbWVzaCwgdGlsZVNpemUpIHsKICAgIHZhciB4dmFscyA9IFtdOwogICAgdmFyIHl2YWxzID0gW107CiAgICB2YXIgaGVpZ2h0TWV0ZXJzID0gW107CiAgICB2YXIgbm9ydGhJbmRpY2VzID0gW107CiAgICB2YXIgc291dGhJbmRpY2VzID0gW107CiAgICB2YXIgZWFzdEluZGljZXMgPSBbXTsKICAgIHZhciB3ZXN0SW5kaWNlcyA9IFtdOwogICAgdmFyIG1pbmltdW1IZWlnaHQgPSBJbmZpbml0eTsKICAgIHZhciBtYXhpbXVtSGVpZ2h0ID0gLUluZmluaXR5OwogICAgdmFyIHNjYWxhciA9IDMyNzY4LjAgLyB0aWxlU2l6ZTsKICAgIGZvciAodmFyIGl4ID0gMDsgaXggPCBtZXNoLnZlcnRpY2VzLmxlbmd0aCAvIDI7IGl4KyspIHsKICAgICAgdmFyIHZlcnRleEl4ID0gaXg7CiAgICAgIHZhciBweCA9IG1lc2gudmVydGljZXNbaXggKiAyXTsKICAgICAgdmFyIHB5ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDIgKyAxXTsKICAgICAgdmFyIGhlaWdodCA9IHRpbGUudGVycmFpbltweSAqICh0aWxlU2l6ZSArIDEpICsgcHhdOwogICAgICBpZiAoaGVpZ2h0ID4gbWF4aW11bUhlaWdodCkgbWF4aW11bUhlaWdodCA9IGhlaWdodDsKICAgICAgaWYgKGhlaWdodCA8IG1pbmltdW1IZWlnaHQpIG1pbmltdW1IZWlnaHQgPSBoZWlnaHQ7CiAgICAgIGhlaWdodE1ldGVycy5wdXNoKGhlaWdodCk7CiAgICAgIGlmIChweSA9PSAwKSBub3J0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweSA9PSB0aWxlU2l6ZSkgc291dGhJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICBpZiAocHggPT0gMCkgd2VzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSB0aWxlU2l6ZSkgZWFzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIHZhciB4diA9IHB4ICogc2NhbGFyOwogICAgICB2YXIgeXYgPSAodGlsZVNpemUgLSBweSkgKiBzY2FsYXI7CiAgICAgIHh2YWxzLnB1c2goeHYpOwogICAgICB5dmFscy5wdXNoKHl2KTsKICAgIH0KICAgIHZhciBoZWlnaHRSYW5nZSA9IG1heGltdW1IZWlnaHQgLSBtaW5pbXVtSGVpZ2h0OwogICAgdmFyIGhlaWdodHMgPSBoZWlnaHRNZXRlcnMubWFwKGZ1bmN0aW9uIChkKSB7CiAgICAgIGlmIChoZWlnaHRSYW5nZSA8IDEpIHJldHVybiAwOwogICAgICByZXR1cm4gKGQgLSBtaW5pbXVtSGVpZ2h0KSAqICgzMjc2Ny4wIC8gaGVpZ2h0UmFuZ2UpOwogICAgfSk7CiAgICB2YXIgdHJpYW5nbGVzID0gbmV3IFVpbnQxNkFycmF5KG1lc2gudHJpYW5nbGVzKTsKICAgIHZhciBxdWFudGl6ZWRWZXJ0aWNlcyA9IG5ldyBVaW50MTZBcnJheSggLy92ZXJ0cwogICAgW10uY29uY2F0KHh2YWxzLCB5dmFscywgX3RvQ29uc3VtYWJsZUFycmF5KGhlaWdodHMpKSk7CgogICAgLy8gU0UgTlcgTkUKICAgIC8vIE5FIE5XIFNFCgogICAgcmV0dXJuIHsKICAgICAgbWluaW11bUhlaWdodDogbWluaW11bUhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodDogbWF4aW11bUhlaWdodCwKICAgICAgcXVhbnRpemVkVmVydGljZXM6IHF1YW50aXplZFZlcnRpY2VzLAogICAgICBpbmRpY2VzOiB0cmlhbmdsZXMsCiAgICAgIHdlc3RJbmRpY2VzOiB3ZXN0SW5kaWNlcywKICAgICAgc291dGhJbmRpY2VzOiBzb3V0aEluZGljZXMsCiAgICAgIGVhc3RJbmRpY2VzOiBlYXN0SW5kaWNlcywKICAgICAgbm9ydGhJbmRpY2VzOiBub3J0aEluZGljZXMKICAgIH07CiAgfQoKICBmdW5jdGlvbiBpb3RhKG4pIHsKICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobik7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgewogICAgICByZXN1bHRbaV0gPSBpOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIGlvdGFfMSA9IGlvdGE7CgogIC8qIQogICAqIERldGVybWluZSBpZiBhbiBvYmplY3QgaXMgYSBCdWZmZXIKICAgKgogICAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+CiAgICogQGxpY2Vuc2UgIE1JVAogICAqLwogIC8vIFRoZSBfaXNCdWZmZXIgY2hlY2sgaXMgZm9yIFNhZmFyaSA1LTcgc3VwcG9ydCwgYmVjYXVzZSBpdCdzIG1pc3NpbmcKICAvLyBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yLiBSZW1vdmUgdGhpcyBldmVudHVhbGx5CiAgdmFyIGlzQnVmZmVyXzEgPSBmdW5jdGlvbiAob2JqKSB7CiAgICByZXR1cm4gb2JqICE9IG51bGwgJiYgKGlzQnVmZmVyKG9iaikgfHwgaXNTbG93QnVmZmVyKG9iaikgfHwgISFvYmouX2lzQnVmZmVyKTsKICB9OwogIGZ1bmN0aW9uIGlzQnVmZmVyKG9iaikgewogICAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iaik7CiAgfQoKICAvLyBGb3IgTm9kZSB2MC4xMCBzdXBwb3J0LiBSZW1vdmUgdGhpcyBldmVudHVhbGx5LgogIGZ1bmN0aW9uIGlzU2xvd0J1ZmZlcihvYmopIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKTsKICB9CgogIHZhciBoYXNUeXBlZEFycmF5cyA9IHR5cGVvZiBGbG9hdDY0QXJyYXkgIT09ICJ1bmRlZmluZWQiOwogIGZ1bmN0aW9uIGNvbXBhcmUxc3QoYSwgYikgewogICAgcmV0dXJuIGFbMF0gLSBiWzBdOwogIH0KICBmdW5jdGlvbiBvcmRlcigpIHsKICAgIHZhciBzdHJpZGUgPSB0aGlzLnN0cmlkZTsKICAgIHZhciB0ZXJtcyA9IG5ldyBBcnJheShzdHJpZGUubGVuZ3RoKTsKICAgIHZhciBpOwogICAgZm9yIChpID0gMDsgaSA8IHRlcm1zLmxlbmd0aDsgKytpKSB7CiAgICAgIHRlcm1zW2ldID0gW01hdGguYWJzKHN0cmlkZVtpXSksIGldOwogICAgfQogICAgdGVybXMuc29ydChjb21wYXJlMXN0KTsKICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodGVybXMubGVuZ3RoKTsKICAgIGZvciAoaSA9IDA7IGkgPCByZXN1bHQubGVuZ3RoOyArK2kpIHsKICAgICAgcmVzdWx0W2ldID0gdGVybXNbaV1bMV07CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiBjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGRpbWVuc2lvbikgewogICAgdmFyIGNsYXNzTmFtZSA9IFsiVmlldyIsIGRpbWVuc2lvbiwgImQiLCBkdHlwZV0uam9pbigiIik7CiAgICBpZiAoZGltZW5zaW9uIDwgMCkgewogICAgICBjbGFzc05hbWUgPSAiVmlld19OaWwiICsgZHR5cGU7CiAgICB9CiAgICB2YXIgdXNlR2V0dGVycyA9IGR0eXBlID09PSAiZ2VuZXJpYyI7CiAgICBpZiAoZGltZW5zaW9uID09PSAtMSkgewogICAgICAvL1NwZWNpYWwgY2FzZSBmb3IgdHJpdmlhbCBhcnJheXMKICAgICAgdmFyIGNvZGUgPSAiZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICIoYSl7dGhpcy5kYXRhPWE7fTtcCnZhciBwcm90bz0iICsgY2xhc3NOYW1lICsgIi5wcm90b3R5cGU7XApwcm90by5kdHlwZT0nIiArIGR0eXBlICsgIic7XApwcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiAtMX07XApwcm90by5zaXplPTA7XApwcm90by5kaW1lbnNpb249LTE7XApwcm90by5zaGFwZT1wcm90by5zdHJpZGU9cHJvdG8ub3JkZXI9W107XApwcm90by5sbz1wcm90by5oaT1wcm90by50cmFuc3Bvc2U9cHJvdG8uc3RlcD1cCmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIih0aGlzLmRhdGEpO307XApwcm90by5nZXQ9cHJvdG8uc2V0PWZ1bmN0aW9uKCl7fTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07XApyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIgKyBjbGFzc05hbWUgKyAiKGEpe3JldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIoYSk7fSI7CiAgICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oY29kZSk7CiAgICAgIHJldHVybiBwcm9jZWR1cmUoKTsKICAgIH0gZWxzZSBpZiAoZGltZW5zaW9uID09PSAwKSB7CiAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciAwZCBhcnJheXMKICAgICAgdmFyIGNvZGUgPSAiZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICIoYSxkKSB7XAp0aGlzLmRhdGEgPSBhO1wKdGhpcy5vZmZzZXQgPSBkXAp9O1wKdmFyIHByb3RvPSIgKyBjbGFzc05hbWUgKyAiLnByb3RvdHlwZTtcCnByb3RvLmR0eXBlPSciICsgZHR5cGUgKyAiJztcCnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMub2Zmc2V0fTtcCnByb3RvLmRpbWVuc2lvbj0wO1wKcHJvdG8uc2l6ZT0xO1wKcHJvdG8uc2hhcGU9XApwcm90by5zdHJpZGU9XApwcm90by5vcmRlcj1bXTtcCnByb3RvLmxvPVwKcHJvdG8uaGk9XApwcm90by50cmFuc3Bvc2U9XApwcm90by5zdGVwPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2NvcHkoKSB7XApyZXR1cm4gbmV3ICIgKyBjbGFzc05hbWUgKyAiKHRoaXMuZGF0YSx0aGlzLm9mZnNldClcCn07XApwcm90by5waWNrPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3BpY2soKXtcCnJldHVybiBUcml2aWFsQXJyYXkodGhpcy5kYXRhKTtcCn07XApwcm90by52YWx1ZU9mPXByb3RvLmdldD1mdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIl9nZXQoKXtcCnJldHVybiAiICsgKHVzZUdldHRlcnMgPyAidGhpcy5kYXRhLmdldCh0aGlzLm9mZnNldCkiIDogInRoaXMuZGF0YVt0aGlzLm9mZnNldF0iKSArICJ9O1wKcHJvdG8uc2V0PWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3NldCh2KXtcCnJldHVybiAiICsgKHVzZUdldHRlcnMgPyAidGhpcy5kYXRhLnNldCh0aGlzLm9mZnNldCx2KSIgOiAidGhpcy5kYXRhW3RoaXMub2Zmc2V0XT12IikgKyAiXAp9O1wKcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF8iICsgY2xhc3NOYW1lICsgIihhLGIsYyxkKXtyZXR1cm4gbmV3ICIgKyBjbGFzc05hbWUgKyAiKGEsZCl9IjsKICAgICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbigiVHJpdmlhbEFycmF5IiwgY29kZSk7CiAgICAgIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV1bMF0pOwogICAgfQogICAgdmFyIGNvZGUgPSBbIid1c2Ugc3RyaWN0JyJdOwoKICAgIC8vQ3JlYXRlIGNvbnN0cnVjdG9yIGZvciB2aWV3CiAgICB2YXIgaW5kaWNlcyA9IGlvdGFfMShkaW1lbnNpb24pOwogICAgdmFyIGFyZ3MgPSBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImkiICsgaTsKICAgIH0pOwogICAgdmFyIGluZGV4X3N0ciA9ICJ0aGlzLm9mZnNldCsiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJ0aGlzLnN0cmlkZVsiICsgaSArICJdKmkiICsgaTsKICAgIH0pLmpvaW4oIisiKTsKICAgIHZhciBzaGFwZUFyZyA9IGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYiIgKyBpOwogICAgfSkuam9pbigiLCIpOwogICAgdmFyIHN0cmlkZUFyZyA9IGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYyIgKyBpOwogICAgfSkuam9pbigiLCIpOwogICAgY29kZS5wdXNoKCJmdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIihhLCIgKyBzaGFwZUFyZyArICIsIiArIHN0cmlkZUFyZyArICIsZCl7dGhpcy5kYXRhPWEiLCAidGhpcy5zaGFwZT1bIiArIHNoYXBlQXJnICsgIl0iLCAidGhpcy5zdHJpZGU9WyIgKyBzdHJpZGVBcmcgKyAiXSIsICJ0aGlzLm9mZnNldD1kfDB9IiwgInZhciBwcm90bz0iICsgY2xhc3NOYW1lICsgIi5wcm90b3R5cGUiLCAicHJvdG8uZHR5cGU9JyIgKyBkdHlwZSArICInIiwgInByb3RvLmRpbWVuc2lvbj0iICsgZGltZW5zaW9uKTsKCiAgICAvL3ZpZXcuc2l6ZToKICAgIGNvZGUucHVzaCgiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdzaXplJyx7Z2V0OmZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3NpemUoKXtcCnJldHVybiAiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJ0aGlzLnNoYXBlWyIgKyBpICsgIl0iOwogICAgfSkuam9pbigiKiIpLCAifX0pIik7CgogICAgLy92aWV3Lm9yZGVyOgogICAgaWYgKGRpbWVuc2lvbiA9PT0gMSkgewogICAgICBjb2RlLnB1c2goInByb3RvLm9yZGVyPVswXSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ29yZGVyJyx7Z2V0OiIpOwogICAgICBpZiAoZGltZW5zaW9uIDwgNCkgewogICAgICAgIGNvZGUucHVzaCgiZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfb3JkZXIoKXsiKTsKICAgICAgICBpZiAoZGltZW5zaW9uID09PSAyKSB7CiAgICAgICAgICBjb2RlLnB1c2goInJldHVybiAoTWF0aC5hYnModGhpcy5zdHJpZGVbMF0pPk1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSk/WzEsMF06WzAsMV19fSkiKTsKICAgICAgICB9IGVsc2UgaWYgKGRpbWVuc2lvbiA9PT0gMykgewogICAgICAgICAgY29kZS5wdXNoKCJ2YXIgczA9TWF0aC5hYnModGhpcy5zdHJpZGVbMF0pLHMxPU1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSxzMj1NYXRoLmFicyh0aGlzLnN0cmlkZVsyXSk7XAppZihzMD5zMSl7XAppZihzMT5zMil7XApyZXR1cm4gWzIsMSwwXTtcCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMSwyLDBdO1wKfWVsc2V7XApyZXR1cm4gWzEsMCwyXTtcCn1cCn1lbHNlIGlmKHMwPnMyKXtcCnJldHVybiBbMiwwLDFdO1wKfWVsc2UgaWYoczI+czEpe1wKcmV0dXJuIFswLDEsMl07XAp9ZWxzZXtcCnJldHVybiBbMCwyLDFdO1wKfX19KSIpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb2RlLnB1c2goIk9SREVSfSkiKTsKICAgICAgfQogICAgfQoKICAgIC8vdmlldy5zZXQoaTAsIC4uLiwgdik6CiAgICBjb2RlLnB1c2goInByb3RvLnNldD1mdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIl9zZXQoIiArIGFyZ3Muam9pbigiLCIpICsgIix2KXsiKTsKICAgIGlmICh1c2VHZXR0ZXJzKSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YS5zZXQoIiArIGluZGV4X3N0ciArICIsdil9Iik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGFbIiArIGluZGV4X3N0ciArICJdPXZ9Iik7CiAgICB9CgogICAgLy92aWV3LmdldChpMCwgLi4uKToKICAgIGNvZGUucHVzaCgicHJvdG8uZ2V0PWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2dldCgiICsgYXJncy5qb2luKCIsIikgKyAiKXsiKTsKICAgIGlmICh1c2VHZXR0ZXJzKSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YS5nZXQoIiArIGluZGV4X3N0ciArICIpfSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhWyIgKyBpbmRleF9zdHIgKyAiXX0iKTsKICAgIH0KCiAgICAvL3ZpZXcuaW5kZXg6CiAgICBjb2RlLnB1c2goInByb3RvLmluZGV4PWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2luZGV4KCIsIGFyZ3Muam9pbigpLCAiKXtyZXR1cm4gIiArIGluZGV4X3N0ciArICJ9Iik7CgogICAgLy92aWV3LmhpKCk6CiAgICBjb2RlLnB1c2goInByb3RvLmhpPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2hpKCIgKyBhcmdzLmpvaW4oIiwiKSArICIpe3JldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIodGhpcy5kYXRhLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gWyIodHlwZW9mIGkiLCBpLCAiIT09J251bWJlcid8fGkiLCBpLCAiPDApP3RoaXMuc2hhcGVbIiwgaSwgIl06aSIsIGksICJ8MCJdLmpvaW4oIiIpOwogICAgfSkuam9pbigiLCIpICsgIiwiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJ0aGlzLnN0cmlkZVsiICsgaSArICJdIjsKICAgIH0pLmpvaW4oIiwiKSArICIsdGhpcy5vZmZzZXQpfSIpOwoKICAgIC8vdmlldy5sbygpOgogICAgdmFyIGFfdmFycyA9IGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYSIgKyBpICsgIj10aGlzLnNoYXBlWyIgKyBpICsgIl0iOwogICAgfSk7CiAgICB2YXIgY192YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJjIiArIGkgKyAiPXRoaXMuc3RyaWRlWyIgKyBpICsgIl0iOwogICAgfSk7CiAgICBjb2RlLnB1c2goInByb3RvLmxvPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2xvKCIgKyBhcmdzLmpvaW4oIiwiKSArICIpe3ZhciBiPXRoaXMub2Zmc2V0LGQ9MCwiICsgYV92YXJzLmpvaW4oIiwiKSArICIsIiArIGNfdmFycy5qb2luKCIsIikpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goImlmKHR5cGVvZiBpIiArIGkgKyAiPT09J251bWJlcicmJmkiICsgaSArICI+PTApe1wKZD1pIiArIGkgKyAifDA7XApiKz1jIiArIGkgKyAiKmQ7XAphIiArIGkgKyAiLT1kfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJyZXR1cm4gbmV3ICIgKyBjbGFzc05hbWUgKyAiKHRoaXMuZGF0YSwiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJhIiArIGk7CiAgICB9KS5qb2luKCIsIikgKyAiLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImMiICsgaTsKICAgIH0pLmpvaW4oIiwiKSArICIsYil9Iik7CgogICAgLy92aWV3LnN0ZXAoKToKICAgIGNvZGUucHVzaCgicHJvdG8uc3RlcD1mdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIl9zdGVwKCIgKyBhcmdzLmpvaW4oIiwiKSArICIpe3ZhciAiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJhIiArIGkgKyAiPXRoaXMuc2hhcGVbIiArIGkgKyAiXSI7CiAgICB9KS5qb2luKCIsIikgKyAiLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImIiICsgaSArICI9dGhpcy5zdHJpZGVbIiArIGkgKyAiXSI7CiAgICB9KS5qb2luKCIsIikgKyAiLGM9dGhpcy5vZmZzZXQsZD0wLGNlaWw9TWF0aC5jZWlsIik7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgiaWYodHlwZW9mIGkiICsgaSArICI9PT0nbnVtYmVyJyl7XApkPWkiICsgaSArICJ8MDtcCmlmKGQ8MCl7XApjKz1iIiArIGkgKyAiKihhIiArIGkgKyAiLTEpO1wKYSIgKyBpICsgIj1jZWlsKC1hIiArIGkgKyAiL2QpXAp9ZWxzZXtcCmEiICsgaSArICI9Y2VpbChhIiArIGkgKyAiL2QpXAp9XApiIiArIGkgKyAiKj1kXAp9Iik7CiAgICB9CiAgICBjb2RlLnB1c2goInJldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIodGhpcy5kYXRhLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImEiICsgaTsKICAgIH0pLmpvaW4oIiwiKSArICIsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYiIgKyBpOwogICAgfSkuam9pbigiLCIpICsgIixjKX0iKTsKCiAgICAvL3ZpZXcudHJhbnNwb3NlKCk6CiAgICB2YXIgdFNoYXBlID0gbmV3IEFycmF5KGRpbWVuc2lvbik7CiAgICB2YXIgdFN0cmlkZSA9IG5ldyBBcnJheShkaW1lbnNpb24pOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkaW1lbnNpb247ICsraSkgewogICAgICB0U2hhcGVbaV0gPSAiYVtpIiArIGkgKyAiXSI7CiAgICAgIHRTdHJpZGVbaV0gPSAiYltpIiArIGkgKyAiXSI7CiAgICB9CiAgICBjb2RlLnB1c2goInByb3RvLnRyYW5zcG9zZT1mdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIl90cmFuc3Bvc2UoIiArIGFyZ3MgKyAiKXsiICsgYXJncy5tYXAoZnVuY3Rpb24gKG4sIGlkeCkgewogICAgICByZXR1cm4gbiArICI9KCIgKyBuICsgIj09PXVuZGVmaW5lZD8iICsgaWR4ICsgIjoiICsgbiArICJ8MCkiOwogICAgfSkuam9pbigiOyIpLCAidmFyIGE9dGhpcy5zaGFwZSxiPXRoaXMuc3RyaWRlO3JldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIodGhpcy5kYXRhLCIgKyB0U2hhcGUuam9pbigiLCIpICsgIiwiICsgdFN0cmlkZS5qb2luKCIsIikgKyAiLHRoaXMub2Zmc2V0KX0iKTsKCiAgICAvL3ZpZXcucGljaygpOgogICAgY29kZS5wdXNoKCJwcm90by5waWNrPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3BpY2soIiArIGFyZ3MgKyAiKXt2YXIgYT1bXSxiPVtdLGM9dGhpcy5vZmZzZXQiKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKCJpZih0eXBlb2YgaSIgKyBpICsgIj09PSdudW1iZXInJiZpIiArIGkgKyAiPj0wKXtjPShjK3RoaXMuc3RyaWRlWyIgKyBpICsgIl0qaSIgKyBpICsgIil8MH1lbHNle2EucHVzaCh0aGlzLnNoYXBlWyIgKyBpICsgIl0pO2IucHVzaCh0aGlzLnN0cmlkZVsiICsgaSArICJdKX0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgidmFyIGN0b3I9Q1RPUl9MSVNUW2EubGVuZ3RoKzFdO3JldHVybiBjdG9yKHRoaXMuZGF0YSxhLGIsYyl9Iik7CgogICAgLy9BZGQgcmV0dXJuIHN0YXRlbWVudAogICAgY29kZS5wdXNoKCJyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIgKyBjbGFzc05hbWUgKyAiKGRhdGEsc2hhcGUsc3RyaWRlLG9mZnNldCl7cmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIihkYXRhLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gInNoYXBlWyIgKyBpICsgIl0iOwogICAgfSkuam9pbigiLCIpICsgIiwiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJzdHJpZGVbIiArIGkgKyAiXSI7CiAgICB9KS5qb2luKCIsIikgKyAiLG9mZnNldCl9Iik7CgogICAgLy9Db21waWxlIHByb2NlZHVyZQogICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbigiQ1RPUl9MSVNUIiwgIk9SREVSIiwgY29kZS5qb2luKCJcbiIpKTsKICAgIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV0sIG9yZGVyKTsKICB9CiAgZnVuY3Rpb24gYXJyYXlEVHlwZShkYXRhKSB7CiAgICBpZiAoaXNCdWZmZXJfMShkYXRhKSkgewogICAgICByZXR1cm4gImJ1ZmZlciI7CiAgICB9CiAgICBpZiAoaGFzVHlwZWRBcnJheXMpIHsKICAgICAgc3dpdGNoIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSkpIHsKICAgICAgICBjYXNlICJbb2JqZWN0IEZsb2F0NjRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJmbG9hdDY0IjsKICAgICAgICBjYXNlICJbb2JqZWN0IEZsb2F0MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJmbG9hdDMyIjsKICAgICAgICBjYXNlICJbb2JqZWN0IEludDhBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQ4IjsKICAgICAgICBjYXNlICJbb2JqZWN0IEludDE2QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiaW50MTYiOwogICAgICAgIGNhc2UgIltvYmplY3QgSW50MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQzMiI7CiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50OEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQ4IjsKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQxNkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQxNiI7CiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50MzIiOwogICAgICAgIGNhc2UgIltvYmplY3QgVWludDhDbGFtcGVkQXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDhfY2xhbXBlZCI7CiAgICAgICAgY2FzZSAiW29iamVjdCBCaWdJbnQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImJpZ2ludDY0IjsKICAgICAgICBjYXNlICJbb2JqZWN0IEJpZ1VpbnQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImJpZ3VpbnQ2NCI7CiAgICAgIH0KICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgIHJldHVybiAiYXJyYXkiOwogICAgfQogICAgcmV0dXJuICJnZW5lcmljIjsKICB9CiAgdmFyIENBQ0hFRF9DT05TVFJVQ1RPUlMgPSB7CiAgICAiZmxvYXQzMiI6IFtdLAogICAgImZsb2F0NjQiOiBbXSwKICAgICJpbnQ4IjogW10sCiAgICAiaW50MTYiOiBbXSwKICAgICJpbnQzMiI6IFtdLAogICAgInVpbnQ4IjogW10sCiAgICAidWludDE2IjogW10sCiAgICAidWludDMyIjogW10sCiAgICAiYXJyYXkiOiBbXSwKICAgICJ1aW50OF9jbGFtcGVkIjogW10sCiAgICAiYmlnaW50NjQiOiBbXSwKICAgICJiaWd1aW50NjQiOiBbXSwKICAgICJidWZmZXIiOiBbXSwKICAgICJnZW5lcmljIjogW10KICB9OwogIGZ1bmN0aW9uIHdyYXBwZWROREFycmF5Q3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpIHsKICAgIGlmIChkYXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIGN0b3IgPSBDQUNIRURfQ09OU1RSVUNUT1JTLmFycmF5WzBdOwogICAgICByZXR1cm4gY3RvcihbXSk7CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSAibnVtYmVyIikgewogICAgICBkYXRhID0gW2RhdGFdOwogICAgfQogICAgaWYgKHNoYXBlID09PSB1bmRlZmluZWQpIHsKICAgICAgc2hhcGUgPSBbZGF0YS5sZW5ndGhdOwogICAgfQogICAgdmFyIGQgPSBzaGFwZS5sZW5ndGg7CiAgICBpZiAoc3RyaWRlID09PSB1bmRlZmluZWQpIHsKICAgICAgc3RyaWRlID0gbmV3IEFycmF5KGQpOwogICAgICBmb3IgKHZhciBpID0gZCAtIDEsIHN6ID0gMTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICBzdHJpZGVbaV0gPSBzejsKICAgICAgICBzeiAqPSBzaGFwZVtpXTsKICAgICAgfQogICAgfQogICAgaWYgKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIG9mZnNldCA9IDA7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZDsgKytpKSB7CiAgICAgICAgaWYgKHN0cmlkZVtpXSA8IDApIHsKICAgICAgICAgIG9mZnNldCAtPSAoc2hhcGVbaV0gLSAxKSAqIHN0cmlkZVtpXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZhciBkdHlwZSA9IGFycmF5RFR5cGUoZGF0YSk7CiAgICB2YXIgY3Rvcl9saXN0ID0gQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV07CiAgICB3aGlsZSAoY3Rvcl9saXN0Lmxlbmd0aCA8PSBkICsgMSkgewogICAgICBjdG9yX2xpc3QucHVzaChjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGN0b3JfbGlzdC5sZW5ndGggLSAxKSk7CiAgICB9CiAgICB2YXIgY3RvciA9IGN0b3JfbGlzdFtkICsgMV07CiAgICByZXR1cm4gY3RvcihkYXRhLCBzaGFwZSwgc3RyaWRlLCBvZmZzZXQpOwogIH0KICB2YXIgbmRhcnJheSA9IHdyYXBwZWROREFycmF5Q3RvcjsKCiAgY2xhc3MgTWFydGluaSB7CiAgICBjb25zdHJ1Y3RvcihncmlkU2l6ZSA9IDI1NykgewogICAgICB0aGlzLmdyaWRTaXplID0gZ3JpZFNpemU7CiAgICAgIGNvbnN0IHRpbGVTaXplID0gZ3JpZFNpemUgLSAxOwogICAgICBpZiAodGlsZVNpemUgJiB0aWxlU2l6ZSAtIDEpIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgZ3JpZCBzaXplIHRvIGJlIDJebisxLCBnb3QgJHtncmlkU2l6ZX0uYCk7CiAgICAgIHRoaXMubnVtVHJpYW5nbGVzID0gdGlsZVNpemUgKiB0aWxlU2l6ZSAqIDIgLSAyOwogICAgICB0aGlzLm51bVBhcmVudFRyaWFuZ2xlcyA9IHRoaXMubnVtVHJpYW5nbGVzIC0gdGlsZVNpemUgKiB0aWxlU2l6ZTsKICAgICAgdGhpcy5pbmRpY2VzID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuZ3JpZFNpemUgKiB0aGlzLmdyaWRTaXplKTsKCiAgICAgIC8vIGNvb3JkaW5hdGVzIGZvciBhbGwgcG9zc2libGUgdHJpYW5nbGVzIGluIGFuIFJUSU4gdGlsZQogICAgICB0aGlzLmNvb3JkcyA9IG5ldyBVaW50MTZBcnJheSh0aGlzLm51bVRyaWFuZ2xlcyAqIDQpOwoKICAgICAgLy8gZ2V0IHRyaWFuZ2xlIGNvb3JkaW5hdGVzIGZyb20gaXRzIGluZGV4IGluIGFuIGltcGxpY2l0IGJpbmFyeSB0cmVlCiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1UcmlhbmdsZXM7IGkrKykgewogICAgICAgIGxldCBpZCA9IGkgKyAyOwogICAgICAgIGxldCBheCA9IDAsCiAgICAgICAgICBheSA9IDAsCiAgICAgICAgICBieCA9IDAsCiAgICAgICAgICBieSA9IDAsCiAgICAgICAgICBjeCA9IDAsCiAgICAgICAgICBjeSA9IDA7CiAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgYnggPSBieSA9IGN4ID0gdGlsZVNpemU7IC8vIGJvdHRvbS1sZWZ0IHRyaWFuZ2xlCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGF4ID0gYXkgPSBjeSA9IHRpbGVTaXplOyAvLyB0b3AtcmlnaHQgdHJpYW5nbGUKICAgICAgICB9CgogICAgICAgIHdoaWxlICgoaWQgPj49IDEpID4gMSkgewogICAgICAgICAgY29uc3QgbXggPSBheCArIGJ4ID4+IDE7CiAgICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICAgIGlmIChpZCAmIDEpIHsKICAgICAgICAgICAgLy8gbGVmdCBoYWxmCiAgICAgICAgICAgIGJ4ID0gYXg7CiAgICAgICAgICAgIGJ5ID0gYXk7CiAgICAgICAgICAgIGF4ID0gY3g7CiAgICAgICAgICAgIGF5ID0gY3k7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyByaWdodCBoYWxmCiAgICAgICAgICAgIGF4ID0gYng7CiAgICAgICAgICAgIGF5ID0gYnk7CiAgICAgICAgICAgIGJ4ID0gY3g7CiAgICAgICAgICAgIGJ5ID0gY3k7CiAgICAgICAgICB9CiAgICAgICAgICBjeCA9IG14OwogICAgICAgICAgY3kgPSBteTsKICAgICAgICB9CiAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgIHRoaXMuY29vcmRzW2sgKyAwXSA9IGF4OwogICAgICAgIHRoaXMuY29vcmRzW2sgKyAxXSA9IGF5OwogICAgICAgIHRoaXMuY29vcmRzW2sgKyAyXSA9IGJ4OwogICAgICAgIHRoaXMuY29vcmRzW2sgKyAzXSA9IGJ5OwogICAgICB9CiAgICB9CiAgICBjcmVhdGVUaWxlKHRlcnJhaW4pIHsKICAgICAgcmV0dXJuIG5ldyBUaWxlKHRlcnJhaW4sIHRoaXMpOwogICAgfQogIH0KICBjbGFzcyBUaWxlIHsKICAgIGNvbnN0cnVjdG9yKHRlcnJhaW4sIG1hcnRpbmkpIHsKICAgICAgY29uc3Qgc2l6ZSA9IG1hcnRpbmkuZ3JpZFNpemU7CiAgICAgIGlmICh0ZXJyYWluLmxlbmd0aCAhPT0gc2l6ZSAqIHNpemUpIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgdGVycmFpbiBkYXRhIG9mIGxlbmd0aCAke3NpemUgKiBzaXplfSAoJHtzaXplfSB4ICR7c2l6ZX0pLCBnb3QgJHt0ZXJyYWluLmxlbmd0aH0uYCk7CiAgICAgIHRoaXMudGVycmFpbiA9IHRlcnJhaW47CiAgICAgIHRoaXMubWFydGluaSA9IG1hcnRpbmk7CiAgICAgIHRoaXMuZXJyb3JzID0gbmV3IEZsb2F0MzJBcnJheSh0ZXJyYWluLmxlbmd0aCk7CiAgICAgIHRoaXMudXBkYXRlKCk7CiAgICB9CiAgICB1cGRhdGUoKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBudW1UcmlhbmdsZXMsCiAgICAgICAgbnVtUGFyZW50VHJpYW5nbGVzLAogICAgICAgIGNvb3JkcywKICAgICAgICBncmlkU2l6ZTogc2l6ZQogICAgICB9ID0gdGhpcy5tYXJ0aW5pOwogICAgICBjb25zdCB7CiAgICAgICAgdGVycmFpbiwKICAgICAgICBlcnJvcnMKICAgICAgfSA9IHRoaXM7CgogICAgICAvLyBpdGVyYXRlIG92ZXIgYWxsIHBvc3NpYmxlIHRyaWFuZ2xlcywgc3RhcnRpbmcgZnJvbSB0aGUgc21hbGxlc3QgbGV2ZWwKICAgICAgZm9yIChsZXQgaSA9IG51bVRyaWFuZ2xlcyAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgIGNvbnN0IGF4ID0gY29vcmRzW2sgKyAwXTsKICAgICAgICBjb25zdCBheSA9IGNvb3Jkc1trICsgMV07CiAgICAgICAgY29uc3QgYnggPSBjb29yZHNbayArIDJdOwogICAgICAgIGNvbnN0IGJ5ID0gY29vcmRzW2sgKyAzXTsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBjeCA9IG14ICsgbXkgLSBheTsKICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsKCiAgICAgICAgLy8gY2FsY3VsYXRlIGVycm9yIGluIHRoZSBtaWRkbGUgb2YgdGhlIGxvbmcgZWRnZSBvZiB0aGUgdHJpYW5nbGUKICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWRIZWlnaHQgPSAodGVycmFpbltheSAqIHNpemUgKyBheF0gKyB0ZXJyYWluW2J5ICogc2l6ZSArIGJ4XSkgLyAyOwogICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgY29uc3QgbWlkZGxlRXJyb3IgPSBNYXRoLmFicyhpbnRlcnBvbGF0ZWRIZWlnaHQgLSB0ZXJyYWluW21pZGRsZUluZGV4XSk7CiAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIG1pZGRsZUVycm9yKTsKICAgICAgICBpZiAoaSA8IG51bVBhcmVudFRyaWFuZ2xlcykgewogICAgICAgICAgLy8gYmlnZ2VyIHRyaWFuZ2xlczsgYWNjdW11bGF0ZSBlcnJvciB3aXRoIGNoaWxkcmVuCiAgICAgICAgICBjb25zdCBsZWZ0Q2hpbGRJbmRleCA9IChheSArIGN5ID4+IDEpICogc2l6ZSArIChheCArIGN4ID4+IDEpOwogICAgICAgICAgY29uc3QgcmlnaHRDaGlsZEluZGV4ID0gKGJ5ICsgY3kgPj4gMSkgKiBzaXplICsgKGJ4ICsgY3ggPj4gMSk7CiAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgZXJyb3JzW2xlZnRDaGlsZEluZGV4XSwgZXJyb3JzW3JpZ2h0Q2hpbGRJbmRleF0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZ2V0TWVzaChtYXhFcnJvciA9IDAsIG1heExlbmd0aCA9IG51bGwpIHsKICAgICAgY29uc3QgewogICAgICAgIGdyaWRTaXplOiBzaXplLAogICAgICAgIGluZGljZXMKICAgICAgfSA9IHRoaXMubWFydGluaTsKICAgICAgY29uc3QgewogICAgICAgIGVycm9ycwogICAgICB9ID0gdGhpczsKICAgICAgbGV0IG51bVZlcnRpY2VzID0gMDsKICAgICAgbGV0IG51bVRyaWFuZ2xlcyA9IDA7CiAgICAgIGNvbnN0IG1heCA9IHNpemUgLSAxOwoKICAgICAgLy8gVGhlIG1heExlbmd0aCBwYXJhbWV0ZXIgd2lsbCBjYXVzZSB0cmlhbmdsZXMgdG8gYmUgZ2VuZXJhdGVkIHVudGlsIHRoZSBsZWdzIGFyZSBiZWxvdyB0aGlzIGxlbmd0aAogICAgICAvLyBJdCBpcyBtZWFudCB0byBzdXBwb3J0IGNhc2VzIHdoZXJlIGEgY2VydGFpbiBtZXNoIGRlbnNpdHkgaXMgcmVxdWlyZWQgdG8gZG8gc3BoZXJpY2FsIG1hdGggb24gZGlnaXRhbCBnbG9iZXMKICAgICAgY29uc3QgbWF4U2NhbGUgPSBtYXhMZW5ndGggfHwgc2l6ZTsKCiAgICAgIC8vIHVzZSBhbiBpbmRleCBncmlkIHRvIGtlZXAgdHJhY2sgb2YgdmVydGljZXMgdGhhdCB3ZXJlIGFscmVhZHkgdXNlZCB0byBhdm9pZCBkdXBsaWNhdGlvbgogICAgICBpbmRpY2VzLmZpbGwoMCk7CgogICAgICAvLyByZXRyaWV2ZSBtZXNoIGluIHR3byBzdGFnZXMgdGhhdCBib3RoIHRyYXZlcnNlIHRoZSBlcnJvciBtYXA6CiAgICAgIC8vIC0gY291bnRFbGVtZW50czogZmluZCB1c2VkIHZlcnRpY2VzIChhbmQgYXNzaWduIGVhY2ggYW4gaW5kZXgpLCBhbmQgY291bnQgdHJpYW5nbGVzIChmb3IgbWluaW11bSBhbGxvY2F0aW9uKQogICAgICAvLyAtIHByb2Nlc3NUcmlhbmdsZTogZmlsbCB0aGUgYWxsb2NhdGVkIHZlcnRpY2VzICYgdHJpYW5nbGVzIHR5cGVkIGFycmF5cwoKICAgICAgZnVuY3Rpb24gY291bnRFbGVtZW50cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgY29uc3QgbXggPSBheCArIGJ4ID4+IDE7CiAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CiAgICAgICAgY29uc3QgbGVnTGVuZ3RoID0gTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KTsKICAgICAgICBpZiAobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IgfHwgbGVnTGVuZ3RoID4gbWF4U2NhbGUpIHsKICAgICAgICAgIGNvdW50RWxlbWVudHMoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSA9IGluZGljZXNbYnkgKiBzaXplICsgYnhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBpbmRpY2VzW2N5ICogc2l6ZSArIGN4XSA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICBudW1UcmlhbmdsZXMrKzsKICAgICAgICB9CiAgICAgIH0KICAgICAgY291bnRFbGVtZW50cygwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgY291bnRFbGVtZW50cyhtYXgsIG1heCwgMCwgMCwgMCwgbWF4KTsKICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICBsZXQgdHJpSW5kZXggPSAwOwogICAgICBmdW5jdGlvbiBwcm9jZXNzVHJpYW5nbGUoYXgsIGF5LCBieCwgYnksIGN4LCBjeSkgewogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGxlZ0xlbmd0aCA9IE1hdGguYWJzKGF4IC0gY3gpICsgTWF0aC5hYnMoYXkgLSBjeSk7CiAgICAgICAgaWYgKGxlZ0xlbmd0aCA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yIHx8IGxlZ0xlbmd0aCA+IG1heFNjYWxlKSB7CiAgICAgICAgICAvLyB0cmlhbmdsZSBkb2Vzbid0IGFwcHJveGltYXRlIHRoZSBzdXJmYWNlIHdlbGwgZW5vdWdoOyBkcmlsbCBkb3duIGZ1cnRoZXIKICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShieCwgYnksIGN4LCBjeSwgbXgsIG15KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgIGNvbnN0IGEgPSBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSAtIDE7CiAgICAgICAgICBjb25zdCBiID0gaW5kaWNlc1tieSAqIHNpemUgKyBieF0gLSAxOwogICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBhXSA9IGF4OwogICAgICAgICAgdmVydGljZXNbMiAqIGEgKyAxXSA9IGF5OwogICAgICAgICAgdmVydGljZXNbMiAqIGJdID0gYng7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CiAgICAgICAgICB2ZXJ0aWNlc1syICogY10gPSBjeDsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGE7CiAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBiOwogICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYzsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmVydGljZXMsCiAgICAgICAgdHJpYW5nbGVzCiAgICAgIH07CiAgICB9CiAgfQoKICAvLyBodHRwczovL2dpdGh1Yi5jb20vQ2VzaXVtR1MvY2VzaXVtL2Jsb2IvMS43Ni9Tb3VyY2UvV29ya2Vyc0VTNi9jcmVhdGVWZXJ0aWNlc0Zyb21RdWFudGl6ZWRUZXJyYWluTWVzaC5qcwoKICB2YXIgbWFydGluaSA9IG51bGw7CiAgZnVuY3Rpb24gZGVjb2RlVGVycmFpbihwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICB2YXIgX21hcnRpbmk7CiAgICB2YXIgaW1hZ2VEYXRhID0gcGFyYW1ldGVycy5pbWFnZURhdGEsCiAgICAgIF9wYXJhbWV0ZXJzJHRpbGVTaXplID0gcGFyYW1ldGVycy50aWxlU2l6ZSwKICAgICAgdGlsZVNpemUgPSBfcGFyYW1ldGVycyR0aWxlU2l6ZSA9PT0gdm9pZCAwID8gMjU2IDogX3BhcmFtZXRlcnMkdGlsZVNpemUsCiAgICAgIGVycm9yTGV2ZWwgPSBwYXJhbWV0ZXJzLmVycm9yTGV2ZWwsCiAgICAgIGludGVydmFsID0gcGFyYW1ldGVycy5pbnRlcnZhbCwKICAgICAgb2Zmc2V0ID0gcGFyYW1ldGVycy5vZmZzZXQ7CiAgICB2YXIgcGl4ZWxzID0gbmRhcnJheShuZXcgVWludDhBcnJheShpbWFnZURhdGEpLCBbdGlsZVNpemUsIHRpbGVTaXplLCA0XSwgWzQsIDQgKiB0aWxlU2l6ZSwgMV0sIDApOwoKICAgIC8vIFRpbGUgc2l6ZSBtdXN0IGJlIG1haW50YWluZWQgdGhyb3VnaCB0aGUgbGlmZSBvZiB0aGUgd29ya2VyCiAgICAoX21hcnRpbmkgPSBtYXJ0aW5pKSAhPT0gbnVsbCAmJiBfbWFydGluaSAhPT0gdm9pZCAwID8gX21hcnRpbmkgOiBtYXJ0aW5pID0gbmV3IE1hcnRpbmkodGlsZVNpemUgKyAxKTsKICAgIHZhciB0ZXJyYWluID0gbWFwYm94VGVycmFpblRvR3JpZChwaXhlbHMsIGludGVydmFsLCBvZmZzZXQpOwogICAgdmFyIHRpbGUgPSBtYXJ0aW5pLmNyZWF0ZVRpbGUodGVycmFpbik7CgogICAgLy8gZ2V0IGEgbWVzaCAodmVydGljZXMgYW5kIHRyaWFuZ2xlcyBpbmRpY2VzKSBmb3IgYSAxMG0gZXJyb3IKICAgIHZhciBtZXNoID0gdGlsZS5nZXRNZXNoKGVycm9yTGV2ZWwsIHBhcmFtZXRlcnMubWF4TGVuZ3RoKTsKICAgIHJldHVybiBjcmVhdGVRdWFudGl6ZWRNZXNoRGF0YSh0aWxlLCBtZXNoLCB0aWxlU2l6ZSk7CiAgfQogIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKG1zZykgewogICAgdmFyIF9tc2ckZGF0YSA9IG1zZy5kYXRhLAogICAgICBpZCA9IF9tc2ckZGF0YS5pZCwKICAgICAgcGF5bG9hZCA9IF9tc2ckZGF0YS5wYXlsb2FkOwogICAgaWYgKGlkID09IG51bGwpIHJldHVybjsKICAgIHZhciBvYmplY3RzID0gW107CiAgICB2YXIgcmVzID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIHJlcyA9IGRlY29kZVRlcnJhaW4ocGF5bG9hZCk7CiAgICAgIG9iamVjdHMucHVzaChyZXMuaW5kaWNlcy5idWZmZXIpOwogICAgICBvYmplY3RzLnB1c2gocmVzLnF1YW50aXplZFZlcnRpY2VzLmJ1ZmZlcik7CiAgICAgIHNlbGYucG9zdE1lc3NhZ2UoewogICAgICAgIGlkOiBpZCwKICAgICAgICBwYXlsb2FkOiByZXMKICAgICAgfSwgb2JqZWN0cyk7CiAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIGVycjogZXJyLnRvU3RyaW5nKCkKICAgICAgfSk7CiAgICB9IGZpbmFsbHkgewogICAgICByZXMgPSBudWxsOwogICAgICBvYmplY3RzID0gbnVsbDsKICAgIH0KICB9OwoKICBleHBvcnRzLmRlY29kZVRlcnJhaW4gPSBkZWNvZGVUZXJyYWluOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pOwoKICByZXR1cm4gZXhwb3J0czsKCn0pKHt9KTsKCg==', null, false);
705
- /* eslint-enable */
706
-
707
- var resolves = {};
708
- var rejects = {};
709
- var globalMsgId = 0; // Activate calculation in the worker, returning a promise
710
- function sendMessage(_x, _x2, _x3) {
711
- return _sendMessage.apply(this, arguments);
712
- } // Handle incoming calculation result
713
- function _sendMessage() {
714
- _sendMessage = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(worker, payload, transferableObjects) {
715
- var msgId, msg;
716
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
717
- while (1) switch (_context2.prev = _context2.next) {
718
- case 0:
719
- msgId = globalMsgId++;
720
- msg = {
721
- id: msgId,
722
- payload: payload
723
- };
724
- return _context2.abrupt("return", new Promise(function (resolve, reject) {
725
- // save callbacks for later
726
- resolves[msgId] = resolve;
727
- rejects[msgId] = reject;
728
- worker.postMessage(msg, transferableObjects);
729
- }));
730
- case 3:
731
- case "end":
732
- return _context2.stop();
733
- }
734
- }, _callee2);
735
- }));
736
- return _sendMessage.apply(this, arguments);
737
- }
738
- function handleMessage(msg) {
739
- var _msg$data = msg.data,
740
- id = _msg$data.id,
741
- err = _msg$data.err,
742
- payload = _msg$data.payload;
743
- if (payload) {
744
- var resolve = resolves[id];
745
- if (resolve) {
746
- resolve(payload);
747
- }
748
- } else {
749
- // error condition
750
- var reject = rejects[id];
751
- if (reject) {
752
- if (err) {
753
- reject(err);
754
- } else {
755
- reject("Got nothing");
756
- }
757
- }
758
- }
759
-
760
- // purge used callbacks
761
- delete resolves[id];
762
- delete rejects[id];
763
- }
764
- var WorkerFarm = /*#__PURE__*/function () {
765
- function WorkerFarm() {
766
- _classCallCheck(this, WorkerFarm);
767
- this.worker = new WorkerFactory();
768
- this.worker.onmessage = handleMessage;
769
- }
770
- _createClass(WorkerFarm, [{
771
- key: "scheduleTask",
772
- value: function () {
773
- var _scheduleTask = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(params, transferableObjects) {
774
- return _regeneratorRuntime().wrap(function _callee$(_context) {
775
- while (1) switch (_context.prev = _context.next) {
776
- case 0:
777
- _context.next = 2;
778
- return sendMessage(this.worker, params, transferableObjects);
779
- case 2:
780
- return _context.abrupt("return", _context.sent);
781
- case 3:
782
- case "end":
783
- return _context.stop();
784
- }
785
- }, _callee, this);
786
- }));
787
- function scheduleTask(_x4, _x5) {
788
- return _scheduleTask.apply(this, arguments);
789
- }
790
- return scheduleTask;
791
- }()
792
- }]);
793
- return WorkerFarm;
794
- }();
795
-
796
- // We should save these
797
- //const canvas = new OffscreenCanvas(256, 256);
798
- //const ctx = canvas.getContext("2d");
799
-
800
- function mapboxTerrainToGrid(png, interval, offset) {
801
- var _interval, _offset;
647
+ /** Mapbox Terrain-RGB default decode function
648
+ * (r * 256 * 256) / 10 + (g * 256) / 10 + b / 10 - 10000
649
+ */
650
+ var defaultMapboxDecodeRgb = function defaultMapboxDecodeRgb(r, g, b, a) {
651
+ return r * 6553.6 + g * 25.6 + b * 0.1 - 10000;
652
+ };
653
+ function rgbTerrainToGrid(png, decodeRgb) {
802
654
  // maybe we should do this on the GPU using REGL?
803
655
  // but that would require GPU -> CPU -> GPU
804
656
  var gridSize = png.shape[0] + 1;
805
657
  var terrain = new Float32Array(gridSize * gridSize);
806
658
  var tileSize = png.shape[0];
807
- interval = (_interval = interval) !== null && _interval !== void 0 ? _interval : 0.1;
808
- offset = (_offset = offset) !== null && _offset !== void 0 ? _offset : -10000;
659
+ var decode = decodeRgb !== null && decodeRgb !== void 0 ? decodeRgb : defaultMapboxDecodeRgb;
809
660
 
810
661
  // decode terrain values
811
662
  for (var y = 0; y < tileSize; y++) {
812
663
  for (var x = 0; x < tileSize; x++) {
813
664
  var yc = y;
814
- var r = png.get(x, yc, 0);
815
- var g = png.get(x, yc, 1);
816
- var b = png.get(x, yc, 2);
817
- terrain[y * gridSize + x] = r * 256 * 256 * interval + g * 256.0 * interval + b * interval + offset;
665
+ var _r = png.get(x, yc, 0);
666
+ var _g = png.get(x, yc, 1);
667
+ var _b = png.get(x, yc, 2);
668
+ var _a = png.get(x, yc, 3);
669
+ terrain[y * gridSize + x] = decode(_r, _g, _b, _a);
818
670
  }
819
671
  }
820
672
  // backfill right and bottom borders
@@ -826,6 +678,42 @@ function mapboxTerrainToGrid(png, interval, offset) {
826
678
  }
827
679
  return terrain;
828
680
  }
681
+ function subsetByWindow(array, window, augmented) {
682
+ var sz = Math.sqrt(array.length);
683
+ var x0 = window.x0;
684
+ var x1 = window.x1;
685
+ var y0 = window.y0;
686
+ var y1 = window.y1;
687
+ var aug = augmented ? 1 : 0;
688
+ var n = Math.floor(x1 - x0) + aug;
689
+ var m = Math.floor(y1 - y0) + aug;
690
+ var result = new Float32Array(n * m);
691
+ for (var i = 0; i < m; i++) {
692
+ for (var j = 0; j < n; j++) {
693
+ result[i * n + j] = array[(i + y0) * sz + j + x0];
694
+ }
695
+ }
696
+ return result;
697
+ }
698
+ function testMeshData() {
699
+ return {
700
+ minimumHeight: -100,
701
+ maximumHeight: 2101,
702
+ quantizedVertices: new Uint16Array([
703
+ // order is SW NW SE NE
704
+ // longitude
705
+ 0, 0, 32767, 32767,
706
+ // latitude
707
+ 0, 32767, 0, 32767,
708
+ // heights
709
+ 16384, 0, 32767, 16384]),
710
+ indices: new Uint16Array([0, 3, 1, 0, 2, 3]),
711
+ westIndices: [0, 1],
712
+ southIndices: [0, 1],
713
+ eastIndices: [2, 3],
714
+ northIndices: [1, 3]
715
+ };
716
+ }
829
717
  function _emptyMesh(n) {
830
718
  n = Math.max(n, 2);
831
719
  var nTriangles = Math.pow(n - 1, 2) * 2;
@@ -886,7 +774,14 @@ function emptyMesh(n) {
886
774
  return result;
887
775
  }
888
776
  }
889
- function createQuantizedMeshData(tile, mesh, tileSize) {
777
+
778
+ /** Terrain workers should return a quantized mesh */
779
+
780
+ function createQuantizedMeshData(tile, mesh, tileSize, terrain) {
781
+ /** Terrain is passed through so we can keep track of it
782
+ * for overscaled tiles
783
+ */
784
+
890
785
  var xvals = [];
891
786
  var yvals = [];
892
787
  var heightMeters = [];
@@ -897,6 +792,9 @@ function createQuantizedMeshData(tile, mesh, tileSize) {
897
792
  var minimumHeight = Infinity;
898
793
  var maximumHeight = -Infinity;
899
794
  var scalar = 32768.0 / tileSize;
795
+
796
+ // There appears to be a problem with the x/y indexing when using 512x512 tiles
797
+ // This may be solved by increasing the minumumErrorLevel in the terrain provider
900
798
  for (var ix = 0; ix < mesh.vertices.length / 2; ix++) {
901
799
  var vertexIx = ix;
902
800
  var px = mesh.vertices[ix * 2];
@@ -917,10 +815,10 @@ function createQuantizedMeshData(tile, mesh, tileSize) {
917
815
  var heightRange = maximumHeight - minimumHeight;
918
816
  var heights = heightMeters.map(function (d) {
919
817
  if (heightRange < 1) return 0;
920
- return (d - minimumHeight) * (32767.0 / heightRange);
818
+ return (d - minimumHeight) * (32768.0 / heightRange);
921
819
  });
922
820
  var triangles = new Uint16Array(mesh.triangles);
923
- var quantizedVertices = new Uint16Array( //verts
821
+ var quantizedVertices = new Uint16Array(//verts
924
822
  [].concat(xvals, yvals, _toConsumableArray(heights)));
925
823
 
926
824
  // SE NW NE
@@ -934,250 +832,469 @@ function createQuantizedMeshData(tile, mesh, tileSize) {
934
832
  westIndices: westIndices,
935
833
  southIndices: southIndices,
936
834
  eastIndices: eastIndices,
937
- northIndices: northIndices
835
+ northIndices: northIndices,
836
+ quantizedHeights: terrain
938
837
  };
939
838
  }
940
839
 
941
- class Martini {
942
- constructor(gridSize = 257) {
943
- this.gridSize = gridSize;
944
- const tileSize = gridSize - 1;
945
- if (tileSize & tileSize - 1) throw new Error(`Expected grid size to be 2^n+1, got ${gridSize}.`);
946
- this.numTriangles = tileSize * tileSize * 2 - 2;
947
- this.numParentTriangles = this.numTriangles - tileSize * tileSize;
948
- this.indices = new Uint32Array(this.gridSize * this.gridSize);
949
-
950
- // coordinates for all possible triangles in an RTIN tile
951
- this.coords = new Uint16Array(this.numTriangles * 4);
952
-
953
- // get triangle coordinates from its index in an implicit binary tree
954
- for (let i = 0; i < this.numTriangles; i++) {
955
- let id = i + 2;
956
- let ax = 0,
957
- ay = 0,
958
- bx = 0,
959
- by = 0,
960
- cx = 0,
961
- cy = 0;
962
- if (id & 1) {
963
- bx = by = cx = tileSize; // bottom-left triangle
840
+ var resolves = {};
841
+ var rejects = {};
842
+ var globalMsgId = 0; // Activate calculation in the worker, returning a promise
843
+ function sendMessage(_x, _x2, _x3) {
844
+ return _sendMessage.apply(this, arguments);
845
+ } // Handle incoming calculation result
846
+ function _sendMessage() {
847
+ _sendMessage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(worker, payload, transferableObjects) {
848
+ var msgId, msg;
849
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
850
+ while (1) switch (_context3.prev = _context3.next) {
851
+ case 0:
852
+ msgId = globalMsgId++;
853
+ msg = {
854
+ id: msgId,
855
+ payload: payload
856
+ };
857
+ return _context3.abrupt("return", new Promise(function (resolve, reject) {
858
+ // save callbacks for later
859
+ resolves[msgId] = resolve;
860
+ rejects[msgId] = reject;
861
+ worker.postMessage(msg, transferableObjects);
862
+ }));
863
+ case 3:
864
+ case "end":
865
+ return _context3.stop();
866
+ }
867
+ }, _callee3);
868
+ }));
869
+ return _sendMessage.apply(this, arguments);
870
+ }
871
+ function handleMessage(msg) {
872
+ var _msg$data = msg.data,
873
+ id = _msg$data.id,
874
+ err = _msg$data.err,
875
+ payload = _msg$data.payload;
876
+ if (payload) {
877
+ var resolve = resolves[id];
878
+ if (resolve) {
879
+ resolve(payload);
880
+ }
881
+ } else {
882
+ // error condition
883
+ var reject = rejects[id];
884
+ if (reject) {
885
+ if (err) {
886
+ reject(err);
964
887
  } else {
965
- ax = ay = cy = tileSize; // top-right triangle
888
+ reject("Got nothing");
966
889
  }
890
+ }
891
+ }
967
892
 
968
- while ((id >>= 1) > 1) {
969
- const mx = ax + bx >> 1;
970
- const my = ay + by >> 1;
971
- if (id & 1) {
972
- // left half
973
- bx = ax;
974
- by = ay;
975
- ax = cx;
976
- ay = cy;
977
- } else {
978
- // right half
979
- ax = bx;
980
- ay = by;
981
- bx = cx;
982
- by = cy;
983
- }
984
- cx = mx;
985
- cy = my;
893
+ // purge used callbacks
894
+ delete resolves[id];
895
+ delete rejects[id];
896
+ }
897
+ var WorkerFarm = /*#__PURE__*/function () {
898
+ function WorkerFarm(opts) {
899
+ _classCallCheck(this, WorkerFarm);
900
+ _defineProperty(this, "inProgressWorkers", 0);
901
+ _defineProperty(this, "maxWorkers", 5);
902
+ _defineProperty(this, "processingQueue", []);
903
+ this.worker = opts.worker;
904
+ this.worker.onmessage = handleMessage;
905
+ }
906
+ return _createClass(WorkerFarm, [{
907
+ key: "scheduleTask",
908
+ value: function () {
909
+ var _scheduleTask = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(params, transferableObjects) {
910
+ var res;
911
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
912
+ while (1) switch (_context.prev = _context.next) {
913
+ case 0:
914
+ _context.next = 2;
915
+ return sendMessage(this.worker, params, transferableObjects);
916
+ case 2:
917
+ res = _context.sent;
918
+ this.releaseWorker();
919
+ return _context.abrupt("return", res);
920
+ case 5:
921
+ case "end":
922
+ return _context.stop();
923
+ }
924
+ }, _callee, this);
925
+ }));
926
+ function scheduleTask(_x4, _x5) {
927
+ return _scheduleTask.apply(this, arguments);
928
+ }
929
+ return scheduleTask;
930
+ }()
931
+ }, {
932
+ key: "holdForAvailableWorker",
933
+ value: function () {
934
+ var _holdForAvailableWorker = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
935
+ var _this = this;
936
+ var resultPromise;
937
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
938
+ while (1) switch (_context2.prev = _context2.next) {
939
+ case 0:
940
+ if (this.inProgressWorkers > this.maxWorkers) {
941
+ resultPromise = new Promise(function (resolve, reject) {
942
+ _this.processingQueue.push(resolve);
943
+ });
944
+ } else {
945
+ resultPromise = Promise.resolve(null);
946
+ }
947
+ _context2.next = 3;
948
+ return resultPromise;
949
+ case 3:
950
+ this.inProgressWorkers += 1;
951
+ case 4:
952
+ case "end":
953
+ return _context2.stop();
954
+ }
955
+ }, _callee2, this);
956
+ }));
957
+ function holdForAvailableWorker() {
958
+ return _holdForAvailableWorker.apply(this, arguments);
959
+ }
960
+ return holdForAvailableWorker;
961
+ }()
962
+ }, {
963
+ key: "releaseWorker",
964
+ value: function releaseWorker() {
965
+ this.inProgressWorkers -= 1;
966
+ if (this.processingQueue.length > 0) {
967
+ this.processingQueue.shift()();
986
968
  }
987
- const k = i * 4;
988
- this.coords[k + 0] = ax;
989
- this.coords[k + 1] = ay;
990
- this.coords[k + 2] = bx;
991
- this.coords[k + 3] = by;
992
969
  }
970
+ }]);
971
+ }();
972
+
973
+ var DefaultTerrainDecoder = /*#__PURE__*/function () {
974
+ function DefaultTerrainDecoder() {
975
+ _classCallCheck(this, DefaultTerrainDecoder);
976
+ _defineProperty(this, "inProgress", 0);
977
+ _defineProperty(this, "maxRequests", 2);
993
978
  }
994
- createTile(terrain) {
995
- return new Tile(terrain, this);
979
+ return _createClass(DefaultTerrainDecoder, [{
980
+ key: "requestTileGeometry",
981
+ value: function requestTileGeometry(coords, processFunction) {
982
+ var _this = this;
983
+ if (this.inProgress > this.maxRequests) return undefined;
984
+ this.inProgress += 1;
985
+ return processFunction(coords)["finally"](function () {
986
+ _this.inProgress -= 1;
987
+ });
988
+ }
989
+ }, {
990
+ key: "decodeTerrain",
991
+ value: function decodeTerrain(params, data) {
992
+ return Promise.resolve(null);
993
+ }
994
+ }]);
995
+ }();
996
+ var WorkerFarmTerrainDecoder = /*#__PURE__*/function (_DefaultTerrainDecode) {
997
+ function WorkerFarmTerrainDecoder(opts) {
998
+ var _opts$maxWorkers;
999
+ var _this2;
1000
+ _classCallCheck(this, WorkerFarmTerrainDecoder);
1001
+ _this2 = _callSuper(this, WorkerFarmTerrainDecoder);
1002
+ _this2.farm = new WorkerFarm({
1003
+ worker: opts.worker
1004
+ });
1005
+ _this2.maxRequests = (_opts$maxWorkers = opts.maxWorkers) !== null && _opts$maxWorkers !== void 0 ? _opts$maxWorkers : 5;
1006
+ return _this2;
996
1007
  }
1008
+ _inherits(WorkerFarmTerrainDecoder, _DefaultTerrainDecode);
1009
+ return _createClass(WorkerFarmTerrainDecoder, [{
1010
+ key: "decodeTerrain",
1011
+ value: function decodeTerrain(params, data) {
1012
+ return this.farm.scheduleTask(params, [data]);
1013
+ }
1014
+ }]);
1015
+ }(DefaultTerrainDecoder);
1016
+
1017
+ function decodeBase64(base64, enableUnicode) {
1018
+ var binaryString = atob(base64);
1019
+ if (enableUnicode) {
1020
+ var binaryView = new Uint8Array(binaryString.length);
1021
+ for (var i = 0, n = binaryString.length; i < n; ++i) {
1022
+ binaryView[i] = binaryString.charCodeAt(i);
1023
+ }
1024
+ const decoder = new TextDecoder("utf-16le");
1025
+ return decoder.decode(new Uint16Array(binaryView.buffer));
1026
+ }
1027
+ return binaryString;
1028
+ }
1029
+
1030
+ function createURL(base64, sourcemapArg, enableUnicodeArg) {
1031
+ var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
1032
+ var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
1033
+ var source = decodeBase64(base64, enableUnicode);
1034
+ var start = source.indexOf('\n', 10) + 1;
1035
+ var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
1036
+ var blob = new Blob([body], { type: 'application/javascript' });
1037
+ return URL.createObjectURL(blob);
997
1038
  }
998
- class Tile {
999
- constructor(terrain, martini) {
1000
- const size = martini.gridSize;
1001
- if (terrain.length !== size * size) throw new Error(`Expected terrain data of length ${size * size} (${size} x ${size}), got ${terrain.length}.`);
1002
- this.terrain = terrain;
1003
- this.martini = martini;
1004
- this.errors = new Float32Array(terrain.length);
1005
- this.update();
1039
+
1040
+ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
1041
+ var url;
1042
+ return function WorkerFactory(options) {
1043
+ url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
1044
+ return new Worker(url, options);
1045
+ };
1046
+ }
1047
+
1048
+ var WorkerFactory$1 = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkociwgYSkgewogICAgKG51bGwgPT0gYSB8fCBhID4gci5sZW5ndGgpICYmIChhID0gci5sZW5ndGgpOwogICAgZm9yICh2YXIgZSA9IDAsIG4gPSBBcnJheShhKTsgZSA8IGE7IGUrKykgbltlXSA9IHJbZV07CiAgICByZXR1cm4gbjsKICB9CiAgZnVuY3Rpb24gX2FycmF5V2l0aG91dEhvbGVzKHIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KHIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkocik7CiAgfQogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkocikgewogICAgaWYgKCJ1bmRlZmluZWQiICE9IHR5cGVvZiBTeW1ib2wgJiYgbnVsbCAhPSByW1N5bWJvbC5pdGVyYXRvcl0gfHwgbnVsbCAhPSByWyJAQGl0ZXJhdG9yIl0pIHJldHVybiBBcnJheS5mcm9tKHIpOwogIH0KICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7CiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cbkluIG9yZGVyIHRvIGJlIGl0ZXJhYmxlLCBub24tYXJyYXkgb2JqZWN0cyBtdXN0IGhhdmUgYSBbU3ltYm9sLml0ZXJhdG9yXSgpIG1ldGhvZC4iKTsKICB9CiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KHIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMocikgfHwgX2l0ZXJhYmxlVG9BcnJheShyKSB8fCBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkocikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShyLCBhKSB7CiAgICBpZiAocikgewogICAgICBpZiAoInN0cmluZyIgPT0gdHlwZW9mIHIpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShyLCBhKTsKICAgICAgdmFyIHQgPSB7fS50b1N0cmluZy5jYWxsKHIpLnNsaWNlKDgsIC0xKTsKICAgICAgcmV0dXJuICJPYmplY3QiID09PSB0ICYmIHIuY29uc3RydWN0b3IgJiYgKHQgPSByLmNvbnN0cnVjdG9yLm5hbWUpLCAiTWFwIiA9PT0gdCB8fCAiU2V0IiA9PT0gdCA/IEFycmF5LmZyb20ocikgOiAiQXJndW1lbnRzIiA9PT0gdCB8fCAvXig/OlVpfEkpbnQoPzo4fDE2fDMyKSg/OkNsYW1wZWQpP0FycmF5JC8udGVzdCh0KSA/IF9hcnJheUxpa2VUb0FycmF5KHIsIGEpIDogdm9pZCAwOwogICAgfQogIH0KCiAgLyoqIFRlcnJhaW4gd29ya2VycyBzaG91bGQgcmV0dXJuIGEgcXVhbnRpemVkIG1lc2ggKi8KCiAgZnVuY3Rpb24gY3JlYXRlUXVhbnRpemVkTWVzaERhdGEodGlsZSwgbWVzaCwgdGlsZVNpemUsIHRlcnJhaW4pIHsKICAgIC8qKiBUZXJyYWluIGlzIHBhc3NlZCB0aHJvdWdoIHNvIHdlIGNhbiBrZWVwIHRyYWNrIG9mIGl0CiAgICAgKiBmb3Igb3ZlcnNjYWxlZCB0aWxlcwogICAgICovCgogICAgdmFyIHh2YWxzID0gW107CiAgICB2YXIgeXZhbHMgPSBbXTsKICAgIHZhciBoZWlnaHRNZXRlcnMgPSBbXTsKICAgIHZhciBub3J0aEluZGljZXMgPSBbXTsKICAgIHZhciBzb3V0aEluZGljZXMgPSBbXTsKICAgIHZhciBlYXN0SW5kaWNlcyA9IFtdOwogICAgdmFyIHdlc3RJbmRpY2VzID0gW107CiAgICB2YXIgbWluaW11bUhlaWdodCA9IEluZmluaXR5OwogICAgdmFyIG1heGltdW1IZWlnaHQgPSAtSW5maW5pdHk7CiAgICB2YXIgc2NhbGFyID0gMzI3NjguMCAvIHRpbGVTaXplOwoKICAgIC8vIFRoZXJlIGFwcGVhcnMgdG8gYmUgYSBwcm9ibGVtIHdpdGggdGhlIHgveSBpbmRleGluZyB3aGVuIHVzaW5nIDUxMng1MTIgdGlsZXMKICAgIC8vIFRoaXMgbWF5IGJlIHNvbHZlZCBieSBpbmNyZWFzaW5nIHRoZSBtaW51bXVtRXJyb3JMZXZlbCBpbiB0aGUgdGVycmFpbiBwcm92aWRlcgogICAgZm9yICh2YXIgaXggPSAwOyBpeCA8IG1lc2gudmVydGljZXMubGVuZ3RoIC8gMjsgaXgrKykgewogICAgICB2YXIgdmVydGV4SXggPSBpeDsKICAgICAgdmFyIHB4ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDJdOwogICAgICB2YXIgcHkgPSBtZXNoLnZlcnRpY2VzW2l4ICogMiArIDFdOwogICAgICB2YXIgaGVpZ2h0ID0gdGlsZS50ZXJyYWluW3B5ICogKHRpbGVTaXplICsgMSkgKyBweF07CiAgICAgIGlmIChoZWlnaHQgPiBtYXhpbXVtSGVpZ2h0KSBtYXhpbXVtSGVpZ2h0ID0gaGVpZ2h0OwogICAgICBpZiAoaGVpZ2h0IDwgbWluaW11bUhlaWdodCkgbWluaW11bUhlaWdodCA9IGhlaWdodDsKICAgICAgaGVpZ2h0TWV0ZXJzLnB1c2goaGVpZ2h0KTsKICAgICAgaWYgKHB5ID09IDApIG5vcnRoSW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB5ID09IHRpbGVTaXplKSBzb3V0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSAwKSB3ZXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB4ID09IHRpbGVTaXplKSBlYXN0SW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgdmFyIHh2ID0gcHggKiBzY2FsYXI7CiAgICAgIHZhciB5diA9ICh0aWxlU2l6ZSAtIHB5KSAqIHNjYWxhcjsKICAgICAgeHZhbHMucHVzaCh4dik7CiAgICAgIHl2YWxzLnB1c2goeXYpOwogICAgfQogICAgdmFyIGhlaWdodFJhbmdlID0gbWF4aW11bUhlaWdodCAtIG1pbmltdW1IZWlnaHQ7CiAgICB2YXIgaGVpZ2h0cyA9IGhlaWdodE1ldGVycy5tYXAoZnVuY3Rpb24gKGQpIHsKICAgICAgaWYgKGhlaWdodFJhbmdlIDwgMSkgcmV0dXJuIDA7CiAgICAgIHJldHVybiAoZCAtIG1pbmltdW1IZWlnaHQpICogKDMyNzY4LjAgLyBoZWlnaHRSYW5nZSk7CiAgICB9KTsKICAgIHZhciB0cmlhbmdsZXMgPSBuZXcgVWludDE2QXJyYXkobWVzaC50cmlhbmdsZXMpOwogICAgdmFyIHF1YW50aXplZFZlcnRpY2VzID0gbmV3IFVpbnQxNkFycmF5KC8vdmVydHMKICAgIFtdLmNvbmNhdCh4dmFscywgeXZhbHMsIF90b0NvbnN1bWFibGVBcnJheShoZWlnaHRzKSkpOwoKICAgIC8vIFNFIE5XIE5FCiAgICAvLyBORSBOVyBTRQoKICAgIHJldHVybiB7CiAgICAgIG1pbmltdW1IZWlnaHQ6IG1pbmltdW1IZWlnaHQsCiAgICAgIG1heGltdW1IZWlnaHQ6IG1heGltdW1IZWlnaHQsCiAgICAgIHF1YW50aXplZFZlcnRpY2VzOiBxdWFudGl6ZWRWZXJ0aWNlcywKICAgICAgaW5kaWNlczogdHJpYW5nbGVzLAogICAgICB3ZXN0SW5kaWNlczogd2VzdEluZGljZXMsCiAgICAgIHNvdXRoSW5kaWNlczogc291dGhJbmRpY2VzLAogICAgICBlYXN0SW5kaWNlczogZWFzdEluZGljZXMsCiAgICAgIG5vcnRoSW5kaWNlczogbm9ydGhJbmRpY2VzLAogICAgICBxdWFudGl6ZWRIZWlnaHRzOiB0ZXJyYWluCiAgICB9OwogIH0KCiAgY2xhc3MgTWFydGluaSB7CiAgICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgICAgICB0aGlzLmdyaWRTaXplID0gZ3JpZFNpemU7CiAgICAgICAgICBjb25zdCB0aWxlU2l6ZSA9IGdyaWRTaXplIC0gMTsKICAgICAgICAgIGlmICh0aWxlU2l6ZSAmICh0aWxlU2l6ZSAtIDEpKSB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICAgYEV4cGVjdGVkIGdyaWQgc2l6ZSB0byBiZSAyXm4rMSwgZ290ICR7Z3JpZFNpemV9LmApOwoKICAgICAgICAgIHRoaXMubnVtVHJpYW5nbGVzID0gdGlsZVNpemUgKiB0aWxlU2l6ZSAqIDIgLSAyOwogICAgICAgICAgdGhpcy5udW1QYXJlbnRUcmlhbmdsZXMgPSB0aGlzLm51bVRyaWFuZ2xlcyAtIHRpbGVTaXplICogdGlsZVNpemU7CgogICAgICAgICAgdGhpcy5pbmRpY2VzID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuZ3JpZFNpemUgKiB0aGlzLmdyaWRTaXplKTsKCiAgICAgICAgICAvLyBjb29yZGluYXRlcyBmb3IgYWxsIHBvc3NpYmxlIHRyaWFuZ2xlcyBpbiBhbiBSVElOIHRpbGUKICAgICAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7CgogICAgICAgICAgLy8gZ2V0IHRyaWFuZ2xlIGNvb3JkaW5hdGVzIGZyb20gaXRzIGluZGV4IGluIGFuIGltcGxpY2l0IGJpbmFyeSB0cmVlCiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubnVtVHJpYW5nbGVzOyBpKyspIHsKICAgICAgICAgICAgICBsZXQgaWQgPSBpICsgMjsKICAgICAgICAgICAgICBsZXQgYXggPSAwLCBheSA9IDAsIGJ4ID0gMCwgYnkgPSAwLCBjeCA9IDAsIGN5ID0gMDsKICAgICAgICAgICAgICBpZiAoaWQgJiAxKSB7CiAgICAgICAgICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGF4ID0gYXkgPSBjeSA9IHRpbGVTaXplOyAvLyB0b3AtcmlnaHQgdHJpYW5nbGUKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgd2hpbGUgKChpZCA+Pj0gMSkgPiAxKSB7CiAgICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICAgIGNvbnN0IG15ID0gKGF5ICsgYnkpID4+IDE7CgogICAgICAgICAgICAgICAgICBpZiAoaWQgJiAxKSB7IC8vIGxlZnQgaGFsZgogICAgICAgICAgICAgICAgICAgICAgYnggPSBheDsgYnkgPSBheTsKICAgICAgICAgICAgICAgICAgICAgIGF4ID0gY3g7IGF5ID0gY3k7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIHJpZ2h0IGhhbGYKICAgICAgICAgICAgICAgICAgICAgIGF4ID0gYng7IGF5ID0gYnk7CiAgICAgICAgICAgICAgICAgICAgICBieCA9IGN4OyBieSA9IGN5OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGN4ID0gbXg7IGN5ID0gbXk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMF0gPSBheDsKICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMl0gPSBieDsKICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgM10gPSBieTsKICAgICAgICAgIH0KICAgICAgfQoKICAgICAgY3JlYXRlVGlsZSh0ZXJyYWluKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICAgIH0KICB9CgogIGNsYXNzIFRpbGUgewogICAgICBjb25zdHJ1Y3Rvcih0ZXJyYWluLCBtYXJ0aW5pKSB7CiAgICAgICAgICBjb25zdCBzaXplID0gbWFydGluaS5ncmlkU2l6ZTsKICAgICAgICAgIGlmICh0ZXJyYWluLmxlbmd0aCAhPT0gc2l6ZSAqIHNpemUpIHRocm93IG5ldyBFcnJvcigKICAgICAgICAgICAgICBgRXhwZWN0ZWQgdGVycmFpbiBkYXRhIG9mIGxlbmd0aCAke3NpemUgKiBzaXplfSAoJHtzaXplfSB4ICR7c2l6ZX0pLCBnb3QgJHt0ZXJyYWluLmxlbmd0aH0uYCk7CgogICAgICAgICAgdGhpcy50ZXJyYWluID0gdGVycmFpbjsKICAgICAgICAgIHRoaXMubWFydGluaSA9IG1hcnRpbmk7CiAgICAgICAgICB0aGlzLmVycm9ycyA9IG5ldyBGbG9hdDMyQXJyYXkodGVycmFpbi5sZW5ndGgpOwogICAgICAgICAgdGhpcy51cGRhdGUoKTsKICAgICAgfQoKICAgICAgdXBkYXRlKCkgewogICAgICAgICAgY29uc3Qge251bVRyaWFuZ2xlcywgbnVtUGFyZW50VHJpYW5nbGVzLCBjb29yZHMsIGdyaWRTaXplOiBzaXplfSA9IHRoaXMubWFydGluaTsKICAgICAgICAgIGNvbnN0IHt0ZXJyYWluLCBlcnJvcnN9ID0gdGhpczsKCiAgICAgICAgICAvLyBpdGVyYXRlIG92ZXIgYWxsIHBvc3NpYmxlIHRyaWFuZ2xlcywgc3RhcnRpbmcgZnJvbSB0aGUgc21hbGxlc3QgbGV2ZWwKICAgICAgICAgIGZvciAobGV0IGkgPSBudW1UcmlhbmdsZXMgLSAxOyBpID49IDA7IGktLSkgewogICAgICAgICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICAgICAgICBjb25zdCBheCA9IGNvb3Jkc1trICsgMF07CiAgICAgICAgICAgICAgY29uc3QgYXkgPSBjb29yZHNbayArIDFdOwogICAgICAgICAgICAgIGNvbnN0IGJ4ID0gY29vcmRzW2sgKyAyXTsKICAgICAgICAgICAgICBjb25zdCBieSA9IGNvb3Jkc1trICsgM107CiAgICAgICAgICAgICAgY29uc3QgbXggPSAoYXggKyBieCkgPj4gMTsKICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwogICAgICAgICAgICAgIGNvbnN0IGN4ID0gbXggKyBteSAtIGF5OwogICAgICAgICAgICAgIGNvbnN0IGN5ID0gbXkgKyBheCAtIG14OwoKICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQogICAgICAgICAgICAgIGNvbnN0IGludGVycG9sYXRlZEhlaWdodCA9ICh0ZXJyYWluW2F5ICogc2l6ZSArIGF4XSArIHRlcnJhaW5bYnkgKiBzaXplICsgYnhdKSAvIDI7CiAgICAgICAgICAgICAgY29uc3QgbWlkZGxlSW5kZXggPSBteSAqIHNpemUgKyBteDsKICAgICAgICAgICAgICBjb25zdCBtaWRkbGVFcnJvciA9IE1hdGguYWJzKGludGVycG9sYXRlZEhlaWdodCAtIHRlcnJhaW5bbWlkZGxlSW5kZXhdKTsKCiAgICAgICAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIG1pZGRsZUVycm9yKTsKCiAgICAgICAgICAgICAgaWYgKGkgPCBudW1QYXJlbnRUcmlhbmdsZXMpIHsgLy8gYmlnZ2VyIHRyaWFuZ2xlczsgYWNjdW11bGF0ZSBlcnJvciB3aXRoIGNoaWxkcmVuCiAgICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRDaGlsZEluZGV4ID0gKChheSArIGN5KSA+PiAxKSAqIHNpemUgKyAoKGF4ICsgY3gpID4+IDEpOwogICAgICAgICAgICAgICAgICBjb25zdCByaWdodENoaWxkSW5kZXggPSAoKGJ5ICsgY3kpID4+IDEpICogc2l6ZSArICgoYnggKyBjeCkgPj4gMSk7CiAgICAgICAgICAgICAgICAgIGVycm9yc1ttaWRkbGVJbmRleF0gPSBNYXRoLm1heChlcnJvcnNbbWlkZGxlSW5kZXhdLCBlcnJvcnNbbGVmdENoaWxkSW5kZXhdLCBlcnJvcnNbcmlnaHRDaGlsZEluZGV4XSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICB9CgogICAgICBnZXRNZXNoKG1heEVycm9yID0gMCwgbWF4TGVuZ3RoID0gbnVsbCkgewogICAgICAgICAgY29uc3Qge2dyaWRTaXplOiBzaXplLCBpbmRpY2VzfSA9IHRoaXMubWFydGluaTsKICAgICAgICAgIGNvbnN0IHtlcnJvcnN9ID0gdGhpczsKICAgICAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgICAgICBsZXQgbnVtVHJpYW5nbGVzID0gMDsKICAgICAgICAgIGNvbnN0IG1heCA9IHNpemUgLSAxOwoKICAgICAgICAgIC8vIFRoZSBtYXhMZW5ndGggcGFyYW1ldGVyIHdpbGwgY2F1c2UgdHJpYW5nbGVzIHRvIGJlIGdlbmVyYXRlZCB1bnRpbCB0aGUgbGVncyBhcmUgYmVsb3cgdGhpcyBsZW5ndGgKICAgICAgICAgIC8vIEl0IGlzIG1lYW50IHRvIHN1cHBvcnQgY2FzZXMgd2hlcmUgYSBjZXJ0YWluIG1lc2ggZGVuc2l0eSBpcyByZXF1aXJlZCB0byBkbyBzcGhlcmljYWwgbWF0aCBvbiBkaWdpdGFsIGdsb2JlcwogICAgICAgICAgY29uc3QgbWF4U2NhbGUgPSBtYXhMZW5ndGggfHwgc2l6ZTsKCiAgICAgICAgICAvLyB1c2UgYW4gaW5kZXggZ3JpZCB0byBrZWVwIHRyYWNrIG9mIHZlcnRpY2VzIHRoYXQgd2VyZSBhbHJlYWR5IHVzZWQgdG8gYXZvaWQgZHVwbGljYXRpb24KICAgICAgICAgIGluZGljZXMuZmlsbCgwKTsKCiAgICAgICAgICAvLyByZXRyaWV2ZSBtZXNoIGluIHR3byBzdGFnZXMgdGhhdCBib3RoIHRyYXZlcnNlIHRoZSBlcnJvciBtYXA6CiAgICAgICAgICAvLyAtIGNvdW50RWxlbWVudHM6IGZpbmQgdXNlZCB2ZXJ0aWNlcyAoYW5kIGFzc2lnbiBlYWNoIGFuIGluZGV4KSwgYW5kIGNvdW50IHRyaWFuZ2xlcyAoZm9yIG1pbmltdW0gYWxsb2NhdGlvbikKICAgICAgICAgIC8vIC0gcHJvY2Vzc1RyaWFuZ2xlOiBmaWxsIHRoZSBhbGxvY2F0ZWQgdmVydGljZXMgJiB0cmlhbmdsZXMgdHlwZWQgYXJyYXlzCgogICAgICAgICAgZnVuY3Rpb24gY291bnRFbGVtZW50cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgICAgICAgY29uc3QgbXggPSAoYXggKyBieCkgPj4gMTsKICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwogICAgICAgICAgICAgIGlmICgobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IpIHx8IGxlZ0xlbmd0aCA+IG1heFNjYWxlKSB7CiAgICAgICAgICAgICAgICAgIGNvdW50RWxlbWVudHMoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICAgICAgICAgIGNvdW50RWxlbWVudHMoYngsIGJ5LCBjeCwgY3ksIG14LCBteSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgaW5kaWNlc1theSAqIHNpemUgKyBheF0gPSBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgICAgICAgICBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSA9IGluZGljZXNbYnkgKiBzaXplICsgYnhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgICAgICAgICAgbnVtVHJpYW5nbGVzKys7CiAgICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY291bnRFbGVtZW50cygwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgICAgIGNvdW50RWxlbWVudHMobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CgogICAgICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgICAgIGNvbnN0IHRyaWFuZ2xlcyA9IG5ldyBVaW50MzJBcnJheShudW1UcmlhbmdsZXMgKiAzKTsKICAgICAgICAgIGxldCB0cmlJbmRleCA9IDA7CgogICAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgIGNvbnN0IG15ID0gKGF5ICsgYnkpID4+IDE7CgogICAgICAgICAgICAgIGNvbnN0IGxlZ0xlbmd0aCA9IE1hdGguYWJzKGF4IC0gY3gpICsgTWF0aC5hYnMoYXkgLSBjeSk7CiAgICAgICAgICAgICAgaWYgKChsZWdMZW5ndGggPiAxICYmIGVycm9yc1tteSAqIHNpemUgKyBteF0gPiBtYXhFcnJvcikgfHwgbGVnTGVuZ3RoID4gbWF4U2NhbGUpIHsKICAgICAgICAgICAgICAgICAgLy8gdHJpYW5nbGUgZG9lc24ndCBhcHByb3hpbWF0ZSB0aGUgc3VyZmFjZSB3ZWxsIGVub3VnaDsgZHJpbGwgZG93biBmdXJ0aGVyCiAgICAgICAgICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwoKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAvLyBhZGQgYSB0cmlhbmdsZQogICAgICAgICAgICAgICAgICBjb25zdCBhID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gLSAxOwogICAgICAgICAgICAgICAgICBjb25zdCBiID0gaW5kaWNlc1tieSAqIHNpemUgKyBieF0gLSAxOwogICAgICAgICAgICAgICAgICBjb25zdCBjID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gLSAxOwoKICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBhICsgMV0gPSBheTsKCiAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBiXSA9IGJ4OwogICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CgogICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogY10gPSBjeDsKICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGMgKyAxXSA9IGN5OwoKICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYjsKICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYzsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoMCwgMCwgbWF4LCBtYXgsIG1heCwgMCk7CiAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CgogICAgICAgICAgcmV0dXJuIHt2ZXJ0aWNlcywgdHJpYW5nbGVzfTsKICAgICAgfQogIH0KCiAgLyoqIFdvcmtlciB0byB1cHNhbXBsZSB0ZXJyYWluIG1lc2hlcyAqLwogIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9DZXNpdW1HUy9jZXNpdW0vYmxvYi8xLjc2L1NvdXJjZS9Xb3JrZXJzRVM2L2NyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoLmpzCgogIHZhciBtYXJ0aW5pQ2FjaGUgPSB7fTsKICBmdW5jdGlvbiBkZWNvZGVUZXJyYWluKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHZhciBfbWFydGluaUNhY2hlJHRpbGVTaXo7CiAgICB2YXIgaGVpZ2h0RGF0YSA9IHBhcmFtZXRlcnMuaGVpZ2h0RGF0YSwKICAgICAgX3BhcmFtZXRlcnMkdGlsZVNpemUgPSBwYXJhbWV0ZXJzLnRpbGVTaXplLAogICAgICB0aWxlU2l6ZSA9IF9wYXJhbWV0ZXJzJHRpbGVTaXplID09PSB2b2lkIDAgPyAyNTYgOiBfcGFyYW1ldGVycyR0aWxlU2l6ZSwKICAgICAgZXJyb3JMZXZlbCA9IHBhcmFtZXRlcnMuZXJyb3JMZXZlbCwKICAgICAgbWF4VmVydGV4RGlzdGFuY2UgPSBwYXJhbWV0ZXJzLm1heFZlcnRleERpc3RhbmNlOwoKICAgIC8vIEhlaWdodCBkYXRhIGNhbiBiZSBlaXRoZXIgYW4gYXJyYXkgb2YgbnVtYmVycyAoZm9yIHByZS1leGlzdGluZyB0ZXJyYWluIGRhdGEpCiAgICAvLyBvciBhbiBpbWFnZSBkYXRhIGFycmF5IChmb3IgZGVjb2RpbmcgZnJvbSBhbiBpbWFnZSkKCiAgICB2YXIgdGVycmFpbiA9IGhlaWdodERhdGE7CgogICAgLy8gVGlsZSBzaXplIG11c3QgYmUgbWFpbnRhaW5lZCB0aHJvdWdoIHRoZSBsaWZlIG9mIHRoZSB3b3JrZXIKICAgIChfbWFydGluaUNhY2hlJHRpbGVTaXogPSBtYXJ0aW5pQ2FjaGVbdGlsZVNpemVdKSAhPT0gbnVsbCAmJiBfbWFydGluaUNhY2hlJHRpbGVTaXogIT09IHZvaWQgMCA/IF9tYXJ0aW5pQ2FjaGUkdGlsZVNpeiA6IG1hcnRpbmlDYWNoZVt0aWxlU2l6ZV0gPSBuZXcgTWFydGluaSh0aWxlU2l6ZSArIDEpOwogICAgdmFyIHRpbGUgPSBtYXJ0aW5pQ2FjaGVbdGlsZVNpemVdLmNyZWF0ZVRpbGUodGVycmFpbik7CgogICAgLy8gZ2V0IGEgbWVzaCAodmVydGljZXMgYW5kIHRyaWFuZ2xlcyBpbmRpY2VzKSBmb3IgYSAxMG0gZXJyb3IKICAgIHZhciBtZXNoID0gdGlsZS5nZXRNZXNoKGVycm9yTGV2ZWwsIE1hdGgubWluKG1heFZlcnRleERpc3RhbmNlLCB0aWxlU2l6ZSkpOwogICAgdmFyIHJlcyA9IGNyZWF0ZVF1YW50aXplZE1lc2hEYXRhKHRpbGUsIG1lc2gsIHRpbGVTaXplLAogICAgLy8gT25seSBpbmNsdWRlIHZlcnRleCBkYXRhIGlmIGFudGljaXBhdGUgdXBzY2FsaW5nIHRpbGUKICAgIHRlcnJhaW4gKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChyZXMuaW5kaWNlcy5idWZmZXIpOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKHJlcy5xdWFudGl6ZWRWZXJ0aWNlcy5idWZmZXIpOwogICAgaWYgKHJlcy5xdWFudGl6ZWRIZWlnaHRzKSB7CiAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChyZXMucXVhbnRpemVkSGVpZ2h0cy5idWZmZXIpOwogICAgfQogICAgcmV0dXJuIHJlczsKICB9CiAgc2VsZi5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAobXNnKSB7CiAgICB2YXIgX21zZyRkYXRhID0gbXNnLmRhdGEsCiAgICAgIGlkID0gX21zZyRkYXRhLmlkLAogICAgICBwYXlsb2FkID0gX21zZyRkYXRhLnBheWxvYWQ7CiAgICBpZiAoaWQgPT0gbnVsbCkgcmV0dXJuOwogICAgdmFyIG9iamVjdHMgPSBbXTsKICAgIHZhciByZXMgPSBudWxsOwogICAgdHJ5IHsKICAgICAgcmVzID0gZGVjb2RlVGVycmFpbihwYXlsb2FkLCBvYmplY3RzKTsKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogaWQsCiAgICAgICAgcGF5bG9hZDogcmVzCiAgICAgIH0sIG9iamVjdHMpOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIHZhciBfZXJyJG1lc3NhZ2U7CiAgICAgIHZhciBfbXNnID0gKF9lcnIkbWVzc2FnZSA9IGVyci5tZXNzYWdlKSAhPT0gbnVsbCAmJiBfZXJyJG1lc3NhZ2UgIT09IHZvaWQgMCA/IF9lcnIkbWVzc2FnZSA6IGVycjsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIGVycjogX21zZy50b1N0cmluZygpCiAgICAgIH0pOwogICAgfSBmaW5hbGx5IHsKICAgICAgcmVzID0gbnVsbDsKICAgICAgb2JqZWN0cyA9IG51bGw7CiAgICB9CiAgfTsKCn0pKCk7Cgo=', null, false);
1049
+ /* eslint-enable */
1050
+
1051
+ var _excluded = ["tilingScheme", "overscaleFactor"];
1052
+ function createTerrainMesh(data, meta) {
1053
+ var minimumHeight = data.minimumHeight,
1054
+ maximumHeight = data.maximumHeight,
1055
+ quantizedVertices = data.quantizedVertices,
1056
+ indices = data.indices,
1057
+ westIndices = data.westIndices,
1058
+ southIndices = data.southIndices,
1059
+ eastIndices = data.eastIndices,
1060
+ northIndices = data.northIndices,
1061
+ quantizedHeights = data.quantizedHeights;
1062
+ var errorLevel = meta.errorLevel,
1063
+ tileSize = meta.tileSize,
1064
+ maxVertexDistance = meta.maxVertexDistance,
1065
+ tileRect = meta.tileRect,
1066
+ ellipsoid = meta.ellipsoid,
1067
+ overscaleFactor = meta.overscaleFactor;
1068
+ var err = errorLevel;
1069
+ var skirtHeight = err * 20;
1070
+
1071
+ // Check if tileRect is not NaNs
1072
+ if (isNaN(tileRect.east) || isNaN(tileRect.north)) {
1073
+ throw new Error("Invalid tile rect");
1006
1074
  }
1007
- update() {
1008
- const {
1009
- numTriangles,
1010
- numParentTriangles,
1011
- coords,
1012
- gridSize: size
1013
- } = this.martini;
1014
- const {
1015
- terrain,
1016
- errors
1017
- } = this;
1075
+ var center = Rectangle.center(tileRect);
1018
1076
 
1019
- // iterate over all possible triangles, starting from the smallest level
1020
- for (let i = numTriangles - 1; i >= 0; i--) {
1021
- const k = i * 4;
1022
- const ax = coords[k + 0];
1023
- const ay = coords[k + 1];
1024
- const bx = coords[k + 2];
1025
- const by = coords[k + 3];
1026
- const mx = ax + bx >> 1;
1027
- const my = ay + by >> 1;
1028
- const cx = mx + my - ay;
1029
- const cy = my + ax - mx;
1077
+ // Calculating occlusion height is kind of messy currently, but it definitely works
1078
+ var halfAngle = tileRect.width / 2;
1079
+ var dr = Math.cos(halfAngle); // half tile width since our ref point is at the center
1030
1080
 
1031
- // calculate error in the middle of the long edge of the triangle
1032
- const interpolatedHeight = (terrain[ay * size + ax] + terrain[by * size + bx]) / 2;
1033
- const middleIndex = my * size + mx;
1034
- const middleError = Math.abs(interpolatedHeight - terrain[middleIndex]);
1035
- errors[middleIndex] = Math.max(errors[middleIndex], middleError);
1036
- if (i < numParentTriangles) {
1037
- // bigger triangles; accumulate error with children
1038
- const leftChildIndex = (ay + cy >> 1) * size + (ax + cx >> 1);
1039
- const rightChildIndex = (by + cy >> 1) * size + (bx + cx >> 1);
1040
- errors[middleIndex] = Math.max(errors[middleIndex], errors[leftChildIndex], errors[rightChildIndex]);
1041
- }
1081
+ var occlusionHeight = dr * ellipsoid.maximumRadius + maximumHeight;
1082
+ if (halfAngle > Math.PI / 4) {
1083
+ occlusionHeight = (1 + halfAngle) * ellipsoid.maximumRadius;
1084
+ }
1085
+ var occlusionPoint = new Cartographic(center.longitude, center.latitude, occlusionHeight) // Scaling factor of two just to be sure.
1086
+ ;
1087
+ var horizonOcclusionPoint = ellipsoid.transformPositionToScaledSpace(Cartographic.toCartesian(occlusionPoint));
1088
+ var orientedBoundingBox = OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, ellipsoid);
1089
+ var boundingSphere = BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox);
1090
+ return new RasterTerrainData({
1091
+ minimumHeight: minimumHeight,
1092
+ maximumHeight: maximumHeight,
1093
+ quantizedVertices: quantizedVertices,
1094
+ indices: indices,
1095
+ boundingSphere: boundingSphere,
1096
+ orientedBoundingBox: orientedBoundingBox,
1097
+ horizonOcclusionPoint: horizonOcclusionPoint,
1098
+ westIndices: westIndices,
1099
+ southIndices: southIndices,
1100
+ eastIndices: eastIndices,
1101
+ northIndices: northIndices,
1102
+ westSkirtHeight: skirtHeight,
1103
+ southSkirtHeight: skirtHeight,
1104
+ eastSkirtHeight: skirtHeight,
1105
+ northSkirtHeight: skirtHeight,
1106
+ childTileMask: 15,
1107
+ createdByUpsampling: overscaleFactor > 0,
1108
+ errorLevel: err,
1109
+ maxVertexDistance: maxVertexDistance,
1110
+ tileSize: tileSize,
1111
+ quantizedHeights: quantizedHeights
1112
+ });
1113
+ }
1114
+ function createEmptyMesh(opts) {
1115
+ var tileRect = opts.tileRect,
1116
+ tileCoord = opts.tileCoord,
1117
+ errorLevel = opts.errorLevel,
1118
+ ellipsoid = opts.ellipsoid,
1119
+ maxVertexDistance = opts.maxVertexDistance;
1120
+ var center = Rectangle.center(tileRect);
1121
+ var z = tileCoord.z;
1122
+ var latScalar = Math.min(Math.abs(Math.sin(center.latitude)), 0.995);
1123
+ var v = Math.max(Math.ceil(200 / (z + 1) * Math.pow(1 - latScalar, 0.25)), 4);
1124
+ var output = emptyMesh(v);
1125
+ // We use zero for some undefined values
1126
+ return createTerrainMesh(output, {
1127
+ tileRect: tileRect,
1128
+ ellipsoid: ellipsoid,
1129
+ errorLevel: errorLevel,
1130
+ overscaleFactor: 0,
1131
+ maxVertexDistance: maxVertexDistance,
1132
+ tileSize: output.tileSize
1133
+ });
1134
+ }
1135
+ var UpsampleTracker = /*#__PURE__*/function () {
1136
+ function UpsampleTracker() {
1137
+ _classCallCheck(this, UpsampleTracker);
1138
+ this.ne = false;
1139
+ this.nw = false;
1140
+ this.se = false;
1141
+ this.sw = false;
1142
+ }
1143
+ return _createClass(UpsampleTracker, [{
1144
+ key: "finished",
1145
+ value: function finished() {
1146
+ return this.ne && this.nw && this.se && this.sw;
1042
1147
  }
1148
+ }]);
1149
+ }();
1150
+ var RasterTerrainData = /*#__PURE__*/function (_QuantizedMeshTerrain) {
1151
+ function RasterTerrainData(opts) {
1152
+ var _opts$maxVertexDistan;
1153
+ var _this;
1154
+ _classCallCheck(this, RasterTerrainData);
1155
+ _this = _callSuper(this, RasterTerrainData, [opts]);
1156
+ _this.quantizedHeights = opts.quantizedHeights;
1157
+ _this.errorLevel = opts.errorLevel;
1158
+ _this.maxVertexDistance = (_opts$maxVertexDistan = opts.maxVertexDistance) !== null && _opts$maxVertexDistan !== void 0 ? _opts$maxVertexDistan : opts.tileSize;
1159
+ _this.tileSize = opts.tileSize;
1160
+ _this.upsampleTracker = new UpsampleTracker();
1161
+ return _this;
1043
1162
  }
1044
- getMesh(maxError = 0, maxLength = null) {
1045
- const {
1046
- gridSize: size,
1047
- indices
1048
- } = this.martini;
1049
- const {
1050
- errors
1051
- } = this;
1052
- let numVertices = 0;
1053
- let numTriangles = 0;
1054
- const max = size - 1;
1163
+ _inherits(RasterTerrainData, _QuantizedMeshTerrain);
1164
+ return _createClass(RasterTerrainData, [{
1165
+ key: "upsample",
1166
+ value: function upsample(tilingScheme, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel) {
1167
+ if (this.quantizedHeights == null) {
1168
+ return _superPropGet(RasterTerrainData, "upsample", this, 3)([tilingScheme, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel]);
1169
+ } // Something wonky about our tiling scheme, perhaps
1170
+ // 12/2215/2293 @2x
1171
+ //const url = `https://a.tiles.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}`;
1055
1172
 
1056
- // The maxLength parameter will cause triangles to be generated until the legs are below this length
1057
- // It is meant to support cases where a certain mesh density is required to do spherical math on digital globes
1058
- const maxScale = maxLength || size;
1173
+ var x = descendantX;
1174
+ var y = descendantY;
1175
+ var z = descendantLevel;
1059
1176
 
1060
- // use an index grid to keep track of vertices that were already used to avoid duplication
1061
- indices.fill(0);
1177
+ //console.log(`Upsampling terrain data from zoom ${thisLevel} to ` + tile);
1062
1178
 
1063
- // retrieve mesh in two stages that both traverse the error map:
1064
- // - countElements: find used vertices (and assign each an index), and count triangles (for minimum allocation)
1065
- // - processTriangle: fill the allocated vertices & triangles typed arrays
1066
-
1067
- function countElements(ax, ay, bx, by, cx, cy) {
1068
- const mx = ax + bx >> 1;
1069
- const my = ay + by >> 1;
1070
- const legLength = Math.abs(ax - cx) + Math.abs(ay - cy);
1071
- if (legLength > 1 && errors[my * size + mx] > maxError || legLength > maxScale) {
1072
- countElements(cx, cy, ax, ay, mx, my);
1073
- countElements(bx, by, cx, cy, mx, my);
1074
- } else {
1075
- indices[ay * size + ax] = indices[ay * size + ax] || ++numVertices;
1076
- indices[by * size + bx] = indices[by * size + bx] || ++numVertices;
1077
- indices[cy * size + cx] = indices[cy * size + cx] || ++numVertices;
1078
- numTriangles++;
1179
+ var dz = z - thisLevel;
1180
+ var scalar = Math.pow(2, dz);
1181
+ var ellipsoid = tilingScheme.ellipsoid;
1182
+ var err = this.errorLevel / scalar;
1183
+ var maxVertexDistance = Math.min(this.maxVertexDistance * scalar, this.tileSize);
1184
+ var upscaledX = thisX * scalar;
1185
+ var upscaledY = thisY * scalar;
1186
+ var dx = x - upscaledX;
1187
+ var dy = y - upscaledY;
1188
+ var x0 = dx * this.tileSize / scalar;
1189
+ var x1 = (dx + 1) * this.tileSize / scalar;
1190
+ var y0 = dy * this.tileSize / scalar;
1191
+ var y1 = (dy + 1) * this.tileSize / scalar;
1192
+ var window = {
1193
+ x0: x0,
1194
+ x1: x1,
1195
+ y0: y0,
1196
+ y1: y1
1197
+ };
1198
+ var res = buildOverscaledTerrainTile({
1199
+ tilingScheme: tilingScheme,
1200
+ heightData: subsetByWindow(this.quantizedHeights, window, true),
1201
+ maxVertexDistance: maxVertexDistance,
1202
+ x: x,
1203
+ y: y,
1204
+ z: z,
1205
+ errorLevel: err,
1206
+ ellipsoidRadius: ellipsoid.maximumRadius,
1207
+ tileSize: x1 - x0,
1208
+ overscaleFactor: dz
1209
+ });
1210
+ if (dz == 1) {
1211
+ // If we've got a single child tile, we can track that we've upsampled the parent.
1212
+ var quadrant = getQuadrant(dx, dy);
1213
+ this.upsampleTracker[quadrant] = true;
1079
1214
  }
1080
- }
1081
- countElements(0, 0, max, max, max, 0);
1082
- countElements(max, max, 0, 0, 0, max);
1083
- const vertices = new Uint16Array(numVertices * 2);
1084
- const triangles = new Uint32Array(numTriangles * 3);
1085
- let triIndex = 0;
1086
- function processTriangle(ax, ay, bx, by, cx, cy) {
1087
- const mx = ax + bx >> 1;
1088
- const my = ay + by >> 1;
1089
- const legLength = Math.abs(ax - cx) + Math.abs(ay - cy);
1090
- if (legLength > 1 && errors[my * size + mx] > maxError || legLength > maxScale) {
1091
- // triangle doesn't approximate the surface well enough; drill down further
1092
- processTriangle(cx, cy, ax, ay, mx, my);
1093
- processTriangle(bx, by, cx, cy, mx, my);
1094
- } else {
1095
- // add a triangle
1096
- const a = indices[ay * size + ax] - 1;
1097
- const b = indices[by * size + bx] - 1;
1098
- const c = indices[cy * size + cx] - 1;
1099
- vertices[2 * a] = ax;
1100
- vertices[2 * a + 1] = ay;
1101
- vertices[2 * b] = bx;
1102
- vertices[2 * b + 1] = by;
1103
- vertices[2 * c] = cx;
1104
- vertices[2 * c + 1] = cy;
1105
- triangles[triIndex++] = a;
1106
- triangles[triIndex++] = b;
1107
- triangles[triIndex++] = c;
1215
+ if (this.upsampleTracker.finished()) {
1216
+ // We've upsampled all child tiles and don't need to keep terrain data around anymore.
1217
+ this.quantizedHeights = undefined;
1108
1218
  }
1219
+ return res;
1109
1220
  }
1110
- processTriangle(0, 0, max, max, max, 0);
1111
- processTriangle(max, max, 0, 0, 0, max);
1112
- return {
1113
- vertices,
1114
- triangles
1115
- };
1116
- }
1221
+ }]);
1222
+ }(QuantizedMeshTerrainData);
1223
+ function getQuadrant(dx, dy) {
1224
+ if (dx == 0 && dy == 0) return "sw";
1225
+ if (dx == 0 && dy == 1) return "nw";
1226
+ if (dx == 1 && dy == 0) return "se";
1227
+ if (dx == 1 && dy == 1) return "ne";
1228
+ throw new Error("Invalid quadrant");
1117
1229
  }
1118
-
1119
- // https://github.com/CesiumGS/cesium/blob/1.76/Source/WorkersES6/createVerticesFromQuantizedTerrainMesh.js
1120
-
1121
- var martini = null;
1122
- function decodeTerrain(parameters, transferableObjects) {
1123
- var _martini;
1124
- var imageData = parameters.imageData,
1125
- _parameters$tileSize = parameters.tileSize,
1126
- tileSize = _parameters$tileSize === void 0 ? 256 : _parameters$tileSize,
1127
- errorLevel = parameters.errorLevel,
1128
- interval = parameters.interval,
1129
- offset = parameters.offset;
1130
- var pixels = ndarray(new Uint8Array(imageData), [tileSize, tileSize, 4], [4, 4 * tileSize, 1], 0);
1131
-
1132
- // Tile size must be maintained through the life of the worker
1133
- (_martini = martini) !== null && _martini !== void 0 ? _martini : martini = new Martini(tileSize + 1);
1134
- var terrain = mapboxTerrainToGrid(pixels, interval, offset);
1135
- var tile = martini.createTile(terrain);
1136
-
1137
- // get a mesh (vertices and triangles indices) for a 10m error
1138
- var mesh = tile.getMesh(errorLevel, parameters.maxLength);
1139
- return createQuantizedMeshData(tile, mesh, tileSize);
1230
+ function buildOverscaledTerrainTile(_x) {
1231
+ return _buildOverscaledTerrainTile.apply(this, arguments);
1140
1232
  }
1141
- self.onmessage = function (msg) {
1142
- var _msg$data = msg.data,
1143
- id = _msg$data.id,
1144
- payload = _msg$data.payload;
1145
- if (id == null) return;
1146
- var objects = [];
1147
- var res = null;
1148
- try {
1149
- res = decodeTerrain(payload);
1150
- objects.push(res.indices.buffer);
1151
- objects.push(res.quantizedVertices.buffer);
1152
- self.postMessage({
1153
- id: id,
1154
- payload: res
1155
- }, objects);
1156
- } catch (err) {
1157
- self.postMessage({
1158
- id: id,
1159
- err: err.toString()
1160
- });
1161
- } finally {
1162
- res = null;
1163
- objects = null;
1164
- }
1165
- };
1233
+ function _buildOverscaledTerrainTile() {
1234
+ _buildOverscaledTerrainTile = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(opts) {
1235
+ var tilingScheme, overscaleFactor, workerOpts, x, y, z, tileRect, ellipsoid, errorLevel, maxVertexDistance, tileSize, res;
1236
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
1237
+ while (1) switch (_context.prev = _context.next) {
1238
+ case 0:
1239
+ tilingScheme = opts.tilingScheme, overscaleFactor = opts.overscaleFactor, workerOpts = _objectWithoutProperties(opts, _excluded);
1240
+ x = workerOpts.x, y = workerOpts.y, z = workerOpts.z;
1241
+ tileRect = tilingScheme.tileXYToRectangle(x, y, z);
1242
+ ellipsoid = tilingScheme.ellipsoid;
1243
+ errorLevel = workerOpts.errorLevel, maxVertexDistance = workerOpts.maxVertexDistance, tileSize = workerOpts.tileSize;
1244
+ _context.prev = 5;
1245
+ _context.next = 8;
1246
+ return upsamplerFarm.scheduleTask(workerOpts, [workerOpts.heightData.buffer]);
1247
+ case 8:
1248
+ res = _context.sent;
1249
+ return _context.abrupt("return", createTerrainMesh(res, {
1250
+ tileRect: tileRect,
1251
+ ellipsoid: ellipsoid,
1252
+ errorLevel: errorLevel,
1253
+ overscaleFactor: overscaleFactor,
1254
+ tileSize: tileSize,
1255
+ // Maximum vertex distance
1256
+ maxVertexDistance: maxVertexDistance
1257
+ }));
1258
+ case 12:
1259
+ _context.prev = 12;
1260
+ _context.t0 = _context["catch"](5);
1261
+ return _context.abrupt("return", createEmptyMesh({
1262
+ tileRect: tileRect,
1263
+ errorLevel: errorLevel,
1264
+ ellipsoid: ellipsoid,
1265
+ tileCoord: {
1266
+ x: x,
1267
+ y: y,
1268
+ z: z
1269
+ },
1270
+ tileSize: 0
1271
+ }));
1272
+ case 15:
1273
+ case "end":
1274
+ return _context.stop();
1275
+ }
1276
+ }, _callee, null, [[5, 12]]);
1277
+ }));
1278
+ return _buildOverscaledTerrainTile.apply(this, arguments);
1279
+ }
1280
+ var upsamplerFarm = new WorkerFarm({
1281
+ worker: new WorkerFactory$1(),
1282
+ maxWorkers: 5
1283
+ });
1166
1284
 
1167
1285
  // https://github.com/CesiumGS/cesium/blob/1.68/Source/Scene/MapboxImageryProvider.js#L42
1286
+
1168
1287
  var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
1169
- _inherits(StretchedTilingScheme, _WebMercatorTilingSch);
1170
- var _super = _createSuper(StretchedTilingScheme);
1171
1288
  function StretchedTilingScheme() {
1172
1289
  _classCallCheck(this, StretchedTilingScheme);
1173
- return _super.apply(this, arguments);
1290
+ return _callSuper(this, StretchedTilingScheme, arguments);
1174
1291
  }
1175
- _createClass(StretchedTilingScheme, [{
1292
+ _inherits(StretchedTilingScheme, _WebMercatorTilingSch);
1293
+ return _createClass(StretchedTilingScheme, [{
1176
1294
  key: "tileXYToRectangle",
1177
1295
  value: function tileXYToRectangle(x, y, level, res) {
1178
- var result = _get(_getPrototypeOf(StretchedTilingScheme.prototype), "tileXYToRectangle", this).call(this, x, y, level);
1296
+ var result = _superPropGet(StretchedTilingScheme, "tileXYToRectangle", this, 3)([x, y, level]);
1179
1297
  if (y == 0) {
1180
- //console.log("Top row", res, y, level);
1181
1298
  result.north = Math.PI / 2;
1182
1299
  }
1183
1300
  if (y + 1 == Math.pow(2, level)) {
@@ -1186,12 +1303,11 @@ var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
1186
1303
  return result;
1187
1304
  }
1188
1305
  }]);
1189
- return StretchedTilingScheme;
1190
1306
  }(WebMercatorTilingScheme);
1191
1307
  var MartiniTerrainProvider = /*#__PURE__*/function () {
1192
1308
  // @ts-ignore
1193
1309
  function MartiniTerrainProvider() {
1194
- var _opts$interval, _opts$offset, _opts$maxWorkers, _opts$minZoomLevel, _opts$fillPoles, _opts$detailScalar, _opts$minimumErrorLev, _opts$ellipsoid;
1310
+ var _this$resource$credit, _opts$maxWorkers, _opts$minZoomLevel, _opts$fillPoles, _opts$minimumErrorLev, _opts$ellipsoid, _opts$detailScalar, _ref, _opts$tilingScheme$el, _opts$tilingScheme;
1195
1311
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1196
1312
  _classCallCheck(this, MartiniTerrainProvider);
1197
1313
  _defineProperty(this, "hasWaterMask", false);
@@ -1199,125 +1315,159 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1199
1315
  _defineProperty(this, "credit", new Credit("Mapbox"));
1200
1316
  _defineProperty(this, "availability", null);
1201
1317
  _defineProperty(this, "errorEvent", new Event());
1202
- _defineProperty(this, "workerFarm", null);
1203
- _defineProperty(this, "inProgressWorkers", 0);
1204
1318
  _defineProperty(this, "levelOfDetailScalar", null);
1205
1319
  _defineProperty(this, "maxWorkers", 5);
1206
1320
  _defineProperty(this, "minError", 0.1);
1207
1321
  _defineProperty(this, "fillPoles", true);
1208
1322
  _defineProperty(this, "_errorAtMinZoom", 1000);
1209
1323
  _defineProperty(this, "resource", null);
1324
+ _defineProperty(this, "decoder", null);
1210
1325
  _defineProperty(this, "RADIUS_SCALAR", 1.0);
1211
1326
  //this.martini = new Martini(257);
1212
1327
  this.resource = opts.resource;
1213
- this.interval = (_opts$interval = opts.interval) !== null && _opts$interval !== void 0 ? _opts$interval : 0.1;
1214
- this.offset = (_opts$offset = opts.offset) !== null && _opts$offset !== void 0 ? _opts$offset : -10000;
1328
+ this.credit = (_this$resource$credit = this.resource.credit) !== null && _this$resource$credit !== void 0 ? _this$resource$credit : new Credit("Mapbox");
1329
+ this.decoder = opts.decoder;
1215
1330
  this.maxWorkers = (_opts$maxWorkers = opts.maxWorkers) !== null && _opts$maxWorkers !== void 0 ? _opts$maxWorkers : 5;
1331
+ if (!this.decoder) {
1332
+ var maxWorkers = this.maxWorkers;
1333
+ if (maxWorkers > 0) {
1334
+ this.decoder = new WorkerFarmTerrainDecoder({
1335
+ maxWorkers: maxWorkers
1336
+ });
1337
+ } else {
1338
+ this.decoder = new DefaultTerrainDecoder();
1339
+ }
1340
+ }
1216
1341
  this.minZoomLevel = (_opts$minZoomLevel = opts.minZoomLevel) !== null && _opts$minZoomLevel !== void 0 ? _opts$minZoomLevel : 3;
1217
1342
  this.fillPoles = (_opts$fillPoles = opts.fillPoles) !== null && _opts$fillPoles !== void 0 ? _opts$fillPoles : true;
1218
- console.log("fillPoles", this.fillPoles);
1219
- this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 4.0) + Math$1.EPSILON5;
1220
1343
  this.ready = true;
1221
1344
  this.readyPromise = Promise.resolve(true);
1222
1345
  this.minError = (_opts$minimumErrorLev = opts.minimumErrorLevel) !== null && _opts$minimumErrorLev !== void 0 ? _opts$minimumErrorLev : 0.1;
1223
1346
  this.errorEvent.addEventListener(console.log, this);
1224
1347
  this.ellipsoid = (_opts$ellipsoid = opts.ellipsoid) !== null && _opts$ellipsoid !== void 0 ? _opts$ellipsoid : Ellipsoid.WGS84;
1225
- if (this.maxWorkers > 0) {
1226
- this.workerFarm = new WorkerFarm();
1227
- }
1228
- var scheme = WebMercatorTilingScheme;
1229
- if (this.fillPoles) {
1230
- scheme = StretchedTilingScheme;
1348
+ if (opts.tilingScheme == null) {
1349
+ var scheme = WebMercatorTilingScheme;
1350
+ if (this.fillPoles) {
1351
+ scheme = StretchedTilingScheme;
1352
+ }
1353
+ this.tilingScheme = new scheme({
1354
+ numberOfLevelZeroTilesX: 1,
1355
+ numberOfLevelZeroTilesY: 1,
1356
+ ellipsoid: this.ellipsoid
1357
+ });
1358
+ } else {
1359
+ this.tilingScheme = opts.tilingScheme;
1231
1360
  }
1232
- this.tilingScheme = new scheme({
1233
- numberOfLevelZeroTilesX: 1,
1234
- numberOfLevelZeroTilesY: 1,
1235
- ellipsoid: this.ellipsoid
1236
- });
1361
+ this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 2.0) + Math$1.EPSILON5;
1362
+
1363
+ //this.errorEvent.addEventListener(console.log, this);
1364
+ this.ellipsoid = (_ref = (_opts$tilingScheme$el = (_opts$tilingScheme = opts.tilingScheme) === null || _opts$tilingScheme === void 0 ? void 0 : _opts$tilingScheme.ellipsoid) !== null && _opts$tilingScheme$el !== void 0 ? _opts$tilingScheme$el : opts.ellipsoid) !== null && _ref !== void 0 ? _ref : Ellipsoid.WGS84;
1237
1365
  this._errorAtMinZoom = this.errorAtZoom(this.minZoomLevel);
1238
1366
  }
1239
- _createClass(MartiniTerrainProvider, [{
1367
+ return _createClass(MartiniTerrainProvider, [{
1240
1368
  key: "requestTileGeometry",
1241
1369
  value: function requestTileGeometry(x, y, z, request) {
1242
- var _this = this;
1243
1370
  // Look for tiles both below the zoom level and below the error threshold for the zoom level at the equator...
1244
-
1245
- if (z < this.minZoomLevel || this.scaledErrorForTile(x, y, z) > this._errorAtMinZoom) {
1371
+ if (this.minZoomLevel != 0 && (z < this.minZoomLevel || this.scaledErrorForTile(x, y, z) > this._errorAtMinZoom)) {
1246
1372
  // If we are below the minimum zoom level, we return empty heightmaps
1247
1373
  // to avoid unnecessary requests for low-resolution data.
1248
1374
  return Promise.resolve(this.emptyMesh(x, y, z));
1249
1375
  }
1250
1376
 
1251
1377
  // Note: we still load a TON of tiles near the poles. We might need to do some overzooming here...
1252
-
1253
- if (this.inProgressWorkers > this.maxWorkers) return undefined;
1254
- this.inProgressWorkers += 1;
1255
- return this.processTile(x, y, z)["finally"](function () {
1256
- _this.inProgressWorkers -= 1;
1257
- });
1378
+ return this.decoder.requestTileGeometry({
1379
+ x: x,
1380
+ y: y,
1381
+ z: z
1382
+ }, this.processTile.bind(this));
1258
1383
  }
1259
1384
  }, {
1260
1385
  key: "processTile",
1261
1386
  value: function () {
1262
- var _processTile = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(x, y, z) {
1263
- var _this$resource, tileSize, getTilePixels, px, pixelData, tileRect, err, maxLength, params, res;
1387
+ var _processTile = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref2) {
1388
+ var x, y, z, tileRect, errorLevel, maxVertexDistance, _this$resource, tileSize, getTilePixels, r1, px, pixelData, params, res, meta;
1264
1389
  return _regeneratorRuntime().wrap(function _callee$(_context) {
1265
1390
  while (1) switch (_context.prev = _context.next) {
1266
1391
  case 0:
1267
- _context.prev = 0;
1392
+ x = _ref2.x, y = _ref2.y, z = _ref2.z;
1393
+ // Something wonky about our tiling scheme, perhaps
1394
+ // 12/2215/2293 @2x
1395
+ //const url = `https://a.tiles.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}`;
1396
+ tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
1397
+ errorLevel = this.errorAtZoom(z);
1398
+ maxVertexDistance = this.maxVertexDistance(tileRect);
1399
+ _context.prev = 4;
1268
1400
  _this$resource = this.resource, tileSize = _this$resource.tileSize, getTilePixels = _this$resource.getTilePixels;
1269
- _context.next = 4;
1270
- return getTilePixels({
1401
+ r1 = getTilePixels.bind(this.resource, {
1271
1402
  x: x,
1272
1403
  y: y,
1273
1404
  z: z
1274
1405
  });
1275
- case 4:
1406
+ if (!(r1 == null)) {
1407
+ _context.next = 9;
1408
+ break;
1409
+ }
1410
+ return _context.abrupt("return");
1411
+ case 9:
1412
+ _context.next = 11;
1413
+ return r1();
1414
+ case 11:
1276
1415
  px = _context.sent;
1277
1416
  pixelData = px.data;
1278
- tileRect = this.tilingScheme.tileXYToRectangle(x, y, z); ///const center = Rectangle.center(tileRect);
1279
- err = this.errorAtZoom(z);
1280
- maxLength = this.maxVertexDistance(tileRect);
1417
+ if (!(pixelData == null)) {
1418
+ _context.next = 15;
1419
+ break;
1420
+ }
1421
+ return _context.abrupt("return");
1422
+ case 15:
1423
+ ///const center = Rectangle.center(tileRect);
1281
1424
  params = {
1282
1425
  imageData: pixelData,
1283
- maxLength: maxLength,
1426
+ maxVertexDistance: maxVertexDistance,
1284
1427
  x: x,
1285
1428
  y: y,
1286
1429
  z: z,
1287
- errorLevel: err,
1288
- ellipsoidRadius: this.ellipsoid.maximumRadius,
1289
- tileSize: tileSize,
1290
- interval: this.interval,
1291
- offset: this.offset
1430
+ errorLevel: errorLevel,
1431
+ ellipsoidRadius: this.tilingScheme.ellipsoid.maximumRadius,
1432
+ tileSize: tileSize
1292
1433
  };
1293
- if (!(this.workerFarm != null)) {
1294
- _context.next = 16;
1295
- break;
1296
- }
1297
- _context.next = 13;
1298
- return this.workerFarm.scheduleTask(params, [pixelData.buffer]);
1299
- case 13:
1434
+ _context.next = 18;
1435
+ return this.decoder.decodeTerrain(params, pixelData.buffer);
1436
+ case 18:
1300
1437
  res = _context.sent;
1301
- _context.next = 17;
1302
- break;
1303
- case 16:
1304
- res = decodeTerrain(params);
1305
- case 17:
1306
- pixelData = undefined;
1307
- px = undefined;
1308
- return _context.abrupt("return", this.createQuantizedMeshData(tileRect, err, res));
1309
- case 22:
1310
- _context.prev = 22;
1311
- _context.t0 = _context["catch"](0);
1312
- console.log(_context.t0);
1313
- return _context.abrupt("return", this.emptyMesh(x, y, z));
1438
+ meta = {
1439
+ ellipsoid: this.tilingScheme.ellipsoid,
1440
+ errorLevel: errorLevel,
1441
+ overscaleFactor: 0,
1442
+ maxVertexDistance: maxVertexDistance,
1443
+ tileRect: tileRect,
1444
+ tileSize: tileSize
1445
+ };
1446
+ /** This builds a final terrain mesh object that can optionally
1447
+ * be upscaled to a higher resolution.
1448
+ */
1449
+ return _context.abrupt("return", createTerrainMesh(res, meta));
1450
+ case 23:
1451
+ _context.prev = 23;
1452
+ _context.t0 = _context["catch"](4);
1453
+ return _context.abrupt("return", createEmptyMesh({
1454
+ tileRect: tileRect,
1455
+ errorLevel: errorLevel,
1456
+ ellipsoid: this.tilingScheme.ellipsoid,
1457
+ tileCoord: {
1458
+ x: x,
1459
+ y: y,
1460
+ z: z
1461
+ },
1462
+ tileSize: 0
1463
+ }));
1314
1464
  case 26:
1315
1465
  case "end":
1316
1466
  return _context.stop();
1317
1467
  }
1318
- }, _callee, this, [[0, 22]]);
1468
+ }, _callee, this, [[4, 23]]);
1319
1469
  }));
1320
- function processTile(_x, _x2, _x3) {
1470
+ function processTile(_x) {
1321
1471
  return _processTile.apply(this, arguments);
1322
1472
  }
1323
1473
  return processTile;
@@ -1373,10 +1523,8 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1373
1523
  if (halfAngle > Math.PI / 4) {
1374
1524
  occlusionHeight = (1 + halfAngle) * this.ellipsoid.maximumRadius;
1375
1525
  }
1376
- var occlusionPoint = new Cartographic(center.longitude, center.latitude, occlusionHeight
1377
- // Scaling factor of two just to be sure.
1378
- );
1379
-
1526
+ var occlusionPoint = new Cartographic(center.longitude, center.latitude, occlusionHeight) // Scaling factor of two just to be sure.
1527
+ ;
1380
1528
  var horizonOcclusionPoint = this.ellipsoid.transformPositionToScaledSpace(Cartographic.toCartesian(occlusionPoint));
1381
1529
  var orientedBoundingBox = OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, this.tilingScheme.ellipsoid);
1382
1530
  var boundingSphere = BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox);
@@ -1384,7 +1532,8 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1384
1532
  // SE NW NE
1385
1533
  // NE NW SE
1386
1534
 
1387
- var result = new QuantizedMeshTerrainData({
1535
+ /** TODO: we need to create raster terrain data. */
1536
+ return new QuantizedMeshTerrainData({
1388
1537
  minimumHeight: minimumHeight,
1389
1538
  maximumHeight: maximumHeight,
1390
1539
  quantizedVertices: quantizedVertices,
@@ -1402,16 +1551,21 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1402
1551
  northSkirtHeight: skirtHeight,
1403
1552
  childTileMask: 15
1404
1553
  });
1405
- return result;
1406
1554
  }
1407
1555
  }, {
1408
1556
  key: "getLevelMaximumGeometricError",
1409
1557
  value: function getLevelMaximumGeometricError(level) {
1410
1558
  var levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this.tilingScheme.ellipsoid, 65, this.tilingScheme.getNumberOfXTilesAtLevel(0));
1411
1559
 
1412
- // Scalar to control overzooming
1413
- // also seems to control zooming for imagery layers
1414
- var scalar = this.resource.tileSize / 256;
1560
+ /*
1561
+ Scalar to control overzooming
1562
+ - also seems to control zooming for imagery layers
1563
+ - This scalar was causing trouble for non-256 tile sizes,
1564
+ and we've removed it for now. It could be reintroduced
1565
+ if it seems necessary
1566
+ */
1567
+ var scalar = 1; //this.resource.tileSize / 256 ;
1568
+
1415
1569
  return levelZeroMaximumGeometricError / scalar / (1 << level);
1416
1570
  }
1417
1571
  }, {
@@ -1424,21 +1578,27 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1424
1578
  });
1425
1579
  }
1426
1580
  }]);
1427
- return MartiniTerrainProvider;
1428
1581
  }();
1582
+
1583
+ var WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkociwgYSkgewogICAgKG51bGwgPT0gYSB8fCBhID4gci5sZW5ndGgpICYmIChhID0gci5sZW5ndGgpOwogICAgZm9yICh2YXIgZSA9IDAsIG4gPSBBcnJheShhKTsgZSA8IGE7IGUrKykgbltlXSA9IHJbZV07CiAgICByZXR1cm4gbjsKICB9CiAgZnVuY3Rpb24gX2FycmF5V2l0aG91dEhvbGVzKHIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KHIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkocik7CiAgfQogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkocikgewogICAgaWYgKCJ1bmRlZmluZWQiICE9IHR5cGVvZiBTeW1ib2wgJiYgbnVsbCAhPSByW1N5bWJvbC5pdGVyYXRvcl0gfHwgbnVsbCAhPSByWyJAQGl0ZXJhdG9yIl0pIHJldHVybiBBcnJheS5mcm9tKHIpOwogIH0KICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7CiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cbkluIG9yZGVyIHRvIGJlIGl0ZXJhYmxlLCBub24tYXJyYXkgb2JqZWN0cyBtdXN0IGhhdmUgYSBbU3ltYm9sLml0ZXJhdG9yXSgpIG1ldGhvZC4iKTsKICB9CiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KHIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMocikgfHwgX2l0ZXJhYmxlVG9BcnJheShyKSB8fCBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkocikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShyLCBhKSB7CiAgICBpZiAocikgewogICAgICBpZiAoInN0cmluZyIgPT0gdHlwZW9mIHIpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShyLCBhKTsKICAgICAgdmFyIHQgPSB7fS50b1N0cmluZy5jYWxsKHIpLnNsaWNlKDgsIC0xKTsKICAgICAgcmV0dXJuICJPYmplY3QiID09PSB0ICYmIHIuY29uc3RydWN0b3IgJiYgKHQgPSByLmNvbnN0cnVjdG9yLm5hbWUpLCAiTWFwIiA9PT0gdCB8fCAiU2V0IiA9PT0gdCA/IEFycmF5LmZyb20ocikgOiAiQXJndW1lbnRzIiA9PT0gdCB8fCAvXig/OlVpfEkpbnQoPzo4fDE2fDMyKSg/OkNsYW1wZWQpP0FycmF5JC8udGVzdCh0KSA/IF9hcnJheUxpa2VUb0FycmF5KHIsIGEpIDogdm9pZCAwOwogICAgfQogIH0KCiAgLyoqIE1hcGJveCBUZXJyYWluLVJHQiBkZWZhdWx0IGRlY29kZSBmdW5jdGlvbgogICAqICAociAqIDI1NiAqIDI1NikgLyAxMCArIChnICogMjU2KSAvIDEwICsgYiAvIDEwIC0gMTAwMDAKICAgKi8KICB2YXIgZGVmYXVsdE1hcGJveERlY29kZVJnYiA9IGZ1bmN0aW9uIGRlZmF1bHRNYXBib3hEZWNvZGVSZ2IociwgZywgYiwgYSkgewogICAgcmV0dXJuIHIgKiA2NTUzLjYgKyBnICogMjUuNiArIGIgKiAwLjEgLSAxMDAwMDsKICB9OwogIGZ1bmN0aW9uIHJnYlRlcnJhaW5Ub0dyaWQocG5nLCBkZWNvZGVSZ2IpIHsKICAgIC8vIG1heWJlIHdlIHNob3VsZCBkbyB0aGlzIG9uIHRoZSBHUFUgdXNpbmcgUkVHTD8KICAgIC8vIGJ1dCB0aGF0IHdvdWxkIHJlcXVpcmUgR1BVIC0+IENQVSAtPiBHUFUKICAgIHZhciBncmlkU2l6ZSA9IHBuZy5zaGFwZVswXSArIDE7CiAgICB2YXIgdGVycmFpbiA9IG5ldyBGbG9hdDMyQXJyYXkoZ3JpZFNpemUgKiBncmlkU2l6ZSk7CiAgICB2YXIgdGlsZVNpemUgPSBwbmcuc2hhcGVbMF07CiAgICB2YXIgZGVjb2RlID0gZGVjb2RlUmdiICE9PSBudWxsICYmIGRlY29kZVJnYiAhPT0gdm9pZCAwID8gZGVjb2RlUmdiIDogZGVmYXVsdE1hcGJveERlY29kZVJnYjsKCiAgICAvLyBkZWNvZGUgdGVycmFpbiB2YWx1ZXMKICAgIGZvciAodmFyIHkgPSAwOyB5IDwgdGlsZVNpemU7IHkrKykgewogICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IHRpbGVTaXplOyB4KyspIHsKICAgICAgICB2YXIgeWMgPSB5OwogICAgICAgIHZhciBfciA9IHBuZy5nZXQoeCwgeWMsIDApOwogICAgICAgIHZhciBfZyA9IHBuZy5nZXQoeCwgeWMsIDEpOwogICAgICAgIHZhciBfYiA9IHBuZy5nZXQoeCwgeWMsIDIpOwogICAgICAgIHZhciBfYSA9IHBuZy5nZXQoeCwgeWMsIDMpOwogICAgICAgIHRlcnJhaW5beSAqIGdyaWRTaXplICsgeF0gPSBkZWNvZGUoX3IsIF9nLCBfYiwgX2EpOwogICAgICB9CiAgICB9CiAgICAvLyBiYWNrZmlsbCByaWdodCBhbmQgYm90dG9tIGJvcmRlcnMKICAgIGZvciAodmFyIF94ID0gMDsgX3ggPCBncmlkU2l6ZSAtIDE7IF94KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDEpICsgX3hdID0gdGVycmFpbltncmlkU2l6ZSAqIChncmlkU2l6ZSAtIDIpICsgX3hdOwogICAgfQogICAgZm9yICh2YXIgX3kgPSAwOyBfeSA8IGdyaWRTaXplOyBfeSsrKSB7CiAgICAgIHRlcnJhaW5bZ3JpZFNpemUgKiBfeSArIGdyaWRTaXplIC0gMV0gPSB0ZXJyYWluW2dyaWRTaXplICogX3kgKyBncmlkU2l6ZSAtIDJdOwogICAgfQogICAgcmV0dXJuIHRlcnJhaW47CiAgfQoKICAvKiogVGVycmFpbiB3b3JrZXJzIHNob3VsZCByZXR1cm4gYSBxdWFudGl6ZWQgbWVzaCAqLwoKICBmdW5jdGlvbiBjcmVhdGVRdWFudGl6ZWRNZXNoRGF0YSh0aWxlLCBtZXNoLCB0aWxlU2l6ZSwgdGVycmFpbikgewogICAgLyoqIFRlcnJhaW4gaXMgcGFzc2VkIHRocm91Z2ggc28gd2UgY2FuIGtlZXAgdHJhY2sgb2YgaXQKICAgICAqIGZvciBvdmVyc2NhbGVkIHRpbGVzCiAgICAgKi8KCiAgICB2YXIgeHZhbHMgPSBbXTsKICAgIHZhciB5dmFscyA9IFtdOwogICAgdmFyIGhlaWdodE1ldGVycyA9IFtdOwogICAgdmFyIG5vcnRoSW5kaWNlcyA9IFtdOwogICAgdmFyIHNvdXRoSW5kaWNlcyA9IFtdOwogICAgdmFyIGVhc3RJbmRpY2VzID0gW107CiAgICB2YXIgd2VzdEluZGljZXMgPSBbXTsKICAgIHZhciBtaW5pbXVtSGVpZ2h0ID0gSW5maW5pdHk7CiAgICB2YXIgbWF4aW11bUhlaWdodCA9IC1JbmZpbml0eTsKICAgIHZhciBzY2FsYXIgPSAzMjc2OC4wIC8gdGlsZVNpemU7CgogICAgLy8gVGhlcmUgYXBwZWFycyB0byBiZSBhIHByb2JsZW0gd2l0aCB0aGUgeC95IGluZGV4aW5nIHdoZW4gdXNpbmcgNTEyeDUxMiB0aWxlcwogICAgLy8gVGhpcyBtYXkgYmUgc29sdmVkIGJ5IGluY3JlYXNpbmcgdGhlIG1pbnVtdW1FcnJvckxldmVsIGluIHRoZSB0ZXJyYWluIHByb3ZpZGVyCiAgICBmb3IgKHZhciBpeCA9IDA7IGl4IDwgbWVzaC52ZXJ0aWNlcy5sZW5ndGggLyAyOyBpeCsrKSB7CiAgICAgIHZhciB2ZXJ0ZXhJeCA9IGl4OwogICAgICB2YXIgcHggPSBtZXNoLnZlcnRpY2VzW2l4ICogMl07CiAgICAgIHZhciBweSA9IG1lc2gudmVydGljZXNbaXggKiAyICsgMV07CiAgICAgIHZhciBoZWlnaHQgPSB0aWxlLnRlcnJhaW5bcHkgKiAodGlsZVNpemUgKyAxKSArIHB4XTsKICAgICAgaWYgKGhlaWdodCA+IG1heGltdW1IZWlnaHQpIG1heGltdW1IZWlnaHQgPSBoZWlnaHQ7CiAgICAgIGlmIChoZWlnaHQgPCBtaW5pbXVtSGVpZ2h0KSBtaW5pbXVtSGVpZ2h0ID0gaGVpZ2h0OwogICAgICBoZWlnaHRNZXRlcnMucHVzaChoZWlnaHQpOwogICAgICBpZiAocHkgPT0gMCkgbm9ydGhJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICBpZiAocHkgPT0gdGlsZVNpemUpIHNvdXRoSW5kaWNlcy5wdXNoKHZlcnRleEl4KTsKICAgICAgaWYgKHB4ID09IDApIHdlc3RJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICBpZiAocHggPT0gdGlsZVNpemUpIGVhc3RJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICB2YXIgeHYgPSBweCAqIHNjYWxhcjsKICAgICAgdmFyIHl2ID0gKHRpbGVTaXplIC0gcHkpICogc2NhbGFyOwogICAgICB4dmFscy5wdXNoKHh2KTsKICAgICAgeXZhbHMucHVzaCh5dik7CiAgICB9CiAgICB2YXIgaGVpZ2h0UmFuZ2UgPSBtYXhpbXVtSGVpZ2h0IC0gbWluaW11bUhlaWdodDsKICAgIHZhciBoZWlnaHRzID0gaGVpZ2h0TWV0ZXJzLm1hcChmdW5jdGlvbiAoZCkgewogICAgICBpZiAoaGVpZ2h0UmFuZ2UgPCAxKSByZXR1cm4gMDsKICAgICAgcmV0dXJuIChkIC0gbWluaW11bUhlaWdodCkgKiAoMzI3NjguMCAvIGhlaWdodFJhbmdlKTsKICAgIH0pOwogICAgdmFyIHRyaWFuZ2xlcyA9IG5ldyBVaW50MTZBcnJheShtZXNoLnRyaWFuZ2xlcyk7CiAgICB2YXIgcXVhbnRpemVkVmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkoLy92ZXJ0cwogICAgW10uY29uY2F0KHh2YWxzLCB5dmFscywgX3RvQ29uc3VtYWJsZUFycmF5KGhlaWdodHMpKSk7CgogICAgLy8gU0UgTlcgTkUKICAgIC8vIE5FIE5XIFNFCgogICAgcmV0dXJuIHsKICAgICAgbWluaW11bUhlaWdodDogbWluaW11bUhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodDogbWF4aW11bUhlaWdodCwKICAgICAgcXVhbnRpemVkVmVydGljZXM6IHF1YW50aXplZFZlcnRpY2VzLAogICAgICBpbmRpY2VzOiB0cmlhbmdsZXMsCiAgICAgIHdlc3RJbmRpY2VzOiB3ZXN0SW5kaWNlcywKICAgICAgc291dGhJbmRpY2VzOiBzb3V0aEluZGljZXMsCiAgICAgIGVhc3RJbmRpY2VzOiBlYXN0SW5kaWNlcywKICAgICAgbm9ydGhJbmRpY2VzOiBub3J0aEluZGljZXMsCiAgICAgIHF1YW50aXplZEhlaWdodHM6IHRlcnJhaW4KICAgIH07CiAgfQoKICBmdW5jdGlvbiBpb3RhKG4pIHsKICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobik7CiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHsKICAgICAgcmVzdWx0W2ldID0gaTsKICAgIH0KICAgIHJldHVybiByZXN1bHQKICB9CgogIHZhciBpb3RhXzEgPSBpb3RhOwoKICAvKiEKICAgKiBEZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGEgQnVmZmVyCiAgICoKICAgKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8aHR0cHM6Ly9mZXJvc3Mub3JnPgogICAqIEBsaWNlbnNlICBNSVQKICAgKi8KICAvLyBUaGUgX2lzQnVmZmVyIGNoZWNrIGlzIGZvciBTYWZhcmkgNS03IHN1cHBvcnQsIGJlY2F1c2UgaXQncyBtaXNzaW5nCiAgLy8gT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseQogIHZhciBpc0J1ZmZlcl8xID0gZnVuY3Rpb24gKG9iaikgewogICAgcmV0dXJuIG9iaiAhPSBudWxsICYmIChpc0J1ZmZlcihvYmopIHx8IGlzU2xvd0J1ZmZlcihvYmopIHx8ICEhb2JqLl9pc0J1ZmZlcikKICB9OwoKICBmdW5jdGlvbiBpc0J1ZmZlciAob2JqKSB7CiAgICByZXR1cm4gISFvYmouY29uc3RydWN0b3IgJiYgdHlwZW9mIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKQogIH0KCiAgLy8gRm9yIE5vZGUgdjAuMTAgc3VwcG9ydC4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseS4KICBmdW5jdGlvbiBpc1Nsb3dCdWZmZXIgKG9iaikgewogICAgcmV0dXJuIHR5cGVvZiBvYmoucmVhZEZsb2F0TEUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIG9iai5zbGljZSA9PT0gJ2Z1bmN0aW9uJyAmJiBpc0J1ZmZlcihvYmouc2xpY2UoMCwgMCkpCiAgfQoKICB2YXIgaGFzVHlwZWRBcnJheXMgID0gKCh0eXBlb2YgRmxvYXQ2NEFycmF5KSAhPT0gInVuZGVmaW5lZCIpOwoKICBmdW5jdGlvbiBjb21wYXJlMXN0KGEsIGIpIHsKICAgIHJldHVybiBhWzBdIC0gYlswXQogIH0KCiAgZnVuY3Rpb24gb3JkZXIoKSB7CiAgICB2YXIgc3RyaWRlID0gdGhpcy5zdHJpZGU7CiAgICB2YXIgdGVybXMgPSBuZXcgQXJyYXkoc3RyaWRlLmxlbmd0aCk7CiAgICB2YXIgaTsKICAgIGZvcihpPTA7IGk8dGVybXMubGVuZ3RoOyArK2kpIHsKICAgICAgdGVybXNbaV0gPSBbTWF0aC5hYnMoc3RyaWRlW2ldKSwgaV07CiAgICB9CiAgICB0ZXJtcy5zb3J0KGNvbXBhcmUxc3QpOwogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh0ZXJtcy5sZW5ndGgpOwogICAgZm9yKGk9MDsgaTxyZXN1bHQubGVuZ3RoOyArK2kpIHsKICAgICAgcmVzdWx0W2ldID0gdGVybXNbaV1bMV07CiAgICB9CiAgICByZXR1cm4gcmVzdWx0CiAgfQoKICBmdW5jdGlvbiBjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGRpbWVuc2lvbikgewogICAgdmFyIGNsYXNzTmFtZSA9IFsiVmlldyIsIGRpbWVuc2lvbiwgImQiLCBkdHlwZV0uam9pbigiIik7CiAgICBpZihkaW1lbnNpb24gPCAwKSB7CiAgICAgIGNsYXNzTmFtZSA9ICJWaWV3X05pbCIgKyBkdHlwZTsKICAgIH0KICAgIHZhciB1c2VHZXR0ZXJzID0gKGR0eXBlID09PSAiZ2VuZXJpYyIpOwoKICAgIGlmKGRpbWVuc2lvbiA9PT0gLTEpIHsKICAgICAgLy9TcGVjaWFsIGNhc2UgZm9yIHRyaXZpYWwgYXJyYXlzCiAgICAgIHZhciBjb2RlID0KICAgICAgICAiZnVuY3Rpb24gIitjbGFzc05hbWUrIihhKXt0aGlzLmRhdGE9YTt9O1wKdmFyIHByb3RvPSIrY2xhc3NOYW1lKyIucHJvdG90eXBlO1wKcHJvdG8uZHR5cGU9JyIrZHR5cGUrIic7XApwcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiAtMX07XApwcm90by5zaXplPTA7XApwcm90by5kaW1lbnNpb249LTE7XApwcm90by5zaGFwZT1wcm90by5zdHJpZGU9cHJvdG8ub3JkZXI9W107XApwcm90by5sbz1wcm90by5oaT1wcm90by50cmFuc3Bvc2U9cHJvdG8uc3RlcD1cCmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKHRoaXMuZGF0YSk7fTtcCnByb3RvLmdldD1wcm90by5zZXQ9ZnVuY3Rpb24oKXt9O1wKcHJvdG8ucGljaz1mdW5jdGlvbigpe3JldHVybiBudWxsfTtcCnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfIitjbGFzc05hbWUrIihhKXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIoYSk7fSI7CiAgICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oY29kZSk7CiAgICAgIHJldHVybiBwcm9jZWR1cmUoKQogICAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMCkgewogICAgICAvL1NwZWNpYWwgY2FzZSBmb3IgMGQgYXJyYXlzCiAgICAgIHZhciBjb2RlID0KICAgICAgICAiZnVuY3Rpb24gIitjbGFzc05hbWUrIihhLGQpIHtcCnRoaXMuZGF0YSA9IGE7XAp0aGlzLm9mZnNldCA9IGRcCn07XAp2YXIgcHJvdG89IitjbGFzc05hbWUrIi5wcm90b3R5cGU7XApwcm90by5kdHlwZT0nIitkdHlwZSsiJztcCnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMub2Zmc2V0fTtcCnByb3RvLmRpbWVuc2lvbj0wO1wKcHJvdG8uc2l6ZT0xO1wKcHJvdG8uc2hhcGU9XApwcm90by5zdHJpZGU9XApwcm90by5vcmRlcj1bXTtcCnByb3RvLmxvPVwKcHJvdG8uaGk9XApwcm90by50cmFuc3Bvc2U9XApwcm90by5zdGVwPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfY29weSgpIHtcCnJldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEsdGhpcy5vZmZzZXQpXAp9O1wKcHJvdG8ucGljaz1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3BpY2soKXtcCnJldHVybiBUcml2aWFsQXJyYXkodGhpcy5kYXRhKTtcCn07XApwcm90by52YWx1ZU9mPXByb3RvLmdldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX2dldCgpe1wKcmV0dXJuICIrKHVzZUdldHRlcnMgPyAidGhpcy5kYXRhLmdldCh0aGlzLm9mZnNldCkiIDogInRoaXMuZGF0YVt0aGlzLm9mZnNldF0iKSsKICAifTtcCnByb3RvLnNldD1mdW5jdGlvbiAiK2NsYXNzTmFtZSsiX3NldCh2KXtcCnJldHVybiAiKyh1c2VHZXR0ZXJzID8gInRoaXMuZGF0YS5zZXQodGhpcy5vZmZzZXQsdikiIDogInRoaXMuZGF0YVt0aGlzLm9mZnNldF09diIpKyJcCn07XApyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIrY2xhc3NOYW1lKyIoYSxiLGMsZCl7cmV0dXJuIG5ldyAiK2NsYXNzTmFtZSsiKGEsZCl9IjsKICAgICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbigiVHJpdmlhbEFycmF5IiwgY29kZSk7CiAgICAgIHJldHVybiBwcm9jZWR1cmUoQ0FDSEVEX0NPTlNUUlVDVE9SU1tkdHlwZV1bMF0pCiAgICB9CgogICAgdmFyIGNvZGUgPSBbIid1c2Ugc3RyaWN0JyJdOwoKICAgIC8vQ3JlYXRlIGNvbnN0cnVjdG9yIGZvciB2aWV3CiAgICB2YXIgaW5kaWNlcyA9IGlvdGFfMShkaW1lbnNpb24pOwogICAgdmFyIGFyZ3MgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiAiaSIraSB9KTsKICAgIHZhciBpbmRleF9zdHIgPSAidGhpcy5vZmZzZXQrIiArIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICAgIHJldHVybiAidGhpcy5zdHJpZGVbIiArIGkgKyAiXSppIiArIGkKICAgICAgICB9KS5qb2luKCIrIik7CiAgICB2YXIgc2hhcGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJiIitpCiAgICAgIH0pLmpvaW4oIiwiKTsKICAgIHZhciBzdHJpZGVBcmcgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJjIitpCiAgICAgIH0pLmpvaW4oIiwiKTsKICAgIGNvZGUucHVzaCgKICAgICAgImZ1bmN0aW9uICIrY2xhc3NOYW1lKyIoYSwiICsgc2hhcGVBcmcgKyAiLCIgKyBzdHJpZGVBcmcgKyAiLGQpe3RoaXMuZGF0YT1hIiwKICAgICAgICAidGhpcy5zaGFwZT1bIiArIHNoYXBlQXJnICsgIl0iLAogICAgICAgICJ0aGlzLnN0cmlkZT1bIiArIHN0cmlkZUFyZyArICJdIiwKICAgICAgICAidGhpcy5vZmZzZXQ9ZHwwfSIsCiAgICAgICJ2YXIgcHJvdG89IitjbGFzc05hbWUrIi5wcm90b3R5cGUiLAogICAgICAicHJvdG8uZHR5cGU9JyIrZHR5cGUrIiciLAogICAgICAicHJvdG8uZGltZW5zaW9uPSIrZGltZW5zaW9uKTsKCiAgICAvL3ZpZXcuc2l6ZToKICAgIGNvZGUucHVzaCgiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdzaXplJyx7Z2V0OmZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfc2l6ZSgpe1wKcmV0dXJuICIraW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gInRoaXMuc2hhcGVbIitpKyJdIiB9KS5qb2luKCIqIiksCiAgIn19KSIpOwoKICAgIC8vdmlldy5vcmRlcjoKICAgIGlmKGRpbWVuc2lvbiA9PT0gMSkgewogICAgICBjb2RlLnB1c2goInByb3RvLm9yZGVyPVswXSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ29yZGVyJyx7Z2V0OiIpOwogICAgICBpZihkaW1lbnNpb24gPCA0KSB7CiAgICAgICAgY29kZS5wdXNoKCJmdW5jdGlvbiAiK2NsYXNzTmFtZSsiX29yZGVyKCl7Iik7CiAgICAgICAgaWYoZGltZW5zaW9uID09PSAyKSB7CiAgICAgICAgICBjb2RlLnB1c2goInJldHVybiAoTWF0aC5hYnModGhpcy5zdHJpZGVbMF0pPk1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSk/WzEsMF06WzAsMV19fSkiKTsKICAgICAgICB9IGVsc2UgaWYoZGltZW5zaW9uID09PSAzKSB7CiAgICAgICAgICBjb2RlLnB1c2goCiAgInZhciBzMD1NYXRoLmFicyh0aGlzLnN0cmlkZVswXSksczE9TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pLHMyPU1hdGguYWJzKHRoaXMuc3RyaWRlWzJdKTtcCmlmKHMwPnMxKXtcCmlmKHMxPnMyKXtcCnJldHVybiBbMiwxLDBdO1wKfWVsc2UgaWYoczA+czIpe1wKcmV0dXJuIFsxLDIsMF07XAp9ZWxzZXtcCnJldHVybiBbMSwwLDJdO1wKfVwKfWVsc2UgaWYoczA+czIpe1wKcmV0dXJuIFsyLDAsMV07XAp9ZWxzZSBpZihzMj5zMSl7XApyZXR1cm4gWzAsMSwyXTtcCn1lbHNle1wKcmV0dXJuIFswLDIsMV07XAp9fX0pIik7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGNvZGUucHVzaCgiT1JERVJ9KSIpOwogICAgICB9CiAgICB9CgogICAgLy92aWV3LnNldChpMCwgLi4uLCB2KToKICAgIGNvZGUucHVzaCgKICAicHJvdG8uc2V0PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfc2V0KCIrYXJncy5qb2luKCIsIikrIix2KXsiKTsKICAgIGlmKHVzZUdldHRlcnMpIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhLnNldCgiK2luZGV4X3N0cisiLHYpfSIpOwogICAgfSBlbHNlIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhWyIraW5kZXhfc3RyKyJdPXZ9Iik7CiAgICB9CgogICAgLy92aWV3LmdldChpMCwgLi4uKToKICAgIGNvZGUucHVzaCgicHJvdG8uZ2V0PWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfZ2V0KCIrYXJncy5qb2luKCIsIikrIil7Iik7CiAgICBpZih1c2VHZXR0ZXJzKSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YS5nZXQoIitpbmRleF9zdHIrIil9Iik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGFbIitpbmRleF9zdHIrIl19Iik7CiAgICB9CgogICAgLy92aWV3LmluZGV4OgogICAgY29kZS5wdXNoKAogICAgICAicHJvdG8uaW5kZXg9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9pbmRleCgiLCBhcmdzLmpvaW4oKSwgIil7cmV0dXJuICIraW5kZXhfc3RyKyJ9Iik7CgogICAgLy92aWV3LmhpKCk6CiAgICBjb2RlLnB1c2goInByb3RvLmhpPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfaGkoIithcmdzLmpvaW4oIiwiKSsiKXtyZXR1cm4gbmV3ICIrY2xhc3NOYW1lKyIodGhpcy5kYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gWyIodHlwZW9mIGkiLGksIiE9PSdudW1iZXInfHxpIixpLCI8MCk/dGhpcy5zaGFwZVsiLCBpLCAiXTppIiwgaSwifDAiXS5qb2luKCIiKQogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJ0aGlzLnN0cmlkZVsiK2kgKyAiXSIKICAgICAgfSkuam9pbigiLCIpKyIsdGhpcy5vZmZzZXQpfSIpOwoKICAgIC8vdmlldy5sbygpOgogICAgdmFyIGFfdmFycyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuICJhIitpKyI9dGhpcy5zaGFwZVsiK2krIl0iIH0pOwogICAgdmFyIGNfdmFycyA9IGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsgcmV0dXJuICJjIitpKyI9dGhpcy5zdHJpZGVbIitpKyJdIiB9KTsKICAgIGNvZGUucHVzaCgicHJvdG8ubG89ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9sbygiK2FyZ3Muam9pbigiLCIpKyIpe3ZhciBiPXRoaXMub2Zmc2V0LGQ9MCwiK2FfdmFycy5qb2luKCIsIikrIiwiK2NfdmFycy5qb2luKCIsIikpOwogICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKAogICJpZih0eXBlb2YgaSIraSsiPT09J251bWJlcicmJmkiK2krIj49MCl7XApkPWkiK2krInwwO1wKYis9YyIraSsiKmQ7XAphIitpKyItPWR9Iik7CiAgICB9CiAgICBjb2RlLnB1c2goInJldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYSIraQogICAgICB9KS5qb2luKCIsIikrIiwiKwogICAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7CiAgICAgICAgcmV0dXJuICJjIitpCiAgICAgIH0pLmpvaW4oIiwiKSsiLGIpfSIpOwoKICAgIC8vdmlldy5zdGVwKCk6CiAgICBjb2RlLnB1c2goInByb3RvLnN0ZXA9ZnVuY3Rpb24gIitjbGFzc05hbWUrIl9zdGVwKCIrYXJncy5qb2luKCIsIikrIil7dmFyICIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImEiK2krIj10aGlzLnNoYXBlWyIraSsiXSIKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYiIraSsiPXRoaXMuc3RyaWRlWyIraSsiXSIKICAgICAgfSkuam9pbigiLCIpKyIsYz10aGlzLm9mZnNldCxkPTAsY2VpbD1NYXRoLmNlaWwiKTsKICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgKICAiaWYodHlwZW9mIGkiK2krIj09PSdudW1iZXInKXtcCmQ9aSIraSsifDA7XAppZihkPDApe1wKYys9YiIraSsiKihhIitpKyItMSk7XAphIitpKyI9Y2VpbCgtYSIraSsiL2QpXAp9ZWxzZXtcCmEiK2krIj1jZWlsKGEiK2krIi9kKVwKfVwKYiIraSsiKj1kXAp9Iik7CiAgICB9CiAgICBjb2RlLnB1c2goInJldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAiYSIgKyBpCiAgICAgIH0pLmpvaW4oIiwiKSsiLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gImIiICsgaQogICAgICB9KS5qb2luKCIsIikrIixjKX0iKTsKCiAgICAvL3ZpZXcudHJhbnNwb3NlKCk6CiAgICB2YXIgdFNoYXBlID0gbmV3IEFycmF5KGRpbWVuc2lvbik7CiAgICB2YXIgdFN0cmlkZSA9IG5ldyBBcnJheShkaW1lbnNpb24pOwogICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsKICAgICAgdFNoYXBlW2ldID0gImFbaSIraSsiXSI7CiAgICAgIHRTdHJpZGVbaV0gPSAiYltpIitpKyJdIjsKICAgIH0KICAgIGNvZGUucHVzaCgicHJvdG8udHJhbnNwb3NlPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfdHJhbnNwb3NlKCIrYXJncysiKXsiKwogICAgICBhcmdzLm1hcChmdW5jdGlvbihuLGlkeCkgeyByZXR1cm4gbiArICI9KCIgKyBuICsgIj09PXVuZGVmaW5lZD8iICsgaWR4ICsgIjoiICsgbiArICJ8MCkifSkuam9pbigiOyIpLAogICAgICAidmFyIGE9dGhpcy5zaGFwZSxiPXRoaXMuc3RyaWRlO3JldHVybiBuZXcgIitjbGFzc05hbWUrIih0aGlzLmRhdGEsIit0U2hhcGUuam9pbigiLCIpKyIsIit0U3RyaWRlLmpvaW4oIiwiKSsiLHRoaXMub2Zmc2V0KX0iKTsKCiAgICAvL3ZpZXcucGljaygpOgogICAgY29kZS5wdXNoKCJwcm90by5waWNrPWZ1bmN0aW9uICIrY2xhc3NOYW1lKyJfcGljaygiK2FyZ3MrIil7dmFyIGE9W10sYj1bXSxjPXRoaXMub2Zmc2V0Iik7CiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goImlmKHR5cGVvZiBpIitpKyI9PT0nbnVtYmVyJyYmaSIraSsiPj0wKXtjPShjK3RoaXMuc3RyaWRlWyIraSsiXSppIitpKyIpfDB9ZWxzZXthLnB1c2godGhpcy5zaGFwZVsiK2krIl0pO2IucHVzaCh0aGlzLnN0cmlkZVsiK2krIl0pfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJ2YXIgY3Rvcj1DVE9SX0xJU1RbYS5sZW5ndGgrMV07cmV0dXJuIGN0b3IodGhpcy5kYXRhLGEsYixjKX0iKTsKCiAgICAvL0FkZCByZXR1cm4gc3RhdGVtZW50CiAgICBjb2RlLnB1c2goInJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfIitjbGFzc05hbWUrIihkYXRhLHNoYXBlLHN0cmlkZSxvZmZzZXQpe3JldHVybiBuZXcgIitjbGFzc05hbWUrIihkYXRhLCIrCiAgICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHsKICAgICAgICByZXR1cm4gInNoYXBlWyIraSsiXSIKICAgICAgfSkuam9pbigiLCIpKyIsIisKICAgICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgewogICAgICAgIHJldHVybiAic3RyaWRlWyIraSsiXSIKICAgICAgfSkuam9pbigiLCIpKyIsb2Zmc2V0KX0iKTsKCiAgICAvL0NvbXBpbGUgcHJvY2VkdXJlCiAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKCJDVE9SX0xJU1QiLCAiT1JERVIiLCBjb2RlLmpvaW4oIlxuIikpOwogICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXSwgb3JkZXIpCiAgfQoKICBmdW5jdGlvbiBhcnJheURUeXBlKGRhdGEpIHsKICAgIGlmKGlzQnVmZmVyXzEoZGF0YSkpIHsKICAgICAgcmV0dXJuICJidWZmZXIiCiAgICB9CiAgICBpZihoYXNUeXBlZEFycmF5cykgewogICAgICBzd2l0Y2goT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGEpKSB7CiAgICAgICAgY2FzZSAiW29iamVjdCBGbG9hdDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiZmxvYXQ2NCIKICAgICAgICBjYXNlICJbb2JqZWN0IEZsb2F0MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJmbG9hdDMyIgogICAgICAgIGNhc2UgIltvYmplY3QgSW50OEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImludDgiCiAgICAgICAgY2FzZSAiW29iamVjdCBJbnQxNkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImludDE2IgogICAgICAgIGNhc2UgIltvYmplY3QgSW50MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQzMiIKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQ4QXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDgiCiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50MTZBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50MTYiCiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50MzJBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50MzIiCiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50OF9jbGFtcGVkIgogICAgICAgIGNhc2UgIltvYmplY3QgQmlnSW50NjRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJiaWdpbnQ2NCIKICAgICAgICBjYXNlICJbb2JqZWN0IEJpZ1VpbnQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImJpZ3VpbnQ2NCIKICAgICAgfQogICAgfQogICAgaWYoQXJyYXkuaXNBcnJheShkYXRhKSkgewogICAgICByZXR1cm4gImFycmF5IgogICAgfQogICAgcmV0dXJuICJnZW5lcmljIgogIH0KCiAgdmFyIENBQ0hFRF9DT05TVFJVQ1RPUlMgPSB7CiAgICAiZmxvYXQzMiI6W10sCiAgICAiZmxvYXQ2NCI6W10sCiAgICAiaW50OCI6W10sCiAgICAiaW50MTYiOltdLAogICAgImludDMyIjpbXSwKICAgICJ1aW50OCI6W10sCiAgICAidWludDE2IjpbXSwKICAgICJ1aW50MzIiOltdLAogICAgImFycmF5IjpbXSwKICAgICJ1aW50OF9jbGFtcGVkIjpbXSwKICAgICJiaWdpbnQ2NCI6IFtdLAogICAgImJpZ3VpbnQ2NCI6IFtdLAogICAgImJ1ZmZlciI6W10sCiAgICAiZ2VuZXJpYyI6W10KICB9CgogIDsKICBmdW5jdGlvbiB3cmFwcGVkTkRBcnJheUN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KSB7CiAgICBpZihkYXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIGN0b3IgPSBDQUNIRURfQ09OU1RSVUNUT1JTLmFycmF5WzBdOwogICAgICByZXR1cm4gY3RvcihbXSkKICAgIH0gZWxzZSBpZih0eXBlb2YgZGF0YSA9PT0gIm51bWJlciIpIHsKICAgICAgZGF0YSA9IFtkYXRhXTsKICAgIH0KICAgIGlmKHNoYXBlID09PSB1bmRlZmluZWQpIHsKICAgICAgc2hhcGUgPSBbIGRhdGEubGVuZ3RoIF07CiAgICB9CiAgICB2YXIgZCA9IHNoYXBlLmxlbmd0aDsKICAgIGlmKHN0cmlkZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHN0cmlkZSA9IG5ldyBBcnJheShkKTsKICAgICAgZm9yKHZhciBpPWQtMSwgc3o9MTsgaT49MDsgLS1pKSB7CiAgICAgICAgc3RyaWRlW2ldID0gc3o7CiAgICAgICAgc3ogKj0gc2hhcGVbaV07CiAgICAgIH0KICAgIH0KICAgIGlmKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIG9mZnNldCA9IDA7CiAgICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkgewogICAgICAgIGlmKHN0cmlkZVtpXSA8IDApIHsKICAgICAgICAgIG9mZnNldCAtPSAoc2hhcGVbaV0tMSkqc3RyaWRlW2ldOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdmFyIGR0eXBlID0gYXJyYXlEVHlwZShkYXRhKTsKICAgIHZhciBjdG9yX2xpc3QgPSBDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXTsKICAgIHdoaWxlKGN0b3JfbGlzdC5sZW5ndGggPD0gZCsxKSB7CiAgICAgIGN0b3JfbGlzdC5wdXNoKGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgY3Rvcl9saXN0Lmxlbmd0aC0xKSk7CiAgICB9CiAgICB2YXIgY3RvciA9IGN0b3JfbGlzdFtkKzFdOwogICAgcmV0dXJuIGN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KQogIH0KCiAgdmFyIG5kYXJyYXkgPSB3cmFwcGVkTkRBcnJheUN0b3I7CgogIGNsYXNzIE1hcnRpbmkgewogICAgICBjb25zdHJ1Y3RvcihncmlkU2l6ZSA9IDI1NykgewogICAgICAgICAgdGhpcy5ncmlkU2l6ZSA9IGdyaWRTaXplOwogICAgICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgICAgICBpZiAodGlsZVNpemUgJiAodGlsZVNpemUgLSAxKSkgdGhyb3cgbmV3IEVycm9yKAogICAgICAgICAgICAgIGBFeHBlY3RlZCBncmlkIHNpemUgdG8gYmUgMl5uKzEsIGdvdCAke2dyaWRTaXplfS5gKTsKCiAgICAgICAgICB0aGlzLm51bVRyaWFuZ2xlcyA9IHRpbGVTaXplICogdGlsZVNpemUgKiAyIC0gMjsKICAgICAgICAgIHRoaXMubnVtUGFyZW50VHJpYW5nbGVzID0gdGhpcy5udW1UcmlhbmdsZXMgLSB0aWxlU2l6ZSAqIHRpbGVTaXplOwoKICAgICAgICAgIHRoaXMuaW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheSh0aGlzLmdyaWRTaXplICogdGhpcy5ncmlkU2l6ZSk7CgogICAgICAgICAgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCiAgICAgICAgICB0aGlzLmNvb3JkcyA9IG5ldyBVaW50MTZBcnJheSh0aGlzLm51bVRyaWFuZ2xlcyAqIDQpOwoKICAgICAgICAgIC8vIGdldCB0cmlhbmdsZSBjb29yZGluYXRlcyBmcm9tIGl0cyBpbmRleCBpbiBhbiBpbXBsaWNpdCBiaW5hcnkgdHJlZQogICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgICAgICAgbGV0IGlkID0gaSArIDI7CiAgICAgICAgICAgICAgbGV0IGF4ID0gMCwgYXkgPSAwLCBieCA9IDAsIGJ5ID0gMCwgY3ggPSAwLCBjeSA9IDA7CiAgICAgICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAgICAgICBieCA9IGJ5ID0gY3ggPSB0aWxlU2l6ZTsgLy8gYm90dG9tLWxlZnQgdHJpYW5nbGUKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHdoaWxlICgoaWQgPj49IDEpID4gMSkgewogICAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICAgICAgaWYgKGlkICYgMSkgeyAvLyBsZWZ0IGhhbGYKICAgICAgICAgICAgICAgICAgICAgIGJ4ID0gYXg7IGJ5ID0gYXk7CiAgICAgICAgICAgICAgICAgICAgICBheCA9IGN4OyBheSA9IGN5OwogICAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyByaWdodCBoYWxmCiAgICAgICAgICAgICAgICAgICAgICBheCA9IGJ4OyBheSA9IGJ5OwogICAgICAgICAgICAgICAgICAgICAgYnggPSBjeDsgYnkgPSBjeTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBjeCA9IG14OyBjeSA9IG15OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBrID0gaSAqIDQ7CiAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDBdID0gYXg7CiAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDFdID0gYXk7CiAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDJdID0gYng7CiAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDNdID0gYnk7CiAgICAgICAgICB9CiAgICAgIH0KCiAgICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICAgICAgcmV0dXJuIG5ldyBUaWxlKHRlcnJhaW4sIHRoaXMpOwogICAgICB9CiAgfQoKICBjbGFzcyBUaWxlIHsKICAgICAgY29uc3RydWN0b3IodGVycmFpbiwgbWFydGluaSkgewogICAgICAgICAgY29uc3Qgc2l6ZSA9IG1hcnRpbmkuZ3JpZFNpemU7CiAgICAgICAgICBpZiAodGVycmFpbi5sZW5ndGggIT09IHNpemUgKiBzaXplKSB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICAgYEV4cGVjdGVkIHRlcnJhaW4gZGF0YSBvZiBsZW5ndGggJHtzaXplICogc2l6ZX0gKCR7c2l6ZX0geCAke3NpemV9KSwgZ290ICR7dGVycmFpbi5sZW5ndGh9LmApOwoKICAgICAgICAgIHRoaXMudGVycmFpbiA9IHRlcnJhaW47CiAgICAgICAgICB0aGlzLm1hcnRpbmkgPSBtYXJ0aW5pOwogICAgICAgICAgdGhpcy5lcnJvcnMgPSBuZXcgRmxvYXQzMkFycmF5KHRlcnJhaW4ubGVuZ3RoKTsKICAgICAgICAgIHRoaXMudXBkYXRlKCk7CiAgICAgIH0KCiAgICAgIHVwZGF0ZSgpIHsKICAgICAgICAgIGNvbnN0IHtudW1UcmlhbmdsZXMsIG51bVBhcmVudFRyaWFuZ2xlcywgY29vcmRzLCBncmlkU2l6ZTogc2l6ZX0gPSB0aGlzLm1hcnRpbmk7CiAgICAgICAgICBjb25zdCB7dGVycmFpbiwgZXJyb3JzfSA9IHRoaXM7CgogICAgICAgICAgLy8gaXRlcmF0ZSBvdmVyIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMsIHN0YXJ0aW5nIGZyb20gdGhlIHNtYWxsZXN0IGxldmVsCiAgICAgICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgICAgICBjb25zdCBrID0gaSAqIDQ7CiAgICAgICAgICAgICAgY29uc3QgYXggPSBjb29yZHNbayArIDBdOwogICAgICAgICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICAgICAgICBjb25zdCBieCA9IGNvb3Jkc1trICsgMl07CiAgICAgICAgICAgICAgY29uc3QgYnkgPSBjb29yZHNbayArIDNdOwogICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgY29uc3QgbXkgPSAoYXkgKyBieSkgPj4gMTsKICAgICAgICAgICAgICBjb25zdCBjeCA9IG14ICsgbXkgLSBheTsKICAgICAgICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsKCiAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIGVycm9yIGluIHRoZSBtaWRkbGUgb2YgdGhlIGxvbmcgZWRnZSBvZiB0aGUgdHJpYW5nbGUKICAgICAgICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWRIZWlnaHQgPSAodGVycmFpbltheSAqIHNpemUgKyBheF0gKyB0ZXJyYWluW2J5ICogc2l6ZSArIGJ4XSkgLyAyOwogICAgICAgICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgICAgICAgY29uc3QgbWlkZGxlRXJyb3IgPSBNYXRoLmFicyhpbnRlcnBvbGF0ZWRIZWlnaHQgLSB0ZXJyYWluW21pZGRsZUluZGV4XSk7CgogICAgICAgICAgICAgIGVycm9yc1ttaWRkbGVJbmRleF0gPSBNYXRoLm1heChlcnJvcnNbbWlkZGxlSW5kZXhdLCBtaWRkbGVFcnJvcik7CgogICAgICAgICAgICAgIGlmIChpIDwgbnVtUGFyZW50VHJpYW5nbGVzKSB7IC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgICAgICAgICBjb25zdCBsZWZ0Q2hpbGRJbmRleCA9ICgoYXkgKyBjeSkgPj4gMSkgKiBzaXplICsgKChheCArIGN4KSA+PiAxKTsKICAgICAgICAgICAgICAgICAgY29uc3QgcmlnaHRDaGlsZEluZGV4ID0gKChieSArIGN5KSA+PiAxKSAqIHNpemUgKyAoKGJ4ICsgY3gpID4+IDEpOwogICAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgZXJyb3JzW2xlZnRDaGlsZEluZGV4XSwgZXJyb3JzW3JpZ2h0Q2hpbGRJbmRleF0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgfQoKICAgICAgZ2V0TWVzaChtYXhFcnJvciA9IDAsIG1heExlbmd0aCA9IG51bGwpIHsKICAgICAgICAgIGNvbnN0IHtncmlkU2l6ZTogc2l6ZSwgaW5kaWNlc30gPSB0aGlzLm1hcnRpbmk7CiAgICAgICAgICBjb25zdCB7ZXJyb3JzfSA9IHRoaXM7CiAgICAgICAgICBsZXQgbnVtVmVydGljZXMgPSAwOwogICAgICAgICAgbGV0IG51bVRyaWFuZ2xlcyA9IDA7CiAgICAgICAgICBjb25zdCBtYXggPSBzaXplIC0gMTsKCiAgICAgICAgICAvLyBUaGUgbWF4TGVuZ3RoIHBhcmFtZXRlciB3aWxsIGNhdXNlIHRyaWFuZ2xlcyB0byBiZSBnZW5lcmF0ZWQgdW50aWwgdGhlIGxlZ3MgYXJlIGJlbG93IHRoaXMgbGVuZ3RoCiAgICAgICAgICAvLyBJdCBpcyBtZWFudCB0byBzdXBwb3J0IGNhc2VzIHdoZXJlIGEgY2VydGFpbiBtZXNoIGRlbnNpdHkgaXMgcmVxdWlyZWQgdG8gZG8gc3BoZXJpY2FsIG1hdGggb24gZGlnaXRhbCBnbG9iZXMKICAgICAgICAgIGNvbnN0IG1heFNjYWxlID0gbWF4TGVuZ3RoIHx8IHNpemU7CgogICAgICAgICAgLy8gdXNlIGFuIGluZGV4IGdyaWQgdG8ga2VlcCB0cmFjayBvZiB2ZXJ0aWNlcyB0aGF0IHdlcmUgYWxyZWFkeSB1c2VkIHRvIGF2b2lkIGR1cGxpY2F0aW9uCiAgICAgICAgICBpbmRpY2VzLmZpbGwoMCk7CgogICAgICAgICAgLy8gcmV0cmlldmUgbWVzaCBpbiB0d28gc3RhZ2VzIHRoYXQgYm90aCB0cmF2ZXJzZSB0aGUgZXJyb3IgbWFwOgogICAgICAgICAgLy8gLSBjb3VudEVsZW1lbnRzOiBmaW5kIHVzZWQgdmVydGljZXMgKGFuZCBhc3NpZ24gZWFjaCBhbiBpbmRleCksIGFuZCBjb3VudCB0cmlhbmdsZXMgKGZvciBtaW5pbXVtIGFsbG9jYXRpb24pCiAgICAgICAgICAvLyAtIHByb2Nlc3NUcmlhbmdsZTogZmlsbCB0aGUgYWxsb2NhdGVkIHZlcnRpY2VzICYgdHJpYW5nbGVzIHR5cGVkIGFycmF5cwoKICAgICAgICAgIGZ1bmN0aW9uIGNvdW50RWxlbWVudHMoYXgsIGF5LCBieCwgYnksIGN4LCBjeSkgewogICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgY29uc3QgbXkgPSAoYXkgKyBieSkgPj4gMTsKCiAgICAgICAgICAgICAgY29uc3QgbGVnTGVuZ3RoID0gTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KTsKICAgICAgICAgICAgICBpZiAoKGxlZ0xlbmd0aCA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yKSB8fCBsZWdMZW5ndGggPiBtYXhTY2FsZSkgewogICAgICAgICAgICAgICAgICBjb3VudEVsZW1lbnRzKGN4LCBjeSwgYXgsIGF5LCBteCwgbXkpOwogICAgICAgICAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGluZGljZXNbYXkgKiBzaXplICsgYXhdID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgICAgICAgICAgaW5kaWNlc1tieSAqIHNpemUgKyBieF0gPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgICAgICAgICBpbmRpY2VzW2N5ICogc2l6ZSArIGN4XSA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICAgICAgICAgIG51bVRyaWFuZ2xlcysrOwogICAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGNvdW50RWxlbWVudHMoMCwgMCwgbWF4LCBtYXgsIG1heCwgMCk7CiAgICAgICAgICBjb3VudEVsZW1lbnRzKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwoKICAgICAgICAgIGNvbnN0IHZlcnRpY2VzID0gbmV3IFVpbnQxNkFycmF5KG51bVZlcnRpY2VzICogMik7CiAgICAgICAgICBjb25zdCB0cmlhbmdsZXMgPSBuZXcgVWludDMyQXJyYXkobnVtVHJpYW5nbGVzICogMyk7CiAgICAgICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgICAgIGZ1bmN0aW9uIHByb2Nlc3NUcmlhbmdsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgICAgICAgY29uc3QgbXggPSAoYXggKyBieCkgPj4gMTsKICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwogICAgICAgICAgICAgIGlmICgobGVnTGVuZ3RoID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IpIHx8IGxlZ0xlbmd0aCA+IG1heFNjYWxlKSB7CiAgICAgICAgICAgICAgICAgIC8vIHRyaWFuZ2xlIGRvZXNuJ3QgYXBwcm94aW1hdGUgdGhlIHN1cmZhY2Ugd2VsbCBlbm91Z2g7IGRyaWxsIGRvd24gZnVydGhlcgogICAgICAgICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICAgICAgICAgIHByb2Nlc3NUcmlhbmdsZShieCwgYnksIGN4LCBjeSwgbXgsIG15KTsKCiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgICAgICAgICAgY29uc3QgYSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIC0gMTsKICAgICAgICAgICAgICAgICAgY29uc3QgYiA9IGluZGljZXNbYnkgKiBzaXplICsgYnhdIC0gMTsKICAgICAgICAgICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKCiAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBhXSA9IGF4OwogICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYSArIDFdID0gYXk7CgogICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGIgKyAxXSA9IGJ5OwoKICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGNdID0gY3g7CiAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKCiAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGE7CiAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGI7CiAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGM7CiAgICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwoKICAgICAgICAgIHJldHVybiB7dmVydGljZXMsIHRyaWFuZ2xlc307CiAgICAgIH0KICB9CgogIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9DZXNpdW1HUy9jZXNpdW0vYmxvYi8xLjc2L1NvdXJjZS9Xb3JrZXJzRVM2L2NyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoLmpzCgogIHZhciBtYXJ0aW5pQ2FjaGUgPSB7fTsKICBmdW5jdGlvbiBkZWNvZGVUZXJyYWluKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHZhciBfbWFydGluaUNhY2hlJHRpbGVTaXo7CiAgICB2YXIgaW1hZ2VEYXRhID0gcGFyYW1ldGVycy5pbWFnZURhdGEsCiAgICAgIF9wYXJhbWV0ZXJzJHRpbGVTaXplID0gcGFyYW1ldGVycy50aWxlU2l6ZSwKICAgICAgdGlsZVNpemUgPSBfcGFyYW1ldGVycyR0aWxlU2l6ZSA9PT0gdm9pZCAwID8gMjU2IDogX3BhcmFtZXRlcnMkdGlsZVNpemUsCiAgICAgIGVycm9yTGV2ZWwgPSBwYXJhbWV0ZXJzLmVycm9yTGV2ZWwsCiAgICAgIG1heFZlcnRleERpc3RhbmNlID0gcGFyYW1ldGVycy5tYXhWZXJ0ZXhEaXN0YW5jZTsKCiAgICAvLyBIZWlnaHQgZGF0YSBjYW4gYmUgZWl0aGVyIGFuIGFycmF5IG9mIG51bWJlcnMgKGZvciBwcmUtZXhpc3RpbmcgdGVycmFpbiBkYXRhKQogICAgLy8gb3IgYW4gaW1hZ2UgZGF0YSBhcnJheSAoZm9yIGRlY29kaW5nIGZyb20gYW4gaW1hZ2UpCgogICAgdmFyIGhlaWdodERhdGEgPSB7CiAgICAgIHR5cGU6ICJpbWFnZSIsCiAgICAgIGFycmF5OiBpbWFnZURhdGEKICAgIH07CiAgICB2YXIgdGVycmFpbjsKICAgIHsKICAgICAgdmFyIGFycmF5ID0gaGVpZ2h0RGF0YS5hcnJheTsKICAgICAgdmFyIHBpeGVscyA9IG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoYXJyYXkpLCBbdGlsZVNpemUsIHRpbGVTaXplLCA0XSwgWzQsIDQgKiB0aWxlU2l6ZSwgMV0sIDApOwogICAgICB0ZXJyYWluID0gcmdiVGVycmFpblRvR3JpZChwaXhlbHMpOwogICAgfQoKICAgIC8vIFRpbGUgc2l6ZSBtdXN0IGJlIG1haW50YWluZWQgdGhyb3VnaCB0aGUgbGlmZSBvZiB0aGUgd29ya2VyCiAgICAoX21hcnRpbmlDYWNoZSR0aWxlU2l6ID0gbWFydGluaUNhY2hlW3RpbGVTaXplXSkgIT09IG51bGwgJiYgX21hcnRpbmlDYWNoZSR0aWxlU2l6ICE9PSB2b2lkIDAgPyBfbWFydGluaUNhY2hlJHRpbGVTaXogOiBtYXJ0aW5pQ2FjaGVbdGlsZVNpemVdID0gbmV3IE1hcnRpbmkodGlsZVNpemUgKyAxKTsKICAgIHZhciB0aWxlID0gbWFydGluaUNhY2hlW3RpbGVTaXplXS5jcmVhdGVUaWxlKHRlcnJhaW4pOwoKICAgIC8vIGdldCBhIG1lc2ggKHZlcnRpY2VzIGFuZCB0cmlhbmdsZXMgaW5kaWNlcykgZm9yIGEgMTBtIGVycm9yCiAgICB2YXIgbWVzaCA9IHRpbGUuZ2V0TWVzaChlcnJvckxldmVsLCBNYXRoLm1pbihtYXhWZXJ0ZXhEaXN0YW5jZSwgdGlsZVNpemUpKTsKICAgIHZhciByZXMgPSBjcmVhdGVRdWFudGl6ZWRNZXNoRGF0YSh0aWxlLCBtZXNoLCB0aWxlU2l6ZSwKICAgIC8vIE9ubHkgaW5jbHVkZSB2ZXJ0ZXggZGF0YSBpZiBhbnRpY2lwYXRlIHVwc2NhbGluZyB0aWxlCiAgICB0ZXJyYWluICk7CiAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2gocmVzLmluZGljZXMuYnVmZmVyKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChyZXMucXVhbnRpemVkVmVydGljZXMuYnVmZmVyKTsKICAgIGlmIChyZXMucXVhbnRpemVkSGVpZ2h0cykgewogICAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2gocmVzLnF1YW50aXplZEhlaWdodHMuYnVmZmVyKTsKICAgIH0KICAgIHJldHVybiByZXM7CiAgfQogIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24gKG1zZykgewogICAgdmFyIF9tc2ckZGF0YSA9IG1zZy5kYXRhLAogICAgICBpZCA9IF9tc2ckZGF0YS5pZCwKICAgICAgcGF5bG9hZCA9IF9tc2ckZGF0YS5wYXlsb2FkOwogICAgaWYgKGlkID09IG51bGwpIHJldHVybjsKICAgIHZhciBvYmplY3RzID0gW107CiAgICB2YXIgcmVzID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIHJlcyA9IGRlY29kZVRlcnJhaW4ocGF5bG9hZCwgb2JqZWN0cyk7CiAgICAgIC8vIEB0cy1pZ25vcmUKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIHBheWxvYWQ6IHJlcwogICAgICB9LCBvYmplY3RzKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICB2YXIgX2VyciRtZXNzYWdlOwogICAgICB2YXIgX21zZyA9IChfZXJyJG1lc3NhZ2UgPSBlcnIubWVzc2FnZSkgIT09IG51bGwgJiYgX2VyciRtZXNzYWdlICE9PSB2b2lkIDAgPyBfZXJyJG1lc3NhZ2UgOiBlcnI7CiAgICAgIHNlbGYucG9zdE1lc3NhZ2UoewogICAgICAgIGlkOiBpZCwKICAgICAgICBlcnI6IF9tc2cudG9TdHJpbmcoKQogICAgICB9KTsKICAgIH0gZmluYWxseSB7CiAgICAgIHJlcyA9IG51bGw7CiAgICAgIG9iamVjdHMgPSBudWxsOwogICAgfQogIH07Cgp9KSgpOwoK', null, false);
1584
+ /* eslint-enable */
1585
+
1429
1586
  var MapboxTerrainProvider = /*#__PURE__*/function (_MartiniTerrainProvid) {
1430
- _inherits(MapboxTerrainProvider, _MartiniTerrainProvid);
1431
- var _super2 = _createSuper(MapboxTerrainProvider);
1432
1587
  function MapboxTerrainProvider() {
1433
1588
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1434
1589
  _classCallCheck(this, MapboxTerrainProvider);
1435
1590
  var resource = new MapboxTerrainResource(opts);
1436
- return _super2.call(this, _objectSpread2(_objectSpread2({}, opts), {}, {
1437
- resource: resource
1438
- }));
1591
+ var decoder = new WorkerFarmTerrainDecoder({
1592
+ worker: new WorkerFactory()
1593
+ });
1594
+ return _callSuper(this, MapboxTerrainProvider, [_objectSpread2(_objectSpread2({}, opts), {}, {
1595
+ resource: resource,
1596
+ decoder: decoder
1597
+ })]);
1439
1598
  }
1599
+ _inherits(MapboxTerrainProvider, _MartiniTerrainProvid);
1440
1600
  return _createClass(MapboxTerrainProvider);
1441
1601
  }(MartiniTerrainProvider);
1442
1602
 
1443
- export { DefaultHeightmapResource, MapboxTerrainResource, MartiniTerrainProvider, MapboxTerrainProvider as default };
1603
+ export { DefaultHeightmapResource, DefaultTerrainDecoder, MapboxTerrainResource, MartiniTerrainProvider, StretchedTilingScheme, WorkerFarmTerrainDecoder, createQuantizedMeshData, MapboxTerrainProvider as default, emptyMesh, rgbTerrainToGrid, subsetByWindow, testMeshData };
1444
1604
  //# sourceMappingURL=index.js.map