@macrostrat/cesium-martini 1.4.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.cjs CHANGED
@@ -4,6 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var cesium = require('cesium');
6
6
 
7
+ function _arrayLikeToArray(r, a) {
8
+ (null == a || a > r.length) && (a = r.length);
9
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
10
+ return n;
11
+ }
12
+ function _arrayWithoutHoles(r) {
13
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
14
+ }
7
15
  function _assertThisInitialized(e) {
8
16
  if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
9
17
  return e;
@@ -92,6 +100,12 @@ function _isNativeReflectConstruct() {
92
100
  return !!t;
93
101
  })();
94
102
  }
103
+ function _iterableToArray(r) {
104
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
105
+ }
106
+ function _nonIterableSpread() {
107
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
108
+ }
95
109
  function ownKeys(e, r) {
96
110
  var t = Object.keys(e);
97
111
  if (Object.getOwnPropertySymbols) {
@@ -113,6 +127,26 @@ function _objectSpread2(e) {
113
127
  }
114
128
  return e;
115
129
  }
130
+ function _objectWithoutProperties(e, t) {
131
+ if (null == e) return {};
132
+ var o,
133
+ r,
134
+ i = _objectWithoutPropertiesLoose(e, t);
135
+ if (Object.getOwnPropertySymbols) {
136
+ var n = Object.getOwnPropertySymbols(e);
137
+ for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
138
+ }
139
+ return i;
140
+ }
141
+ function _objectWithoutPropertiesLoose(r, e) {
142
+ if (null == r) return {};
143
+ var t = {};
144
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
145
+ if (-1 !== e.indexOf(n)) continue;
146
+ t[n] = r[n];
147
+ }
148
+ return t;
149
+ }
116
150
  function _possibleConstructorReturn(t, e) {
117
151
  if (e && ("object" == typeof e || "function" == typeof e)) return e;
118
152
  if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
@@ -434,6 +468,9 @@ function _superPropGet(t, o, e, r) {
434
468
  return p.apply(e, t);
435
469
  } : p;
436
470
  }
471
+ function _toConsumableArray(r) {
472
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
473
+ }
437
474
  function _toPrimitive(t, r) {
438
475
  if ("object" != typeof t || !t) return t;
439
476
  var e = t[Symbol.toPrimitive];
@@ -448,57 +485,43 @@ function _toPropertyKey(t) {
448
485
  var i = _toPrimitive(t, "string");
449
486
  return "symbol" == typeof i ? i : i + "";
450
487
  }
488
+ function _unsupportedIterableToArray(r, a) {
489
+ if (r) {
490
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
491
+ var t = {}.toString.call(r).slice(8, -1);
492
+ 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;
493
+ }
494
+ }
451
495
 
452
- var loadImage = function loadImage(url) {
453
- return new Promise(function (resolve, reject) {
454
- var img = new Image();
455
- img.addEventListener("load", function () {
456
- return resolve(img);
457
- });
458
- img.addEventListener("error", function (err) {
459
- return reject(err);
460
- });
461
- img.crossOrigin = "anonymous";
462
- img.src = url;
463
- });
464
- };
465
496
  var DefaultHeightmapResource = /*#__PURE__*/function () {
466
497
  function DefaultHeightmapResource() {
467
- var _this = this,
468
- _opts$skipOddLevels,
469
- _opts$tileSize,
470
- _opts$maxZoom;
498
+ var _opts$tileSize, _opts$maxZoom;
471
499
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
472
500
  _classCallCheck(this, DefaultHeightmapResource);
473
501
  _defineProperty(this, "resource", null);
474
502
  _defineProperty(this, "tileSize", 256);
475
- _defineProperty(this, "skipOddLevels", false);
476
- _defineProperty(this, "getTilePixels", /*#__PURE__*/function () {
477
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(coords) {
478
- var url, img;
479
- return _regeneratorRuntime().wrap(function _callee$(_context) {
480
- while (1) switch (_context.prev = _context.next) {
481
- case 0:
482
- url = _this.buildTileURL(coords);
483
- _context.next = 3;
484
- return loadImage(url);
485
- case 3:
486
- img = _context.sent;
487
- return _context.abrupt("return", _this.getPixels(img));
488
- case 5:
489
- case "end":
490
- return _context.stop();
491
- }
492
- }, _callee);
493
- }));
494
- return function (_x) {
495
- return _ref.apply(this, arguments);
496
- };
497
- }());
498
503
  if (opts.url) {
499
- this.resource = cesium.Resource.createIfNeeded(opts.url);
504
+ this.resource = new cesium.Resource({
505
+ url: opts.url
506
+ });
507
+ }
508
+ this.skipZoomLevel = function () {
509
+ return false;
510
+ };
511
+ if (opts.skipZoomLevels) {
512
+ if (Array.isArray(opts.skipZoomLevels)) {
513
+ var _skipZoomLevels = opts.skipZoomLevels;
514
+ this.skipZoomLevel = function (z) {
515
+ return _skipZoomLevels.includes(z);
516
+ };
517
+ } else {
518
+ this.skipZoomLevel = opts.skipZoomLevels;
519
+ }
520
+ } else if (opts.skipOddLevels) {
521
+ this.skipZoomLevel = function (z) {
522
+ return z % 2 == 1;
523
+ };
500
524
  }
501
- this.skipOddLevels = (_opts$skipOddLevels = opts.skipOddLevels) !== null && _opts$skipOddLevels !== void 0 ? _opts$skipOddLevels : false;
502
525
  this.tileSize = (_opts$tileSize = opts.tileSize) !== null && _opts$tileSize !== void 0 ? _opts$tileSize : 256;
503
526
  this.maxZoom = (_opts$maxZoom = opts.maxZoom) !== null && _opts$maxZoom !== void 0 ? _opts$maxZoom : 15;
504
527
  this.contextQueue = [];
@@ -534,26 +557,48 @@ var DefaultHeightmapResource = /*#__PURE__*/function () {
534
557
  return pixels;
535
558
  }
536
559
  }, {
537
- key: "buildTileURL",
538
- value: function buildTileURL(tileCoords) {
539
- var _this$resource;
560
+ key: "getTileResource",
561
+ value: function getTileResource(tileCoords) {
540
562
  // reverseY for TMS tiling (https://gist.github.com/tmcw/4954720)
541
563
  // See tiling schemes here: https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/
542
564
  var z = tileCoords.z,
543
565
  y = tileCoords.y;
544
- return (_this$resource = this.resource) === null || _this$resource === void 0 ? void 0 : _this$resource.getDerivedResource({
566
+ return this.resource.getDerivedResource({
545
567
  templateValues: _objectSpread2(_objectSpread2({}, tileCoords), {}, {
546
568
  reverseY: Math.pow(2, z) - y - 1
547
569
  }),
548
570
  preserveQueryParameters: true
549
- }).getUrlComponent(true);
571
+ });
572
+ }
573
+ }, {
574
+ key: "getTilePixels",
575
+ value: function getTilePixels(coords) {
576
+ var _this = this;
577
+ var resource = this.getTileResource(coords);
578
+ var request = resource.fetchImage({
579
+ preferImageBitmap: false,
580
+ // @ts-ignore
581
+ retryAttempts: 3
582
+ });
583
+ if (request == null) return undefined;
584
+ return request.then(function (img) {
585
+ return (
586
+ // @ts-ignore
587
+ _this.getPixels(img)
588
+ );
589
+ });
550
590
  }
551
591
  }, {
552
592
  key: "getTileDataAvailable",
553
- value: function getTileDataAvailable(_ref2) {
554
- var z = _ref2.z;
593
+ value: function getTileDataAvailable(_ref) {
594
+ var z = _ref.z;
555
595
  if (z == this.maxZoom) return true;
556
- if (z % 2 == 1 && this.skipOddLevels) return false;
596
+ /* Weird hack:
597
+ For some reason, request render mode breaks if zoom 1 tiles are disabled.
598
+ So we have to make sure that we always report zoom 1 tiles as available.
599
+ */
600
+ if (z < 2) return true;
601
+ if (this.skipZoomLevel(z)) return false;
557
602
  if (z > this.maxZoom) return false;
558
603
  return true;
559
604
  }
@@ -577,6 +622,7 @@ var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
577
622
  _defineProperty(_this, "credit", new cesium.Credit("Mapbox"));
578
623
  var highResolution = (_opts$highResolution = opts.highResolution) !== null && _opts$highResolution !== void 0 ? _opts$highResolution : false;
579
624
  var format = (_opts$imageFormat = opts.imageFormat) !== null && _opts$imageFormat !== void 0 ? _opts$imageFormat : ImageFormat.WEBP;
625
+ var urlTemplate = opts.urlTemplate;
580
626
 
581
627
  // overrides based on highResolution flag
582
628
  if (highResolution) {
@@ -587,7 +633,10 @@ var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
587
633
  _this.tileSize = 512;
588
634
  }
589
635
  }
590
- _this.resource = cesium.Resource.createIfNeeded("https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format));
636
+ var defaultURL = "https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}".concat(highResolution ? "@2x" : "", ".").concat(format);
637
+ _this.resource = new cesium.Resource({
638
+ url: urlTemplate !== null && urlTemplate !== void 0 ? urlTemplate : defaultURL
639
+ });
591
640
  if (opts.accessToken) {
592
641
  _this.resource.setQueryParameters({
593
642
  access_token: opts.accessToken
@@ -599,6 +648,76 @@ var MapboxTerrainResource = /*#__PURE__*/function (_DefaultHeightmapReso) {
599
648
  return _createClass(MapboxTerrainResource);
600
649
  }(DefaultHeightmapResource);
601
650
 
651
+ /** Mapbox Terrain-RGB default decode function
652
+ * (r * 256 * 256) / 10 + (g * 256) / 10 + b / 10 - 10000
653
+ */
654
+ var defaultMapboxDecodeRgb = function defaultMapboxDecodeRgb(r, g, b, a) {
655
+ return r * 6553.6 + g * 25.6 + b * 0.1 - 10000;
656
+ };
657
+ function rgbTerrainToGrid(png, decodeRgb) {
658
+ // maybe we should do this on the GPU using REGL?
659
+ // but that would require GPU -> CPU -> GPU
660
+ var gridSize = png.shape[0] + 1;
661
+ var terrain = new Float32Array(gridSize * gridSize);
662
+ var tileSize = png.shape[0];
663
+ var decode = decodeRgb !== null && decodeRgb !== void 0 ? decodeRgb : defaultMapboxDecodeRgb;
664
+
665
+ // decode terrain values
666
+ for (var y = 0; y < tileSize; y++) {
667
+ for (var x = 0; x < tileSize; x++) {
668
+ var yc = y;
669
+ var _r = png.get(x, yc, 0);
670
+ var _g = png.get(x, yc, 1);
671
+ var _b = png.get(x, yc, 2);
672
+ var _a = png.get(x, yc, 3);
673
+ terrain[y * gridSize + x] = decode(_r, _g, _b, _a);
674
+ }
675
+ }
676
+ // backfill right and bottom borders
677
+ for (var _x = 0; _x < gridSize - 1; _x++) {
678
+ terrain[gridSize * (gridSize - 1) + _x] = terrain[gridSize * (gridSize - 2) + _x];
679
+ }
680
+ for (var _y = 0; _y < gridSize; _y++) {
681
+ terrain[gridSize * _y + gridSize - 1] = terrain[gridSize * _y + gridSize - 2];
682
+ }
683
+ return terrain;
684
+ }
685
+ function subsetByWindow(array, window, augmented) {
686
+ var sz = Math.sqrt(array.length);
687
+ var x0 = window.x0;
688
+ var x1 = window.x1;
689
+ var y0 = window.y0;
690
+ var y1 = window.y1;
691
+ var aug = augmented ? 1 : 0;
692
+ var n = Math.floor(x1 - x0) + aug;
693
+ var m = Math.floor(y1 - y0) + aug;
694
+ var result = new Float32Array(n * m);
695
+ for (var i = 0; i < m; i++) {
696
+ for (var j = 0; j < n; j++) {
697
+ result[i * n + j] = array[(i + y0) * sz + j + x0];
698
+ }
699
+ }
700
+ return result;
701
+ }
702
+ function testMeshData() {
703
+ return {
704
+ minimumHeight: -100,
705
+ maximumHeight: 2101,
706
+ quantizedVertices: new Uint16Array([
707
+ // order is SW NW SE NE
708
+ // longitude
709
+ 0, 0, 32767, 32767,
710
+ // latitude
711
+ 0, 32767, 0, 32767,
712
+ // heights
713
+ 16384, 0, 32767, 16384]),
714
+ indices: new Uint16Array([0, 3, 1, 0, 2, 3]),
715
+ westIndices: [0, 1],
716
+ southIndices: [0, 1],
717
+ eastIndices: [2, 3],
718
+ northIndices: [1, 3]
719
+ };
720
+ }
602
721
  function _emptyMesh(n) {
603
722
  n = Math.max(n, 2);
604
723
  var nTriangles = Math.pow(n - 1, 2) * 2;
@@ -660,6 +779,68 @@ function emptyMesh(n) {
660
779
  }
661
780
  }
662
781
 
782
+ /** Terrain workers should return a quantized mesh */
783
+
784
+ function createQuantizedMeshData(tile, mesh, tileSize, terrain) {
785
+ /** Terrain is passed through so we can keep track of it
786
+ * for overscaled tiles
787
+ */
788
+
789
+ var xvals = [];
790
+ var yvals = [];
791
+ var heightMeters = [];
792
+ var northIndices = [];
793
+ var southIndices = [];
794
+ var eastIndices = [];
795
+ var westIndices = [];
796
+ var minimumHeight = Infinity;
797
+ var maximumHeight = -Infinity;
798
+ var scalar = 32768.0 / tileSize;
799
+
800
+ // There appears to be a problem with the x/y indexing when using 512x512 tiles
801
+ // This may be solved by increasing the minumumErrorLevel in the terrain provider
802
+ for (var ix = 0; ix < mesh.vertices.length / 2; ix++) {
803
+ var vertexIx = ix;
804
+ var px = mesh.vertices[ix * 2];
805
+ var py = mesh.vertices[ix * 2 + 1];
806
+ var height = tile.terrain[py * (tileSize + 1) + px];
807
+ if (height > maximumHeight) maximumHeight = height;
808
+ if (height < minimumHeight) minimumHeight = height;
809
+ heightMeters.push(height);
810
+ if (py == 0) northIndices.push(vertexIx);
811
+ if (py == tileSize) southIndices.push(vertexIx);
812
+ if (px == 0) westIndices.push(vertexIx);
813
+ if (px == tileSize) eastIndices.push(vertexIx);
814
+ var xv = px * scalar;
815
+ var yv = (tileSize - py) * scalar;
816
+ xvals.push(xv);
817
+ yvals.push(yv);
818
+ }
819
+ var heightRange = maximumHeight - minimumHeight;
820
+ var heights = heightMeters.map(function (d) {
821
+ if (heightRange < 1) return 0;
822
+ return (d - minimumHeight) * (32768.0 / heightRange);
823
+ });
824
+ var triangles = new Uint16Array(mesh.triangles);
825
+ var quantizedVertices = new Uint16Array(//verts
826
+ [].concat(xvals, yvals, _toConsumableArray(heights)));
827
+
828
+ // SE NW NE
829
+ // NE NW SE
830
+
831
+ return {
832
+ minimumHeight: minimumHeight,
833
+ maximumHeight: maximumHeight,
834
+ quantizedVertices: quantizedVertices,
835
+ indices: triangles,
836
+ westIndices: westIndices,
837
+ southIndices: southIndices,
838
+ eastIndices: eastIndices,
839
+ northIndices: northIndices,
840
+ quantizedHeights: terrain
841
+ };
842
+ }
843
+
663
844
  var resolves = {};
664
845
  var rejects = {};
665
846
  var globalMsgId = 0; // Activate calculation in the worker, returning a promise
@@ -667,17 +848,17 @@ function sendMessage(_x, _x2, _x3) {
667
848
  return _sendMessage.apply(this, arguments);
668
849
  } // Handle incoming calculation result
669
850
  function _sendMessage() {
670
- _sendMessage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(worker, payload, transferableObjects) {
851
+ _sendMessage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(worker, payload, transferableObjects) {
671
852
  var msgId, msg;
672
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
673
- while (1) switch (_context2.prev = _context2.next) {
853
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
854
+ while (1) switch (_context3.prev = _context3.next) {
674
855
  case 0:
675
856
  msgId = globalMsgId++;
676
857
  msg = {
677
858
  id: msgId,
678
859
  payload: payload
679
860
  };
680
- return _context2.abrupt("return", new Promise(function (resolve, reject) {
861
+ return _context3.abrupt("return", new Promise(function (resolve, reject) {
681
862
  // save callbacks for later
682
863
  resolves[msgId] = resolve;
683
864
  rejects[msgId] = reject;
@@ -685,9 +866,9 @@ function _sendMessage() {
685
866
  }));
686
867
  case 3:
687
868
  case "end":
688
- return _context2.stop();
869
+ return _context3.stop();
689
870
  }
690
- }, _callee2);
871
+ }, _callee3);
691
872
  }));
692
873
  return _sendMessage.apply(this, arguments);
693
874
  }
@@ -720,6 +901,9 @@ function handleMessage(msg) {
720
901
  var WorkerFarm = /*#__PURE__*/function () {
721
902
  function WorkerFarm(opts) {
722
903
  _classCallCheck(this, WorkerFarm);
904
+ _defineProperty(this, "inProgressWorkers", 0);
905
+ _defineProperty(this, "maxWorkers", 5);
906
+ _defineProperty(this, "processingQueue", []);
723
907
  this.worker = opts.worker;
724
908
  this.worker.onmessage = handleMessage;
725
909
  }
@@ -727,14 +911,17 @@ var WorkerFarm = /*#__PURE__*/function () {
727
911
  key: "scheduleTask",
728
912
  value: function () {
729
913
  var _scheduleTask = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(params, transferableObjects) {
914
+ var res;
730
915
  return _regeneratorRuntime().wrap(function _callee$(_context) {
731
916
  while (1) switch (_context.prev = _context.next) {
732
917
  case 0:
733
918
  _context.next = 2;
734
919
  return sendMessage(this.worker, params, transferableObjects);
735
920
  case 2:
736
- return _context.abrupt("return", _context.sent);
737
- case 3:
921
+ res = _context.sent;
922
+ this.releaseWorker();
923
+ return _context.abrupt("return", res);
924
+ case 5:
738
925
  case "end":
739
926
  return _context.stop();
740
927
  }
@@ -745,6 +932,45 @@ var WorkerFarm = /*#__PURE__*/function () {
745
932
  }
746
933
  return scheduleTask;
747
934
  }()
935
+ }, {
936
+ key: "holdForAvailableWorker",
937
+ value: function () {
938
+ var _holdForAvailableWorker = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
939
+ var _this = this;
940
+ var resultPromise;
941
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
942
+ while (1) switch (_context2.prev = _context2.next) {
943
+ case 0:
944
+ if (this.inProgressWorkers > this.maxWorkers) {
945
+ resultPromise = new Promise(function (resolve, reject) {
946
+ _this.processingQueue.push(resolve);
947
+ });
948
+ } else {
949
+ resultPromise = Promise.resolve(null);
950
+ }
951
+ _context2.next = 3;
952
+ return resultPromise;
953
+ case 3:
954
+ this.inProgressWorkers += 1;
955
+ case 4:
956
+ case "end":
957
+ return _context2.stop();
958
+ }
959
+ }, _callee2, this);
960
+ }));
961
+ function holdForAvailableWorker() {
962
+ return _holdForAvailableWorker.apply(this, arguments);
963
+ }
964
+ return holdForAvailableWorker;
965
+ }()
966
+ }, {
967
+ key: "releaseWorker",
968
+ value: function releaseWorker() {
969
+ this.inProgressWorkers -= 1;
970
+ if (this.processingQueue.length > 0) {
971
+ this.processingQueue.shift()();
972
+ }
973
+ }
748
974
  }]);
749
975
  }();
750
976
 
@@ -792,7 +1018,276 @@ var WorkerFarmTerrainDecoder = /*#__PURE__*/function (_DefaultTerrainDecode) {
792
1018
  }]);
793
1019
  }(DefaultTerrainDecoder);
794
1020
 
1021
+ function decodeBase64(base64, enableUnicode) {
1022
+ var binaryString = atob(base64);
1023
+ if (enableUnicode) {
1024
+ var binaryView = new Uint8Array(binaryString.length);
1025
+ for (var i = 0, n = binaryString.length; i < n; ++i) {
1026
+ binaryView[i] = binaryString.charCodeAt(i);
1027
+ }
1028
+ const decoder = new TextDecoder("utf-16le");
1029
+ return decoder.decode(new Uint16Array(binaryView.buffer));
1030
+ }
1031
+ return binaryString;
1032
+ }
1033
+
1034
+ function createURL(base64, sourcemapArg, enableUnicodeArg) {
1035
+ var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
1036
+ var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
1037
+ var source = decodeBase64(base64, enableUnicode);
1038
+ var start = source.indexOf('\n', 10) + 1;
1039
+ var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
1040
+ var blob = new Blob([body], { type: 'application/javascript' });
1041
+ return URL.createObjectURL(blob);
1042
+ }
1043
+
1044
+ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
1045
+ var url;
1046
+ return function WorkerFactory(options) {
1047
+ url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
1048
+ return new Worker(url, options);
1049
+ };
1050
+ }
1051
+
1052
+ 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);
1053
+ /* eslint-enable */
1054
+
1055
+ var _excluded = ["tilingScheme", "overscaleFactor"];
1056
+ function createTerrainMesh(data, meta) {
1057
+ var minimumHeight = data.minimumHeight,
1058
+ maximumHeight = data.maximumHeight,
1059
+ quantizedVertices = data.quantizedVertices,
1060
+ indices = data.indices,
1061
+ westIndices = data.westIndices,
1062
+ southIndices = data.southIndices,
1063
+ eastIndices = data.eastIndices,
1064
+ northIndices = data.northIndices,
1065
+ quantizedHeights = data.quantizedHeights;
1066
+ var errorLevel = meta.errorLevel,
1067
+ tileSize = meta.tileSize,
1068
+ maxVertexDistance = meta.maxVertexDistance,
1069
+ tileRect = meta.tileRect,
1070
+ ellipsoid = meta.ellipsoid,
1071
+ overscaleFactor = meta.overscaleFactor;
1072
+ var err = errorLevel;
1073
+ var skirtHeight = err * 20;
1074
+
1075
+ // Check if tileRect is not NaNs
1076
+ if (isNaN(tileRect.east) || isNaN(tileRect.north)) {
1077
+ throw new Error("Invalid tile rect");
1078
+ }
1079
+ var center = cesium.Rectangle.center(tileRect);
1080
+
1081
+ // Calculating occlusion height is kind of messy currently, but it definitely works
1082
+ var halfAngle = tileRect.width / 2;
1083
+ var dr = Math.cos(halfAngle); // half tile width since our ref point is at the center
1084
+
1085
+ var occlusionHeight = dr * ellipsoid.maximumRadius + maximumHeight;
1086
+ if (halfAngle > Math.PI / 4) {
1087
+ occlusionHeight = (1 + halfAngle) * ellipsoid.maximumRadius;
1088
+ }
1089
+ var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude, occlusionHeight) // Scaling factor of two just to be sure.
1090
+ ;
1091
+ var horizonOcclusionPoint = ellipsoid.transformPositionToScaledSpace(cesium.Cartographic.toCartesian(occlusionPoint));
1092
+ var orientedBoundingBox = cesium.OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, ellipsoid);
1093
+ var boundingSphere = cesium.BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox);
1094
+ return new RasterTerrainData({
1095
+ minimumHeight: minimumHeight,
1096
+ maximumHeight: maximumHeight,
1097
+ quantizedVertices: quantizedVertices,
1098
+ indices: indices,
1099
+ boundingSphere: boundingSphere,
1100
+ orientedBoundingBox: orientedBoundingBox,
1101
+ horizonOcclusionPoint: horizonOcclusionPoint,
1102
+ westIndices: westIndices,
1103
+ southIndices: southIndices,
1104
+ eastIndices: eastIndices,
1105
+ northIndices: northIndices,
1106
+ westSkirtHeight: skirtHeight,
1107
+ southSkirtHeight: skirtHeight,
1108
+ eastSkirtHeight: skirtHeight,
1109
+ northSkirtHeight: skirtHeight,
1110
+ childTileMask: 15,
1111
+ createdByUpsampling: overscaleFactor > 0,
1112
+ errorLevel: err,
1113
+ maxVertexDistance: maxVertexDistance,
1114
+ tileSize: tileSize,
1115
+ quantizedHeights: quantizedHeights
1116
+ });
1117
+ }
1118
+ function createEmptyMesh(opts) {
1119
+ var tileRect = opts.tileRect,
1120
+ tileCoord = opts.tileCoord,
1121
+ errorLevel = opts.errorLevel,
1122
+ ellipsoid = opts.ellipsoid,
1123
+ maxVertexDistance = opts.maxVertexDistance;
1124
+ var center = cesium.Rectangle.center(tileRect);
1125
+ var z = tileCoord.z;
1126
+ var latScalar = Math.min(Math.abs(Math.sin(center.latitude)), 0.995);
1127
+ var v = Math.max(Math.ceil(200 / (z + 1) * Math.pow(1 - latScalar, 0.25)), 4);
1128
+ var output = emptyMesh(v);
1129
+ // We use zero for some undefined values
1130
+ return createTerrainMesh(output, {
1131
+ tileRect: tileRect,
1132
+ ellipsoid: ellipsoid,
1133
+ errorLevel: errorLevel,
1134
+ overscaleFactor: 0,
1135
+ maxVertexDistance: maxVertexDistance,
1136
+ tileSize: output.tileSize
1137
+ });
1138
+ }
1139
+ var UpsampleTracker = /*#__PURE__*/function () {
1140
+ function UpsampleTracker() {
1141
+ _classCallCheck(this, UpsampleTracker);
1142
+ this.ne = false;
1143
+ this.nw = false;
1144
+ this.se = false;
1145
+ this.sw = false;
1146
+ }
1147
+ return _createClass(UpsampleTracker, [{
1148
+ key: "finished",
1149
+ value: function finished() {
1150
+ return this.ne && this.nw && this.se && this.sw;
1151
+ }
1152
+ }]);
1153
+ }();
1154
+ var RasterTerrainData = /*#__PURE__*/function (_QuantizedMeshTerrain) {
1155
+ function RasterTerrainData(opts) {
1156
+ var _opts$maxVertexDistan;
1157
+ var _this;
1158
+ _classCallCheck(this, RasterTerrainData);
1159
+ _this = _callSuper(this, RasterTerrainData, [opts]);
1160
+ _this.quantizedHeights = opts.quantizedHeights;
1161
+ _this.errorLevel = opts.errorLevel;
1162
+ _this.maxVertexDistance = (_opts$maxVertexDistan = opts.maxVertexDistance) !== null && _opts$maxVertexDistan !== void 0 ? _opts$maxVertexDistan : opts.tileSize;
1163
+ _this.tileSize = opts.tileSize;
1164
+ _this.upsampleTracker = new UpsampleTracker();
1165
+ return _this;
1166
+ }
1167
+ _inherits(RasterTerrainData, _QuantizedMeshTerrain);
1168
+ return _createClass(RasterTerrainData, [{
1169
+ key: "upsample",
1170
+ value: function upsample(tilingScheme, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel) {
1171
+ if (this.quantizedHeights == null) {
1172
+ return _superPropGet(RasterTerrainData, "upsample", this, 3)([tilingScheme, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel]);
1173
+ } // Something wonky about our tiling scheme, perhaps
1174
+ // 12/2215/2293 @2x
1175
+ //const url = `https://a.tiles.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}`;
1176
+
1177
+ var x = descendantX;
1178
+ var y = descendantY;
1179
+ var z = descendantLevel;
1180
+
1181
+ //console.log(`Upsampling terrain data from zoom ${thisLevel} to ` + tile);
1182
+
1183
+ var dz = z - thisLevel;
1184
+ var scalar = Math.pow(2, dz);
1185
+ var ellipsoid = tilingScheme.ellipsoid;
1186
+ var err = this.errorLevel / scalar;
1187
+ var maxVertexDistance = Math.min(this.maxVertexDistance * scalar, this.tileSize);
1188
+ var upscaledX = thisX * scalar;
1189
+ var upscaledY = thisY * scalar;
1190
+ var dx = x - upscaledX;
1191
+ var dy = y - upscaledY;
1192
+ var x0 = dx * this.tileSize / scalar;
1193
+ var x1 = (dx + 1) * this.tileSize / scalar;
1194
+ var y0 = dy * this.tileSize / scalar;
1195
+ var y1 = (dy + 1) * this.tileSize / scalar;
1196
+ var window = {
1197
+ x0: x0,
1198
+ x1: x1,
1199
+ y0: y0,
1200
+ y1: y1
1201
+ };
1202
+ var res = buildOverscaledTerrainTile({
1203
+ tilingScheme: tilingScheme,
1204
+ heightData: subsetByWindow(this.quantizedHeights, window, true),
1205
+ maxVertexDistance: maxVertexDistance,
1206
+ x: x,
1207
+ y: y,
1208
+ z: z,
1209
+ errorLevel: err,
1210
+ ellipsoidRadius: ellipsoid.maximumRadius,
1211
+ tileSize: x1 - x0,
1212
+ overscaleFactor: dz
1213
+ });
1214
+ if (dz == 1) {
1215
+ // If we've got a single child tile, we can track that we've upsampled the parent.
1216
+ var quadrant = getQuadrant(dx, dy);
1217
+ this.upsampleTracker[quadrant] = true;
1218
+ }
1219
+ if (this.upsampleTracker.finished()) {
1220
+ // We've upsampled all child tiles and don't need to keep terrain data around anymore.
1221
+ this.quantizedHeights = undefined;
1222
+ }
1223
+ return res;
1224
+ }
1225
+ }]);
1226
+ }(cesium.QuantizedMeshTerrainData);
1227
+ function getQuadrant(dx, dy) {
1228
+ if (dx == 0 && dy == 0) return "sw";
1229
+ if (dx == 0 && dy == 1) return "nw";
1230
+ if (dx == 1 && dy == 0) return "se";
1231
+ if (dx == 1 && dy == 1) return "ne";
1232
+ throw new Error("Invalid quadrant");
1233
+ }
1234
+ function buildOverscaledTerrainTile(_x) {
1235
+ return _buildOverscaledTerrainTile.apply(this, arguments);
1236
+ }
1237
+ function _buildOverscaledTerrainTile() {
1238
+ _buildOverscaledTerrainTile = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(opts) {
1239
+ var tilingScheme, overscaleFactor, workerOpts, x, y, z, tileRect, ellipsoid, errorLevel, maxVertexDistance, tileSize, res;
1240
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
1241
+ while (1) switch (_context.prev = _context.next) {
1242
+ case 0:
1243
+ tilingScheme = opts.tilingScheme, overscaleFactor = opts.overscaleFactor, workerOpts = _objectWithoutProperties(opts, _excluded);
1244
+ x = workerOpts.x, y = workerOpts.y, z = workerOpts.z;
1245
+ tileRect = tilingScheme.tileXYToRectangle(x, y, z);
1246
+ ellipsoid = tilingScheme.ellipsoid;
1247
+ errorLevel = workerOpts.errorLevel, maxVertexDistance = workerOpts.maxVertexDistance, tileSize = workerOpts.tileSize;
1248
+ _context.prev = 5;
1249
+ _context.next = 8;
1250
+ return upsamplerFarm.scheduleTask(workerOpts, [workerOpts.heightData.buffer]);
1251
+ case 8:
1252
+ res = _context.sent;
1253
+ return _context.abrupt("return", createTerrainMesh(res, {
1254
+ tileRect: tileRect,
1255
+ ellipsoid: ellipsoid,
1256
+ errorLevel: errorLevel,
1257
+ overscaleFactor: overscaleFactor,
1258
+ tileSize: tileSize,
1259
+ // Maximum vertex distance
1260
+ maxVertexDistance: maxVertexDistance
1261
+ }));
1262
+ case 12:
1263
+ _context.prev = 12;
1264
+ _context.t0 = _context["catch"](5);
1265
+ return _context.abrupt("return", createEmptyMesh({
1266
+ tileRect: tileRect,
1267
+ errorLevel: errorLevel,
1268
+ ellipsoid: ellipsoid,
1269
+ tileCoord: {
1270
+ x: x,
1271
+ y: y,
1272
+ z: z
1273
+ },
1274
+ tileSize: 0
1275
+ }));
1276
+ case 15:
1277
+ case "end":
1278
+ return _context.stop();
1279
+ }
1280
+ }, _callee, null, [[5, 12]]);
1281
+ }));
1282
+ return _buildOverscaledTerrainTile.apply(this, arguments);
1283
+ }
1284
+ var upsamplerFarm = new WorkerFarm({
1285
+ worker: new WorkerFactory$1(),
1286
+ maxWorkers: 5
1287
+ });
1288
+
795
1289
  // https://github.com/CesiumGS/cesium/blob/1.68/Source/Scene/MapboxImageryProvider.js#L42
1290
+
796
1291
  var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
797
1292
  function StretchedTilingScheme() {
798
1293
  _classCallCheck(this, StretchedTilingScheme);
@@ -804,7 +1299,6 @@ var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
804
1299
  value: function tileXYToRectangle(x, y, level, res) {
805
1300
  var result = _superPropGet(StretchedTilingScheme, "tileXYToRectangle", this, 3)([x, y, level]);
806
1301
  if (y == 0) {
807
- //console.log("Top row", res, y, level);
808
1302
  result.north = Math.PI / 2;
809
1303
  }
810
1304
  if (y + 1 == Math.pow(2, level)) {
@@ -817,7 +1311,7 @@ var StretchedTilingScheme = /*#__PURE__*/function (_WebMercatorTilingSch) {
817
1311
  var MartiniTerrainProvider = /*#__PURE__*/function () {
818
1312
  // @ts-ignore
819
1313
  function MartiniTerrainProvider() {
820
- var _this$resource$credit, _opts$minZoomLevel, _opts$fillPoles, _opts$detailScalar, _opts$minimumErrorLev, _opts$ellipsoid;
1314
+ var _this$resource$credit, _opts$maxWorkers, _opts$minZoomLevel, _opts$fillPoles, _opts$minimumErrorLev, _opts$ellipsoid, _opts$detailScalar, _ref, _opts$tilingScheme$el, _opts$tilingScheme;
821
1315
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
822
1316
  _classCallCheck(this, MartiniTerrainProvider);
823
1317
  _defineProperty(this, "hasWaterMask", false);
@@ -826,6 +1320,7 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
826
1320
  _defineProperty(this, "availability", null);
827
1321
  _defineProperty(this, "errorEvent", new cesium.Event());
828
1322
  _defineProperty(this, "levelOfDetailScalar", null);
1323
+ _defineProperty(this, "maxWorkers", 5);
829
1324
  _defineProperty(this, "minError", 0.1);
830
1325
  _defineProperty(this, "fillPoles", true);
831
1326
  _defineProperty(this, "_errorAtMinZoom", 1000);
@@ -836,9 +1331,9 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
836
1331
  this.resource = opts.resource;
837
1332
  this.credit = (_this$resource$credit = this.resource.credit) !== null && _this$resource$credit !== void 0 ? _this$resource$credit : new cesium.Credit("Mapbox");
838
1333
  this.decoder = opts.decoder;
1334
+ this.maxWorkers = (_opts$maxWorkers = opts.maxWorkers) !== null && _opts$maxWorkers !== void 0 ? _opts$maxWorkers : 5;
839
1335
  if (!this.decoder) {
840
- var _opts$maxWorkers;
841
- var maxWorkers = (_opts$maxWorkers = opts.maxWorkers) !== null && _opts$maxWorkers !== void 0 ? _opts$maxWorkers : 5;
1336
+ var maxWorkers = this.maxWorkers;
842
1337
  if (maxWorkers > 0) {
843
1338
  this.decoder = new WorkerFarmTerrainDecoder({
844
1339
  maxWorkers: maxWorkers
@@ -849,32 +1344,40 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
849
1344
  }
850
1345
  this.minZoomLevel = (_opts$minZoomLevel = opts.minZoomLevel) !== null && _opts$minZoomLevel !== void 0 ? _opts$minZoomLevel : 3;
851
1346
  this.fillPoles = (_opts$fillPoles = opts.fillPoles) !== null && _opts$fillPoles !== void 0 ? _opts$fillPoles : true;
852
- this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 4.0) + cesium.Math.EPSILON5;
853
1347
  this.ready = true;
854
1348
  this.readyPromise = Promise.resolve(true);
855
1349
  this.minError = (_opts$minimumErrorLev = opts.minimumErrorLevel) !== null && _opts$minimumErrorLev !== void 0 ? _opts$minimumErrorLev : 0.1;
856
1350
  this.errorEvent.addEventListener(console.log, this);
857
1351
  this.ellipsoid = (_opts$ellipsoid = opts.ellipsoid) !== null && _opts$ellipsoid !== void 0 ? _opts$ellipsoid : cesium.Ellipsoid.WGS84;
858
- var scheme = cesium.WebMercatorTilingScheme;
859
- if (this.fillPoles) {
860
- scheme = StretchedTilingScheme;
1352
+ if (opts.tilingScheme == null) {
1353
+ var scheme = cesium.WebMercatorTilingScheme;
1354
+ if (this.fillPoles) {
1355
+ scheme = StretchedTilingScheme;
1356
+ }
1357
+ this.tilingScheme = new scheme({
1358
+ numberOfLevelZeroTilesX: 1,
1359
+ numberOfLevelZeroTilesY: 1,
1360
+ ellipsoid: this.ellipsoid
1361
+ });
1362
+ } else {
1363
+ this.tilingScheme = opts.tilingScheme;
861
1364
  }
862
- this.tilingScheme = new scheme({
863
- numberOfLevelZeroTilesX: 1,
864
- numberOfLevelZeroTilesY: 1,
865
- ellipsoid: this.ellipsoid
866
- });
1365
+ this.levelOfDetailScalar = ((_opts$detailScalar = opts.detailScalar) !== null && _opts$detailScalar !== void 0 ? _opts$detailScalar : 2.0) + cesium.Math.EPSILON5;
1366
+
1367
+ //this.errorEvent.addEventListener(console.log, this);
1368
+ 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 : cesium.Ellipsoid.WGS84;
867
1369
  this._errorAtMinZoom = this.errorAtZoom(this.minZoomLevel);
868
1370
  }
869
1371
  return _createClass(MartiniTerrainProvider, [{
870
1372
  key: "requestTileGeometry",
871
1373
  value: function requestTileGeometry(x, y, z, request) {
872
1374
  // Look for tiles both below the zoom level and below the error threshold for the zoom level at the equator...
873
- if (z < this.minZoomLevel || this.scaledErrorForTile(x, y, z) > this._errorAtMinZoom) {
1375
+ if (this.minZoomLevel != 0 && (z < this.minZoomLevel || this.scaledErrorForTile(x, y, z) > this._errorAtMinZoom)) {
874
1376
  // If we are below the minimum zoom level, we return empty heightmaps
875
1377
  // to avoid unnecessary requests for low-resolution data.
876
1378
  return Promise.resolve(this.emptyMesh(x, y, z));
877
1379
  }
1380
+
878
1381
  // Note: we still load a TON of tiles near the poles. We might need to do some overzooming here...
879
1382
  return this.decoder.requestTileGeometry({
880
1383
  x: x,
@@ -885,53 +1388,88 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
885
1388
  }, {
886
1389
  key: "processTile",
887
1390
  value: function () {
888
- var _processTile = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref) {
889
- var x, y, z, _this$resource, tileSize, getTilePixels, px, pixelData, tileRect, err, maxLength, params, res;
1391
+ var _processTile = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(_ref2) {
1392
+ var x, y, z, tileRect, errorLevel, maxVertexDistance, _this$resource, tileSize, getTilePixels, r1, px, pixelData, params, res, meta;
890
1393
  return _regeneratorRuntime().wrap(function _callee$(_context) {
891
1394
  while (1) switch (_context.prev = _context.next) {
892
1395
  case 0:
893
- x = _ref.x, y = _ref.y, z = _ref.z;
894
- _context.prev = 1;
1396
+ x = _ref2.x, y = _ref2.y, z = _ref2.z;
1397
+ // Something wonky about our tiling scheme, perhaps
1398
+ // 12/2215/2293 @2x
1399
+ //const url = `https://a.tiles.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}${hires}.${this.format}?access_token=${this.accessToken}`;
1400
+ tileRect = this.tilingScheme.tileXYToRectangle(x, y, z);
1401
+ errorLevel = this.errorAtZoom(z);
1402
+ maxVertexDistance = this.maxVertexDistance(tileRect);
1403
+ _context.prev = 4;
895
1404
  _this$resource = this.resource, tileSize = _this$resource.tileSize, getTilePixels = _this$resource.getTilePixels;
896
- _context.next = 5;
897
- return getTilePixels({
1405
+ r1 = getTilePixels.bind(this.resource, {
898
1406
  x: x,
899
1407
  y: y,
900
1408
  z: z
901
1409
  });
902
- case 5:
1410
+ if (!(r1 == null)) {
1411
+ _context.next = 9;
1412
+ break;
1413
+ }
1414
+ return _context.abrupt("return");
1415
+ case 9:
1416
+ _context.next = 11;
1417
+ return r1();
1418
+ case 11:
903
1419
  px = _context.sent;
904
1420
  pixelData = px.data;
905
- tileRect = this.tilingScheme.tileXYToRectangle(x, y, z); ///const center = Rectangle.center(tileRect);
906
- err = this.errorAtZoom(z);
907
- maxLength = this.maxVertexDistance(tileRect);
1421
+ if (!(pixelData == null)) {
1422
+ _context.next = 15;
1423
+ break;
1424
+ }
1425
+ return _context.abrupt("return");
1426
+ case 15:
1427
+ ///const center = Rectangle.center(tileRect);
908
1428
  params = {
909
1429
  imageData: pixelData,
910
- maxLength: maxLength,
1430
+ maxVertexDistance: maxVertexDistance,
911
1431
  x: x,
912
1432
  y: y,
913
1433
  z: z,
914
- errorLevel: err,
915
- ellipsoidRadius: this.ellipsoid.maximumRadius,
1434
+ errorLevel: errorLevel,
1435
+ ellipsoidRadius: this.tilingScheme.ellipsoid.maximumRadius,
916
1436
  tileSize: tileSize
917
1437
  };
918
- _context.next = 13;
1438
+ _context.next = 18;
919
1439
  return this.decoder.decodeTerrain(params, pixelData.buffer);
920
- case 13:
1440
+ case 18:
921
1441
  res = _context.sent;
922
- pixelData = undefined;
923
- px = undefined;
924
- return _context.abrupt("return", this.createQuantizedMeshData(tileRect, err, res));
925
- case 19:
926
- _context.prev = 19;
927
- _context.t0 = _context["catch"](1);
928
- console.log(_context.t0);
929
- return _context.abrupt("return", this.emptyMesh(x, y, z));
1442
+ meta = {
1443
+ ellipsoid: this.tilingScheme.ellipsoid,
1444
+ errorLevel: errorLevel,
1445
+ overscaleFactor: 0,
1446
+ maxVertexDistance: maxVertexDistance,
1447
+ tileRect: tileRect,
1448
+ tileSize: tileSize
1449
+ };
1450
+ /** This builds a final terrain mesh object that can optionally
1451
+ * be upscaled to a higher resolution.
1452
+ */
1453
+ return _context.abrupt("return", createTerrainMesh(res, meta));
930
1454
  case 23:
1455
+ _context.prev = 23;
1456
+ _context.t0 = _context["catch"](4);
1457
+ return _context.abrupt("return", createEmptyMesh({
1458
+ tileRect: tileRect,
1459
+ errorLevel: errorLevel,
1460
+ ellipsoid: this.tilingScheme.ellipsoid,
1461
+ tileCoord: {
1462
+ x: x,
1463
+ y: y,
1464
+ z: z
1465
+ },
1466
+ tileSize: 0
1467
+ }));
1468
+ case 26:
931
1469
  case "end":
932
1470
  return _context.stop();
933
1471
  }
934
- }, _callee, this, [[1, 19]]);
1472
+ }, _callee, this, [[4, 23]]);
935
1473
  }));
936
1474
  function processTile(_x) {
937
1475
  return _processTile.apply(this, arguments);
@@ -989,9 +1527,8 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
989
1527
  if (halfAngle > Math.PI / 4) {
990
1528
  occlusionHeight = (1 + halfAngle) * this.ellipsoid.maximumRadius;
991
1529
  }
992
- var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude, occlusionHeight
993
- // Scaling factor of two just to be sure.
994
- );
1530
+ var occlusionPoint = new cesium.Cartographic(center.longitude, center.latitude, occlusionHeight) // Scaling factor of two just to be sure.
1531
+ ;
995
1532
  var horizonOcclusionPoint = this.ellipsoid.transformPositionToScaledSpace(cesium.Cartographic.toCartesian(occlusionPoint));
996
1533
  var orientedBoundingBox = cesium.OrientedBoundingBox.fromRectangle(tileRect, minimumHeight, maximumHeight, this.tilingScheme.ellipsoid);
997
1534
  var boundingSphere = cesium.BoundingSphere.fromOrientedBoundingBox(orientedBoundingBox);
@@ -999,7 +1536,8 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
999
1536
  // SE NW NE
1000
1537
  // NE NW SE
1001
1538
 
1002
- var result = new cesium.QuantizedMeshTerrainData({
1539
+ /** TODO: we need to create raster terrain data. */
1540
+ return new cesium.QuantizedMeshTerrainData({
1003
1541
  minimumHeight: minimumHeight,
1004
1542
  maximumHeight: maximumHeight,
1005
1543
  quantizedVertices: quantizedVertices,
@@ -1017,16 +1555,21 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1017
1555
  northSkirtHeight: skirtHeight,
1018
1556
  childTileMask: 15
1019
1557
  });
1020
- return result;
1021
1558
  }
1022
1559
  }, {
1023
1560
  key: "getLevelMaximumGeometricError",
1024
1561
  value: function getLevelMaximumGeometricError(level) {
1025
1562
  var levelZeroMaximumGeometricError = cesium.TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this.tilingScheme.ellipsoid, 65, this.tilingScheme.getNumberOfXTilesAtLevel(0));
1026
1563
 
1027
- // Scalar to control overzooming
1028
- // also seems to control zooming for imagery layers
1029
- var scalar = this.resource.tileSize / 256;
1564
+ /*
1565
+ Scalar to control overzooming
1566
+ - also seems to control zooming for imagery layers
1567
+ - This scalar was causing trouble for non-256 tile sizes,
1568
+ and we've removed it for now. It could be reintroduced
1569
+ if it seems necessary
1570
+ */
1571
+ var scalar = 1; //this.resource.tileSize / 256 ;
1572
+
1030
1573
  return levelZeroMaximumGeometricError / scalar / (1 << level);
1031
1574
  }
1032
1575
  }, {
@@ -1041,38 +1584,7 @@ var MartiniTerrainProvider = /*#__PURE__*/function () {
1041
1584
  }]);
1042
1585
  }();
1043
1586
 
1044
- function decodeBase64(base64, enableUnicode) {
1045
- var binaryString = atob(base64);
1046
- if (enableUnicode) {
1047
- var binaryView = new Uint8Array(binaryString.length);
1048
- for (var i = 0, n = binaryString.length; i < n; ++i) {
1049
- binaryView[i] = binaryString.charCodeAt(i);
1050
- }
1051
- const decoder = new TextDecoder("utf-16le");
1052
- return decoder.decode(new Uint16Array(binaryView.buffer));
1053
- }
1054
- return binaryString;
1055
- }
1056
-
1057
- function createURL(base64, sourcemapArg, enableUnicodeArg) {
1058
- var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
1059
- var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
1060
- var source = decodeBase64(base64, enableUnicode);
1061
- var start = source.indexOf('\n', 10) + 1;
1062
- var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
1063
- var blob = new Blob([body], { type: 'application/javascript' });
1064
- return URL.createObjectURL(blob);
1065
- }
1066
-
1067
- function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
1068
- var url;
1069
- return function WorkerFactory(options) {
1070
- url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
1071
- return new Worker(url, options);
1072
- };
1073
- }
1074
-
1075
- var WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkociwgYSkgewogICAgKG51bGwgPT0gYSB8fCBhID4gci5sZW5ndGgpICYmIChhID0gci5sZW5ndGgpOwogICAgZm9yICh2YXIgZSA9IDAsIG4gPSBBcnJheShhKTsgZSA8IGE7IGUrKykgbltlXSA9IHJbZV07CiAgICByZXR1cm4gbjsKICB9CiAgZnVuY3Rpb24gX2FycmF5V2l0aG91dEhvbGVzKHIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KHIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkocik7CiAgfQogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkocikgewogICAgaWYgKCJ1bmRlZmluZWQiICE9IHR5cGVvZiBTeW1ib2wgJiYgbnVsbCAhPSByW1N5bWJvbC5pdGVyYXRvcl0gfHwgbnVsbCAhPSByWyJAQGl0ZXJhdG9yIl0pIHJldHVybiBBcnJheS5mcm9tKHIpOwogIH0KICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7CiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cbkluIG9yZGVyIHRvIGJlIGl0ZXJhYmxlLCBub24tYXJyYXkgb2JqZWN0cyBtdXN0IGhhdmUgYSBbU3ltYm9sLml0ZXJhdG9yXSgpIG1ldGhvZC4iKTsKICB9CiAgZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KHIpIHsKICAgIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMocikgfHwgX2l0ZXJhYmxlVG9BcnJheShyKSB8fCBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkocikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7CiAgfQogIGZ1bmN0aW9uIF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShyLCBhKSB7CiAgICBpZiAocikgewogICAgICBpZiAoInN0cmluZyIgPT0gdHlwZW9mIHIpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShyLCBhKTsKICAgICAgdmFyIHQgPSB7fS50b1N0cmluZy5jYWxsKHIpLnNsaWNlKDgsIC0xKTsKICAgICAgcmV0dXJuICJPYmplY3QiID09PSB0ICYmIHIuY29uc3RydWN0b3IgJiYgKHQgPSByLmNvbnN0cnVjdG9yLm5hbWUpLCAiTWFwIiA9PT0gdCB8fCAiU2V0IiA9PT0gdCA/IEFycmF5LmZyb20ocikgOiAiQXJndW1lbnRzIiA9PT0gdCB8fCAvXig/OlVpfEkpbnQoPzo4fDE2fDMyKSg/OkNsYW1wZWQpP0FycmF5JC8udGVzdCh0KSA/IF9hcnJheUxpa2VUb0FycmF5KHIsIGEpIDogdm9pZCAwOwogICAgfQogIH0KCiAgLy8gV2Ugc2hvdWxkIHNhdmUgdGhlc2UKICAvL2NvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoMjU2LCAyNTYpOwogIC8vY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CgogIC8qKiBNYXBib3ggVGVycmFpbi1SR0IgZGVmYXVsdCBkZWNvZGUgZnVuY3Rpb24KICAqICAociAqIDI1NiAqIDI1NikgLyAxMCArIChnICogMjU2KSAvIDEwICsgYiAvIDEwIC0gMTAwMDAKICAqLwogIHZhciBkZWZhdWx0TWFwYm94RGVjb2RlUmdiID0gZnVuY3Rpb24gZGVmYXVsdE1hcGJveERlY29kZVJnYihyLCBnLCBiLCBhKSB7CiAgICByZXR1cm4gciAqIDY1NTMuNiArIGcgKiAyNS42ICsgYiAqIDAuMSAtIDEwMDAwOwogIH07CiAgZnVuY3Rpb24gcmdiVGVycmFpblRvR3JpZChwbmcsIGRlY29kZVJnYikgewogICAgLy8gbWF5YmUgd2Ugc2hvdWxkIGRvIHRoaXMgb24gdGhlIEdQVSB1c2luZyBSRUdMPwogICAgLy8gYnV0IHRoYXQgd291bGQgcmVxdWlyZSBHUFUgLT4gQ1BVIC0+IEdQVQogICAgdmFyIGdyaWRTaXplID0gcG5nLnNoYXBlWzBdICsgMTsKICAgIHZhciB0ZXJyYWluID0gbmV3IEZsb2F0MzJBcnJheShncmlkU2l6ZSAqIGdyaWRTaXplKTsKICAgIHZhciB0aWxlU2l6ZSA9IHBuZy5zaGFwZVswXTsKICAgIHZhciBkZWNvZGUgPSBkZWNvZGVSZ2IgIT09IG51bGwgJiYgZGVjb2RlUmdiICE9PSB2b2lkIDAgPyBkZWNvZGVSZ2IgOiBkZWZhdWx0TWFwYm94RGVjb2RlUmdiOwoKICAgIC8vIGRlY29kZSB0ZXJyYWluIHZhbHVlcwogICAgZm9yICh2YXIgeSA9IDA7IHkgPCB0aWxlU2l6ZTsgeSsrKSB7CiAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgdGlsZVNpemU7IHgrKykgewogICAgICAgIHZhciB5YyA9IHk7CiAgICAgICAgdmFyIF9yID0gcG5nLmdldCh4LCB5YywgMCk7CiAgICAgICAgdmFyIF9nID0gcG5nLmdldCh4LCB5YywgMSk7CiAgICAgICAgdmFyIF9iID0gcG5nLmdldCh4LCB5YywgMik7CiAgICAgICAgdmFyIF9hID0gcG5nLmdldCh4LCB5YywgMyk7CiAgICAgICAgdGVycmFpblt5ICogZ3JpZFNpemUgKyB4XSA9IGRlY29kZShfciwgX2csIF9iLCBfYSk7CiAgICAgIH0KICAgIH0KICAgIC8vIGJhY2tmaWxsIHJpZ2h0IGFuZCBib3R0b20gYm9yZGVycwogICAgZm9yICh2YXIgX3ggPSAwOyBfeCA8IGdyaWRTaXplIC0gMTsgX3grKykgewogICAgICB0ZXJyYWluW2dyaWRTaXplICogKGdyaWRTaXplIC0gMSkgKyBfeF0gPSB0ZXJyYWluW2dyaWRTaXplICogKGdyaWRTaXplIC0gMikgKyBfeF07CiAgICB9CiAgICBmb3IgKHZhciBfeSA9IDA7IF95IDwgZ3JpZFNpemU7IF95KyspIHsKICAgICAgdGVycmFpbltncmlkU2l6ZSAqIF95ICsgZ3JpZFNpemUgLSAxXSA9IHRlcnJhaW5bZ3JpZFNpemUgKiBfeSArIGdyaWRTaXplIC0gMl07CiAgICB9CiAgICByZXR1cm4gdGVycmFpbjsKICB9CiAgZnVuY3Rpb24gY3JlYXRlUXVhbnRpemVkTWVzaERhdGEodGlsZSwgbWVzaCwgdGlsZVNpemUpIHsKICAgIHZhciB4dmFscyA9IFtdOwogICAgdmFyIHl2YWxzID0gW107CiAgICB2YXIgaGVpZ2h0TWV0ZXJzID0gW107CiAgICB2YXIgbm9ydGhJbmRpY2VzID0gW107CiAgICB2YXIgc291dGhJbmRpY2VzID0gW107CiAgICB2YXIgZWFzdEluZGljZXMgPSBbXTsKICAgIHZhciB3ZXN0SW5kaWNlcyA9IFtdOwogICAgdmFyIG1pbmltdW1IZWlnaHQgPSBJbmZpbml0eTsKICAgIHZhciBtYXhpbXVtSGVpZ2h0ID0gLUluZmluaXR5OwogICAgdmFyIHNjYWxhciA9IDMyNzY4LjAgLyB0aWxlU2l6ZTsKICAgIGZvciAodmFyIGl4ID0gMDsgaXggPCBtZXNoLnZlcnRpY2VzLmxlbmd0aCAvIDI7IGl4KyspIHsKICAgICAgdmFyIHZlcnRleEl4ID0gaXg7CiAgICAgIHZhciBweCA9IG1lc2gudmVydGljZXNbaXggKiAyXTsKICAgICAgdmFyIHB5ID0gbWVzaC52ZXJ0aWNlc1tpeCAqIDIgKyAxXTsKICAgICAgdmFyIGhlaWdodCA9IHRpbGUudGVycmFpbltweSAqICh0aWxlU2l6ZSArIDEpICsgcHhdOwogICAgICBpZiAoaGVpZ2h0ID4gbWF4aW11bUhlaWdodCkgbWF4aW11bUhlaWdodCA9IGhlaWdodDsKICAgICAgaWYgKGhlaWdodCA8IG1pbmltdW1IZWlnaHQpIG1pbmltdW1IZWlnaHQgPSBoZWlnaHQ7CiAgICAgIGhlaWdodE1ldGVycy5wdXNoKGhlaWdodCk7CiAgICAgIGlmIChweSA9PSAwKSBub3J0aEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweSA9PSB0aWxlU2l6ZSkgc291dGhJbmRpY2VzLnB1c2godmVydGV4SXgpOwogICAgICBpZiAocHggPT0gMCkgd2VzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIGlmIChweCA9PSB0aWxlU2l6ZSkgZWFzdEluZGljZXMucHVzaCh2ZXJ0ZXhJeCk7CiAgICAgIHZhciB4diA9IHB4ICogc2NhbGFyOwogICAgICB2YXIgeXYgPSAodGlsZVNpemUgLSBweSkgKiBzY2FsYXI7CiAgICAgIHh2YWxzLnB1c2goeHYpOwogICAgICB5dmFscy5wdXNoKHl2KTsKICAgIH0KICAgIHZhciBoZWlnaHRSYW5nZSA9IG1heGltdW1IZWlnaHQgLSBtaW5pbXVtSGVpZ2h0OwogICAgdmFyIGhlaWdodHMgPSBoZWlnaHRNZXRlcnMubWFwKGZ1bmN0aW9uIChkKSB7CiAgICAgIGlmIChoZWlnaHRSYW5nZSA8IDEpIHJldHVybiAwOwogICAgICByZXR1cm4gKGQgLSBtaW5pbXVtSGVpZ2h0KSAqICgzMjc2Ny4wIC8gaGVpZ2h0UmFuZ2UpOwogICAgfSk7CiAgICB2YXIgdHJpYW5nbGVzID0gbmV3IFVpbnQxNkFycmF5KG1lc2gudHJpYW5nbGVzKTsKICAgIHZhciBxdWFudGl6ZWRWZXJ0aWNlcyA9IG5ldyBVaW50MTZBcnJheSgvL3ZlcnRzCiAgICBbXS5jb25jYXQoeHZhbHMsIHl2YWxzLCBfdG9Db25zdW1hYmxlQXJyYXkoaGVpZ2h0cykpKTsKCiAgICAvLyBTRSBOVyBORQogICAgLy8gTkUgTlcgU0UKCiAgICByZXR1cm4gewogICAgICBtaW5pbXVtSGVpZ2h0OiBtaW5pbXVtSGVpZ2h0LAogICAgICBtYXhpbXVtSGVpZ2h0OiBtYXhpbXVtSGVpZ2h0LAogICAgICBxdWFudGl6ZWRWZXJ0aWNlczogcXVhbnRpemVkVmVydGljZXMsCiAgICAgIGluZGljZXM6IHRyaWFuZ2xlcywKICAgICAgd2VzdEluZGljZXM6IHdlc3RJbmRpY2VzLAogICAgICBzb3V0aEluZGljZXM6IHNvdXRoSW5kaWNlcywKICAgICAgZWFzdEluZGljZXM6IGVhc3RJbmRpY2VzLAogICAgICBub3J0aEluZGljZXM6IG5vcnRoSW5kaWNlcwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGlvdGEobikgewogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIHJlc3VsdFtpXSA9IGk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICB2YXIgaW90YV8xID0gaW90YTsKCiAgLyohCiAgICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlcgogICAqCiAgICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz4KICAgKiBAbGljZW5zZSAgTUlUCiAgICovCiAgLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZwogIC8vIE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkKICB2YXIgaXNCdWZmZXJfMSA9IGZ1bmN0aW9uIChvYmopIHsKICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpOwogIH07CiAgZnVuY3Rpb24gaXNCdWZmZXIob2JqKSB7CiAgICByZXR1cm4gISFvYmouY29uc3RydWN0b3IgJiYgdHlwZW9mIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKTsKICB9CgogIC8vIEZvciBOb2RlIHYwLjEwIHN1cHBvcnQuIFJlbW92ZSB0aGlzIGV2ZW50dWFsbHkuCiAgZnVuY3Rpb24gaXNTbG93QnVmZmVyKG9iaikgewogICAgcmV0dXJuIHR5cGVvZiBvYmoucmVhZEZsb2F0TEUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIG9iai5zbGljZSA9PT0gJ2Z1bmN0aW9uJyAmJiBpc0J1ZmZlcihvYmouc2xpY2UoMCwgMCkpOwogIH0KCiAgdmFyIGhhc1R5cGVkQXJyYXlzID0gdHlwZW9mIEZsb2F0NjRBcnJheSAhPT0gInVuZGVmaW5lZCI7CiAgZnVuY3Rpb24gY29tcGFyZTFzdChhLCBiKSB7CiAgICByZXR1cm4gYVswXSAtIGJbMF07CiAgfQogIGZ1bmN0aW9uIG9yZGVyKCkgewogICAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlOwogICAgdmFyIHRlcm1zID0gbmV3IEFycmF5KHN0cmlkZS5sZW5ndGgpOwogICAgdmFyIGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgdGVybXMubGVuZ3RoOyArK2kpIHsKICAgICAgdGVybXNbaV0gPSBbTWF0aC5hYnMoc3RyaWRlW2ldKSwgaV07CiAgICB9CiAgICB0ZXJtcy5zb3J0KGNvbXBhcmUxc3QpOwogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh0ZXJtcy5sZW5ndGgpOwogICAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5sZW5ndGg7ICsraSkgewogICAgICByZXN1bHRbaV0gPSB0ZXJtc1tpXVsxXTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgZGltZW5zaW9uKSB7CiAgICB2YXIgY2xhc3NOYW1lID0gWyJWaWV3IiwgZGltZW5zaW9uLCAiZCIsIGR0eXBlXS5qb2luKCIiKTsKICAgIGlmIChkaW1lbnNpb24gPCAwKSB7CiAgICAgIGNsYXNzTmFtZSA9ICJWaWV3X05pbCIgKyBkdHlwZTsKICAgIH0KICAgIHZhciB1c2VHZXR0ZXJzID0gZHR5cGUgPT09ICJnZW5lcmljIjsKICAgIGlmIChkaW1lbnNpb24gPT09IC0xKSB7CiAgICAgIC8vU3BlY2lhbCBjYXNlIGZvciB0cml2aWFsIGFycmF5cwogICAgICB2YXIgY29kZSA9ICJmdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIihhKXt0aGlzLmRhdGE9YTt9O1wKdmFyIHByb3RvPSIgKyBjbGFzc05hbWUgKyAiLnByb3RvdHlwZTtcCnByb3RvLmR0eXBlPSciICsgZHR5cGUgKyAiJztcCnByb3RvLmluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIC0xfTtcCnByb3RvLnNpemU9MDtcCnByb3RvLmRpbWVuc2lvbj0tMTtcCnByb3RvLnNoYXBlPXByb3RvLnN0cmlkZT1wcm90by5vcmRlcj1bXTtcCnByb3RvLmxvPXByb3RvLmhpPXByb3RvLnRyYW5zcG9zZT1wcm90by5zdGVwPVwKZnVuY3Rpb24oKXtyZXR1cm4gbmV3ICIgKyBjbGFzc05hbWUgKyAiKHRoaXMuZGF0YSk7fTtcCnByb3RvLmdldD1wcm90by5zZXQ9ZnVuY3Rpb24oKXt9O1wKcHJvdG8ucGljaz1mdW5jdGlvbigpe3JldHVybiBudWxsfTtcCnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfIiArIGNsYXNzTmFtZSArICIoYSl7cmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIihhKTt9IjsKICAgICAgdmFyIHByb2NlZHVyZSA9IG5ldyBGdW5jdGlvbihjb2RlKTsKICAgICAgcmV0dXJuIHByb2NlZHVyZSgpOwogICAgfSBlbHNlIGlmIChkaW1lbnNpb24gPT09IDApIHsKICAgICAgLy9TcGVjaWFsIGNhc2UgZm9yIDBkIGFycmF5cwogICAgICB2YXIgY29kZSA9ICJmdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIihhLGQpIHtcCnRoaXMuZGF0YSA9IGE7XAp0aGlzLm9mZnNldCA9IGRcCn07XAp2YXIgcHJvdG89IiArIGNsYXNzTmFtZSArICIucHJvdG90eXBlO1wKcHJvdG8uZHR5cGU9JyIgKyBkdHlwZSArICInO1wKcHJvdG8uaW5kZXg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vZmZzZXR9O1wKcHJvdG8uZGltZW5zaW9uPTA7XApwcm90by5zaXplPTE7XApwcm90by5zaGFwZT1cCnByb3RvLnN0cmlkZT1cCnByb3RvLm9yZGVyPVtdO1wKcHJvdG8ubG89XApwcm90by5oaT1cCnByb3RvLnRyYW5zcG9zZT1cCnByb3RvLnN0ZXA9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfY29weSgpIHtcCnJldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIodGhpcy5kYXRhLHRoaXMub2Zmc2V0KVwKfTtcCnByb3RvLnBpY2s9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfcGljaygpe1wKcmV0dXJuIFRyaXZpYWxBcnJheSh0aGlzLmRhdGEpO1wKfTtcCnByb3RvLnZhbHVlT2Y9cHJvdG8uZ2V0PWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX2dldCgpe1wKcmV0dXJuICIgKyAodXNlR2V0dGVycyA/ICJ0aGlzLmRhdGEuZ2V0KHRoaXMub2Zmc2V0KSIgOiAidGhpcy5kYXRhW3RoaXMub2Zmc2V0XSIpICsgIn07XApwcm90by5zZXQ9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfc2V0KHYpe1wKcmV0dXJuICIgKyAodXNlR2V0dGVycyA/ICJ0aGlzLmRhdGEuc2V0KHRoaXMub2Zmc2V0LHYpIiA6ICJ0aGlzLmRhdGFbdGhpcy5vZmZzZXRdPXYiKSArICJcCn07XApyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0XyIgKyBjbGFzc05hbWUgKyAiKGEsYixjLGQpe3JldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIoYSxkKX0iOwogICAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKCJUcml2aWFsQXJyYXkiLCBjb2RlKTsKICAgICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXVswXSk7CiAgICB9CiAgICB2YXIgY29kZSA9IFsiJ3VzZSBzdHJpY3QnIl07CgogICAgLy9DcmVhdGUgY29uc3RydWN0b3IgZm9yIHZpZXcKICAgIHZhciBpbmRpY2VzID0gaW90YV8xKGRpbWVuc2lvbik7CiAgICB2YXIgYXJncyA9IGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiaSIgKyBpOwogICAgfSk7CiAgICB2YXIgaW5kZXhfc3RyID0gInRoaXMub2Zmc2V0KyIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gInRoaXMuc3RyaWRlWyIgKyBpICsgIl0qaSIgKyBpOwogICAgfSkuam9pbigiKyIpOwogICAgdmFyIHNoYXBlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJiIiArIGk7CiAgICB9KS5qb2luKCIsIik7CiAgICB2YXIgc3RyaWRlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJjIiArIGk7CiAgICB9KS5qb2luKCIsIik7CiAgICBjb2RlLnB1c2goImZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiKGEsIiArIHNoYXBlQXJnICsgIiwiICsgc3RyaWRlQXJnICsgIixkKXt0aGlzLmRhdGE9YSIsICJ0aGlzLnNoYXBlPVsiICsgc2hhcGVBcmcgKyAiXSIsICJ0aGlzLnN0cmlkZT1bIiArIHN0cmlkZUFyZyArICJdIiwgInRoaXMub2Zmc2V0PWR8MH0iLCAidmFyIHByb3RvPSIgKyBjbGFzc05hbWUgKyAiLnByb3RvdHlwZSIsICJwcm90by5kdHlwZT0nIiArIGR0eXBlICsgIiciLCAicHJvdG8uZGltZW5zaW9uPSIgKyBkaW1lbnNpb24pOwoKICAgIC8vdmlldy5zaXplOgogICAgY29kZS5wdXNoKCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ3NpemUnLHtnZXQ6ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfc2l6ZSgpe1wKcmV0dXJuICIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gInRoaXMuc2hhcGVbIiArIGkgKyAiXSI7CiAgICB9KS5qb2luKCIqIiksICJ9fSkiKTsKCiAgICAvL3ZpZXcub3JkZXI6CiAgICBpZiAoZGltZW5zaW9uID09PSAxKSB7CiAgICAgIGNvZGUucHVzaCgicHJvdG8ub3JkZXI9WzBdIik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goIk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywnb3JkZXInLHtnZXQ6Iik7CiAgICAgIGlmIChkaW1lbnNpb24gPCA0KSB7CiAgICAgICAgY29kZS5wdXNoKCJmdW5jdGlvbiAiICsgY2xhc3NOYW1lICsgIl9vcmRlcigpeyIpOwogICAgICAgIGlmIChkaW1lbnNpb24gPT09IDIpIHsKICAgICAgICAgIGNvZGUucHVzaCgicmV0dXJuIChNYXRoLmFicyh0aGlzLnN0cmlkZVswXSk+TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pKT9bMSwwXTpbMCwxXX19KSIpOwogICAgICAgIH0gZWxzZSBpZiAoZGltZW5zaW9uID09PSAzKSB7CiAgICAgICAgICBjb2RlLnB1c2goInZhciBzMD1NYXRoLmFicyh0aGlzLnN0cmlkZVswXSksczE9TWF0aC5hYnModGhpcy5zdHJpZGVbMV0pLHMyPU1hdGguYWJzKHRoaXMuc3RyaWRlWzJdKTtcCmlmKHMwPnMxKXtcCmlmKHMxPnMyKXtcCnJldHVybiBbMiwxLDBdO1wKfWVsc2UgaWYoczA+czIpe1wKcmV0dXJuIFsxLDIsMF07XAp9ZWxzZXtcCnJldHVybiBbMSwwLDJdO1wKfVwKfWVsc2UgaWYoczA+czIpe1wKcmV0dXJuIFsyLDAsMV07XAp9ZWxzZSBpZihzMj5zMSl7XApyZXR1cm4gWzAsMSwyXTtcCn1lbHNle1wKcmV0dXJuIFswLDIsMV07XAp9fX0pIik7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGNvZGUucHVzaCgiT1JERVJ9KSIpOwogICAgICB9CiAgICB9CgogICAgLy92aWV3LnNldChpMCwgLi4uLCB2KToKICAgIGNvZGUucHVzaCgicHJvdG8uc2V0PWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3NldCgiICsgYXJncy5qb2luKCIsIikgKyAiLHYpeyIpOwogICAgaWYgKHVzZUdldHRlcnMpIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhLnNldCgiICsgaW5kZXhfc3RyICsgIix2KX0iKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUucHVzaCgicmV0dXJuIHRoaXMuZGF0YVsiICsgaW5kZXhfc3RyICsgIl09dn0iKTsKICAgIH0KCiAgICAvL3ZpZXcuZ2V0KGkwLCAuLi4pOgogICAgY29kZS5wdXNoKCJwcm90by5nZXQ9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfZ2V0KCIgKyBhcmdzLmpvaW4oIiwiKSArICIpeyIpOwogICAgaWYgKHVzZUdldHRlcnMpIHsKICAgICAgY29kZS5wdXNoKCJyZXR1cm4gdGhpcy5kYXRhLmdldCgiICsgaW5kZXhfc3RyICsgIil9Iik7CiAgICB9IGVsc2UgewogICAgICBjb2RlLnB1c2goInJldHVybiB0aGlzLmRhdGFbIiArIGluZGV4X3N0ciArICJdfSIpOwogICAgfQoKICAgIC8vdmlldy5pbmRleDoKICAgIGNvZGUucHVzaCgicHJvdG8uaW5kZXg9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfaW5kZXgoIiwgYXJncy5qb2luKCksICIpe3JldHVybiAiICsgaW5kZXhfc3RyICsgIn0iKTsKCiAgICAvL3ZpZXcuaGkoKToKICAgIGNvZGUucHVzaCgicHJvdG8uaGk9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfaGkoIiArIGFyZ3Muam9pbigiLCIpICsgIil7cmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIih0aGlzLmRhdGEsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiBbIih0eXBlb2YgaSIsIGksICIhPT0nbnVtYmVyJ3x8aSIsIGksICI8MCk/dGhpcy5zaGFwZVsiLCBpLCAiXTppIiwgaSwgInwwIl0uam9pbigiIik7CiAgICB9KS5qb2luKCIsIikgKyAiLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gInRoaXMuc3RyaWRlWyIgKyBpICsgIl0iOwogICAgfSkuam9pbigiLCIpICsgIix0aGlzLm9mZnNldCl9Iik7CgogICAgLy92aWV3LmxvKCk6CiAgICB2YXIgYV92YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJhIiArIGkgKyAiPXRoaXMuc2hhcGVbIiArIGkgKyAiXSI7CiAgICB9KTsKICAgIHZhciBjX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImMiICsgaSArICI9dGhpcy5zdHJpZGVbIiArIGkgKyAiXSI7CiAgICB9KTsKICAgIGNvZGUucHVzaCgicHJvdG8ubG89ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfbG8oIiArIGFyZ3Muam9pbigiLCIpICsgIil7dmFyIGI9dGhpcy5vZmZzZXQsZD0wLCIgKyBhX3ZhcnMuam9pbigiLCIpICsgIiwiICsgY192YXJzLmpvaW4oIiwiKSk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIGNvZGUucHVzaCgiaWYodHlwZW9mIGkiICsgaSArICI9PT0nbnVtYmVyJyYmaSIgKyBpICsgIj49MCl7XApkPWkiICsgaSArICJ8MDtcCmIrPWMiICsgaSArICIqZDtcCmEiICsgaSArICItPWR9Iik7CiAgICB9CiAgICBjb2RlLnB1c2goInJldHVybiBuZXcgIiArIGNsYXNzTmFtZSArICIodGhpcy5kYXRhLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImEiICsgaTsKICAgIH0pLmpvaW4oIiwiKSArICIsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYyIgKyBpOwogICAgfSkuam9pbigiLCIpICsgIixiKX0iKTsKCiAgICAvL3ZpZXcuc3RlcCgpOgogICAgY29kZS5wdXNoKCJwcm90by5zdGVwPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3N0ZXAoIiArIGFyZ3Muam9pbigiLCIpICsgIil7dmFyICIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gImEiICsgaSArICI9dGhpcy5zaGFwZVsiICsgaSArICJdIjsKICAgIH0pLmpvaW4oIiwiKSArICIsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYiIgKyBpICsgIj10aGlzLnN0cmlkZVsiICsgaSArICJdIjsKICAgIH0pLmpvaW4oIiwiKSArICIsYz10aGlzLm9mZnNldCxkPTAsY2VpbD1NYXRoLmNlaWwiKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGltZW5zaW9uOyArK2kpIHsKICAgICAgY29kZS5wdXNoKCJpZih0eXBlb2YgaSIgKyBpICsgIj09PSdudW1iZXInKXtcCmQ9aSIgKyBpICsgInwwO1wKaWYoZDwwKXtcCmMrPWIiICsgaSArICIqKGEiICsgaSArICItMSk7XAphIiArIGkgKyAiPWNlaWwoLWEiICsgaSArICIvZClcCn1lbHNle1wKYSIgKyBpICsgIj1jZWlsKGEiICsgaSArICIvZClcCn1cCmIiICsgaSArICIqPWRcCn0iKTsKICAgIH0KICAgIGNvZGUucHVzaCgicmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIih0aGlzLmRhdGEsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAiYSIgKyBpOwogICAgfSkuam9pbigiLCIpICsgIiwiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24gKGkpIHsKICAgICAgcmV0dXJuICJiIiArIGk7CiAgICB9KS5qb2luKCIsIikgKyAiLGMpfSIpOwoKICAgIC8vdmlldy50cmFuc3Bvc2UoKToKICAgIHZhciB0U2hhcGUgPSBuZXcgQXJyYXkoZGltZW5zaW9uKTsKICAgIHZhciB0U3RyaWRlID0gbmV3IEFycmF5KGRpbWVuc2lvbik7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpbWVuc2lvbjsgKytpKSB7CiAgICAgIHRTaGFwZVtpXSA9ICJhW2kiICsgaSArICJdIjsKICAgICAgdFN0cmlkZVtpXSA9ICJiW2kiICsgaSArICJdIjsKICAgIH0KICAgIGNvZGUucHVzaCgicHJvdG8udHJhbnNwb3NlPWZ1bmN0aW9uICIgKyBjbGFzc05hbWUgKyAiX3RyYW5zcG9zZSgiICsgYXJncyArICIpeyIgKyBhcmdzLm1hcChmdW5jdGlvbiAobiwgaWR4KSB7CiAgICAgIHJldHVybiBuICsgIj0oIiArIG4gKyAiPT09dW5kZWZpbmVkPyIgKyBpZHggKyAiOiIgKyBuICsgInwwKSI7CiAgICB9KS5qb2luKCI7IiksICJ2YXIgYT10aGlzLnNoYXBlLGI9dGhpcy5zdHJpZGU7cmV0dXJuIG5ldyAiICsgY2xhc3NOYW1lICsgIih0aGlzLmRhdGEsIiArIHRTaGFwZS5qb2luKCIsIikgKyAiLCIgKyB0U3RyaWRlLmpvaW4oIiwiKSArICIsdGhpcy5vZmZzZXQpfSIpOwoKICAgIC8vdmlldy5waWNrKCk6CiAgICBjb2RlLnB1c2goInByb3RvLnBpY2s9ZnVuY3Rpb24gIiArIGNsYXNzTmFtZSArICJfcGljaygiICsgYXJncyArICIpe3ZhciBhPVtdLGI9W10sYz10aGlzLm9mZnNldCIpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkaW1lbnNpb247ICsraSkgewogICAgICBjb2RlLnB1c2goImlmKHR5cGVvZiBpIiArIGkgKyAiPT09J251bWJlcicmJmkiICsgaSArICI+PTApe2M9KGMrdGhpcy5zdHJpZGVbIiArIGkgKyAiXSppIiArIGkgKyAiKXwwfWVsc2V7YS5wdXNoKHRoaXMuc2hhcGVbIiArIGkgKyAiXSk7Yi5wdXNoKHRoaXMuc3RyaWRlWyIgKyBpICsgIl0pfSIpOwogICAgfQogICAgY29kZS5wdXNoKCJ2YXIgY3Rvcj1DVE9SX0xJU1RbYS5sZW5ndGgrMV07cmV0dXJuIGN0b3IodGhpcy5kYXRhLGEsYixjKX0iKTsKCiAgICAvL0FkZCByZXR1cm4gc3RhdGVtZW50CiAgICBjb2RlLnB1c2goInJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfIiArIGNsYXNzTmFtZSArICIoZGF0YSxzaGFwZSxzdHJpZGUsb2Zmc2V0KXtyZXR1cm4gbmV3ICIgKyBjbGFzc05hbWUgKyAiKGRhdGEsIiArIGluZGljZXMubWFwKGZ1bmN0aW9uIChpKSB7CiAgICAgIHJldHVybiAic2hhcGVbIiArIGkgKyAiXSI7CiAgICB9KS5qb2luKCIsIikgKyAiLCIgKyBpbmRpY2VzLm1hcChmdW5jdGlvbiAoaSkgewogICAgICByZXR1cm4gInN0cmlkZVsiICsgaSArICJdIjsKICAgIH0pLmpvaW4oIiwiKSArICIsb2Zmc2V0KX0iKTsKCiAgICAvL0NvbXBpbGUgcHJvY2VkdXJlCiAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKCJDVE9SX0xJU1QiLCAiT1JERVIiLCBjb2RlLmpvaW4oIlxuIikpOwogICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXSwgb3JkZXIpOwogIH0KICBmdW5jdGlvbiBhcnJheURUeXBlKGRhdGEpIHsKICAgIGlmIChpc0J1ZmZlcl8xKGRhdGEpKSB7CiAgICAgIHJldHVybiAiYnVmZmVyIjsKICAgIH0KICAgIGlmIChoYXNUeXBlZEFycmF5cykgewogICAgICBzd2l0Y2ggKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSkgewogICAgICAgIGNhc2UgIltvYmplY3QgRmxvYXQ2NEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImZsb2F0NjQiOwogICAgICAgIGNhc2UgIltvYmplY3QgRmxvYXQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImZsb2F0MzIiOwogICAgICAgIGNhc2UgIltvYmplY3QgSW50OEFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImludDgiOwogICAgICAgIGNhc2UgIltvYmplY3QgSW50MTZBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJpbnQxNiI7CiAgICAgICAgY2FzZSAiW29iamVjdCBJbnQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gImludDMyIjsKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQ4QXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDgiOwogICAgICAgIGNhc2UgIltvYmplY3QgVWludDE2QXJyYXldIjoKICAgICAgICAgIHJldHVybiAidWludDE2IjsKICAgICAgICBjYXNlICJbb2JqZWN0IFVpbnQzMkFycmF5XSI6CiAgICAgICAgICByZXR1cm4gInVpbnQzMiI7CiAgICAgICAgY2FzZSAiW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0iOgogICAgICAgICAgcmV0dXJuICJ1aW50OF9jbGFtcGVkIjsKICAgICAgICBjYXNlICJbb2JqZWN0IEJpZ0ludDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiYmlnaW50NjQiOwogICAgICAgIGNhc2UgIltvYmplY3QgQmlnVWludDY0QXJyYXldIjoKICAgICAgICAgIHJldHVybiAiYmlndWludDY0IjsKICAgICAgfQogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHsKICAgICAgcmV0dXJuICJhcnJheSI7CiAgICB9CiAgICByZXR1cm4gImdlbmVyaWMiOwogIH0KICB2YXIgQ0FDSEVEX0NPTlNUUlVDVE9SUyA9IHsKICAgICJmbG9hdDMyIjogW10sCiAgICAiZmxvYXQ2NCI6IFtdLAogICAgImludDgiOiBbXSwKICAgICJpbnQxNiI6IFtdLAogICAgImludDMyIjogW10sCiAgICAidWludDgiOiBbXSwKICAgICJ1aW50MTYiOiBbXSwKICAgICJ1aW50MzIiOiBbXSwKICAgICJhcnJheSI6IFtdLAogICAgInVpbnQ4X2NsYW1wZWQiOiBbXSwKICAgICJiaWdpbnQ2NCI6IFtdLAogICAgImJpZ3VpbnQ2NCI6IFtdLAogICAgImJ1ZmZlciI6IFtdLAogICAgImdlbmVyaWMiOiBbXQogIH07CiAgZnVuY3Rpb24gd3JhcHBlZE5EQXJyYXlDdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkgewogICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgY3RvciA9IENBQ0hFRF9DT05TVFJVQ1RPUlMuYXJyYXlbMF07CiAgICAgIHJldHVybiBjdG9yKFtdKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEgPT09ICJudW1iZXIiKSB7CiAgICAgIGRhdGEgPSBbZGF0YV07CiAgICB9CiAgICBpZiAoc2hhcGUgPT09IHVuZGVmaW5lZCkgewogICAgICBzaGFwZSA9IFtkYXRhLmxlbmd0aF07CiAgICB9CiAgICB2YXIgZCA9IHNoYXBlLmxlbmd0aDsKICAgIGlmIChzdHJpZGUgPT09IHVuZGVmaW5lZCkgewogICAgICBzdHJpZGUgPSBuZXcgQXJyYXkoZCk7CiAgICAgIGZvciAodmFyIGkgPSBkIC0gMSwgc3ogPSAxOyBpID49IDA7IC0taSkgewogICAgICAgIHN0cmlkZVtpXSA9IHN6OwogICAgICAgIHN6ICo9IHNoYXBlW2ldOwogICAgICB9CiAgICB9CiAgICBpZiAob2Zmc2V0ID09PSB1bmRlZmluZWQpIHsKICAgICAgb2Zmc2V0ID0gMDsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkOyArK2kpIHsKICAgICAgICBpZiAoc3RyaWRlW2ldIDwgMCkgewogICAgICAgICAgb2Zmc2V0IC09IChzaGFwZVtpXSAtIDEpICogc3RyaWRlW2ldOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdmFyIGR0eXBlID0gYXJyYXlEVHlwZShkYXRhKTsKICAgIHZhciBjdG9yX2xpc3QgPSBDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXTsKICAgIHdoaWxlIChjdG9yX2xpc3QubGVuZ3RoIDw9IGQgKyAxKSB7CiAgICAgIGN0b3JfbGlzdC5wdXNoKGNvbXBpbGVDb25zdHJ1Y3RvcihkdHlwZSwgY3Rvcl9saXN0Lmxlbmd0aCAtIDEpKTsKICAgIH0KICAgIHZhciBjdG9yID0gY3Rvcl9saXN0W2QgKyAxXTsKICAgIHJldHVybiBjdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCk7CiAgfQogIHZhciBuZGFycmF5ID0gd3JhcHBlZE5EQXJyYXlDdG9yOwoKICBjbGFzcyBNYXJ0aW5pIHsKICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgIGlmICh0aWxlU2l6ZSAmIHRpbGVTaXplIC0gMSkgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBncmlkIHNpemUgdG8gYmUgMl5uKzEsIGdvdCAke2dyaWRTaXplfS5gKTsKICAgICAgdGhpcy5udW1UcmlhbmdsZXMgPSB0aWxlU2l6ZSAqIHRpbGVTaXplICogMiAtIDI7CiAgICAgIHRoaXMubnVtUGFyZW50VHJpYW5nbGVzID0gdGhpcy5udW1UcmlhbmdsZXMgLSB0aWxlU2l6ZSAqIHRpbGVTaXplOwogICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOwoKICAgICAgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCiAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7CgogICAgICAvLyBnZXQgdHJpYW5nbGUgY29vcmRpbmF0ZXMgZnJvbSBpdHMgaW5kZXggaW4gYW4gaW1wbGljaXQgYmluYXJ5IHRyZWUKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgbGV0IGlkID0gaSArIDI7CiAgICAgICAgbGV0IGF4ID0gMCwKICAgICAgICAgIGF5ID0gMCwKICAgICAgICAgIGJ4ID0gMCwKICAgICAgICAgIGJ5ID0gMCwKICAgICAgICAgIGN4ID0gMCwKICAgICAgICAgIGN5ID0gMDsKICAgICAgICBpZiAoaWQgJiAxKSB7CiAgICAgICAgICBieCA9IGJ5ID0gY3ggPSB0aWxlU2l6ZTsgLy8gYm90dG9tLWxlZnQgdHJpYW5nbGUKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYXggPSBheSA9IGN5ID0gdGlsZVNpemU7IC8vIHRvcC1yaWdodCB0cmlhbmdsZQogICAgICAgIH0KICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CiAgICAgICAgICBpZiAoaWQgJiAxKSB7CiAgICAgICAgICAgIC8vIGxlZnQgaGFsZgogICAgICAgICAgICBieCA9IGF4OwogICAgICAgICAgICBieSA9IGF5OwogICAgICAgICAgICBheCA9IGN4OwogICAgICAgICAgICBheSA9IGN5OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gcmlnaHQgaGFsZgogICAgICAgICAgICBheCA9IGJ4OwogICAgICAgICAgICBheSA9IGJ5OwogICAgICAgICAgICBieCA9IGN4OwogICAgICAgICAgICBieSA9IGN5OwogICAgICAgICAgfQogICAgICAgICAgY3ggPSBteDsKICAgICAgICAgIGN5ID0gbXk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMF0gPSBheDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgMl0gPSBieDsKICAgICAgICB0aGlzLmNvb3Jkc1trICsgM10gPSBieTsKICAgICAgfQogICAgfQogICAgY3JlYXRlVGlsZSh0ZXJyYWluKSB7CiAgICAgIHJldHVybiBuZXcgVGlsZSh0ZXJyYWluLCB0aGlzKTsKICAgIH0KICB9CiAgY2xhc3MgVGlsZSB7CiAgICBjb25zdHJ1Y3Rvcih0ZXJyYWluLCBtYXJ0aW5pKSB7CiAgICAgIGNvbnN0IHNpemUgPSBtYXJ0aW5pLmdyaWRTaXplOwogICAgICBpZiAodGVycmFpbi5sZW5ndGggIT09IHNpemUgKiBzaXplKSB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHRlcnJhaW4gZGF0YSBvZiBsZW5ndGggJHtzaXplICogc2l6ZX0gKCR7c2l6ZX0geCAke3NpemV9KSwgZ290ICR7dGVycmFpbi5sZW5ndGh9LmApOwogICAgICB0aGlzLnRlcnJhaW4gPSB0ZXJyYWluOwogICAgICB0aGlzLm1hcnRpbmkgPSBtYXJ0aW5pOwogICAgICB0aGlzLmVycm9ycyA9IG5ldyBGbG9hdDMyQXJyYXkodGVycmFpbi5sZW5ndGgpOwogICAgICB0aGlzLnVwZGF0ZSgpOwogICAgfQogICAgdXBkYXRlKCkgewogICAgICBjb25zdCB7CiAgICAgICAgbnVtVHJpYW5nbGVzLAogICAgICAgIG51bVBhcmVudFRyaWFuZ2xlcywKICAgICAgICBjb29yZHMsCiAgICAgICAgZ3JpZFNpemU6IHNpemUKICAgICAgfSA9IHRoaXMubWFydGluaTsKICAgICAgY29uc3QgewogICAgICAgIHRlcnJhaW4sCiAgICAgICAgZXJyb3JzCiAgICAgIH0gPSB0aGlzOwoKICAgICAgLy8gaXRlcmF0ZSBvdmVyIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMsIHN0YXJ0aW5nIGZyb20gdGhlIHNtYWxsZXN0IGxldmVsCiAgICAgIGZvciAobGV0IGkgPSBudW1UcmlhbmdsZXMgLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICBjb25zdCBheCA9IGNvb3Jkc1trICsgMF07CiAgICAgICAgY29uc3QgYXkgPSBjb29yZHNbayArIDFdOwogICAgICAgIGNvbnN0IGJ4ID0gY29vcmRzW2sgKyAyXTsKICAgICAgICBjb25zdCBieSA9IGNvb3Jkc1trICsgM107CiAgICAgICAgY29uc3QgbXggPSBheCArIGJ4ID4+IDE7CiAgICAgICAgY29uc3QgbXkgPSBheSArIGJ5ID4+IDE7CiAgICAgICAgY29uc3QgY3ggPSBteCArIG15IC0gYXk7CiAgICAgICAgY29uc3QgY3kgPSBteSArIGF4IC0gbXg7CgogICAgICAgIC8vIGNhbGN1bGF0ZSBlcnJvciBpbiB0aGUgbWlkZGxlIG9mIHRoZSBsb25nIGVkZ2Ugb2YgdGhlIHRyaWFuZ2xlCiAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkSGVpZ2h0ID0gKHRlcnJhaW5bYXkgKiBzaXplICsgYXhdICsgdGVycmFpbltieSAqIHNpemUgKyBieF0pIC8gMjsKICAgICAgICBjb25zdCBtaWRkbGVJbmRleCA9IG15ICogc2l6ZSArIG14OwogICAgICAgIGNvbnN0IG1pZGRsZUVycm9yID0gTWF0aC5hYnMoaW50ZXJwb2xhdGVkSGVpZ2h0IC0gdGVycmFpblttaWRkbGVJbmRleF0pOwogICAgICAgIGVycm9yc1ttaWRkbGVJbmRleF0gPSBNYXRoLm1heChlcnJvcnNbbWlkZGxlSW5kZXhdLCBtaWRkbGVFcnJvcik7CiAgICAgICAgaWYgKGkgPCBudW1QYXJlbnRUcmlhbmdsZXMpIHsKICAgICAgICAgIC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgY29uc3QgbGVmdENoaWxkSW5kZXggPSAoYXkgKyBjeSA+PiAxKSAqIHNpemUgKyAoYXggKyBjeCA+PiAxKTsKICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9IChieSArIGN5ID4+IDEpICogc2l6ZSArIChieCArIGN4ID4+IDEpOwogICAgICAgICAgZXJyb3JzW21pZGRsZUluZGV4XSA9IE1hdGgubWF4KGVycm9yc1ttaWRkbGVJbmRleF0sIGVycm9yc1tsZWZ0Q2hpbGRJbmRleF0sIGVycm9yc1tyaWdodENoaWxkSW5kZXhdKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGdldE1lc2gobWF4RXJyb3IgPSAwLCBtYXhMZW5ndGggPSBudWxsKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBncmlkU2l6ZTogc2l6ZSwKICAgICAgICBpbmRpY2VzCiAgICAgIH0gPSB0aGlzLm1hcnRpbmk7CiAgICAgIGNvbnN0IHsKICAgICAgICBlcnJvcnMKICAgICAgfSA9IHRoaXM7CiAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgIGxldCBudW1UcmlhbmdsZXMgPSAwOwogICAgICBjb25zdCBtYXggPSBzaXplIC0gMTsKCiAgICAgIC8vIFRoZSBtYXhMZW5ndGggcGFyYW1ldGVyIHdpbGwgY2F1c2UgdHJpYW5nbGVzIHRvIGJlIGdlbmVyYXRlZCB1bnRpbCB0aGUgbGVncyBhcmUgYmVsb3cgdGhpcyBsZW5ndGgKICAgICAgLy8gSXQgaXMgbWVhbnQgdG8gc3VwcG9ydCBjYXNlcyB3aGVyZSBhIGNlcnRhaW4gbWVzaCBkZW5zaXR5IGlzIHJlcXVpcmVkIHRvIGRvIHNwaGVyaWNhbCBtYXRoIG9uIGRpZ2l0YWwgZ2xvYmVzCiAgICAgIGNvbnN0IG1heFNjYWxlID0gbWF4TGVuZ3RoIHx8IHNpemU7CgogICAgICAvLyB1c2UgYW4gaW5kZXggZ3JpZCB0byBrZWVwIHRyYWNrIG9mIHZlcnRpY2VzIHRoYXQgd2VyZSBhbHJlYWR5IHVzZWQgdG8gYXZvaWQgZHVwbGljYXRpb24KICAgICAgaW5kaWNlcy5maWxsKDApOwoKICAgICAgLy8gcmV0cmlldmUgbWVzaCBpbiB0d28gc3RhZ2VzIHRoYXQgYm90aCB0cmF2ZXJzZSB0aGUgZXJyb3IgbWFwOgogICAgICAvLyAtIGNvdW50RWxlbWVudHM6IGZpbmQgdXNlZCB2ZXJ0aWNlcyAoYW5kIGFzc2lnbiBlYWNoIGFuIGluZGV4KSwgYW5kIGNvdW50IHRyaWFuZ2xlcyAoZm9yIG1pbmltdW0gYWxsb2NhdGlvbikKICAgICAgLy8gLSBwcm9jZXNzVHJpYW5nbGU6IGZpbGwgdGhlIGFsbG9jYXRlZCB2ZXJ0aWNlcyAmIHRyaWFuZ2xlcyB0eXBlZCBhcnJheXMKCiAgICAgIGZ1bmN0aW9uIGNvdW50RWxlbWVudHMoYXgsIGF5LCBieCwgYnksIGN4LCBjeSkgewogICAgICAgIGNvbnN0IG14ID0gYXggKyBieCA+PiAxOwogICAgICAgIGNvbnN0IG15ID0gYXkgKyBieSA+PiAxOwogICAgICAgIGNvbnN0IGxlZ0xlbmd0aCA9IE1hdGguYWJzKGF4IC0gY3gpICsgTWF0aC5hYnMoYXkgLSBjeSk7CiAgICAgICAgaWYgKGxlZ0xlbmd0aCA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yIHx8IGxlZ0xlbmd0aCA+IG1heFNjYWxlKSB7CiAgICAgICAgICBjb3VudEVsZW1lbnRzKGN4LCBjeSwgYXgsIGF5LCBteCwgbXkpOwogICAgICAgICAgY291bnRFbGVtZW50cyhieCwgYnksIGN4LCBjeSwgbXgsIG15KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaW5kaWNlc1theSAqIHNpemUgKyBheF0gPSBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgaW5kaWNlc1tieSAqIHNpemUgKyBieF0gPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gPSBpbmRpY2VzW2N5ICogc2l6ZSArIGN4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgbnVtVHJpYW5nbGVzKys7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvdW50RWxlbWVudHMoMCwgMCwgbWF4LCBtYXgsIG1heCwgMCk7CiAgICAgIGNvdW50RWxlbWVudHMobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CiAgICAgIGNvbnN0IHZlcnRpY2VzID0gbmV3IFVpbnQxNkFycmF5KG51bVZlcnRpY2VzICogMik7CiAgICAgIGNvbnN0IHRyaWFuZ2xlcyA9IG5ldyBVaW50MzJBcnJheShudW1UcmlhbmdsZXMgKiAzKTsKICAgICAgbGV0IHRyaUluZGV4ID0gMDsKICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICBjb25zdCBteCA9IGF4ICsgYnggPj4gMTsKICAgICAgICBjb25zdCBteSA9IGF5ICsgYnkgPj4gMTsKICAgICAgICBjb25zdCBsZWdMZW5ndGggPSBNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpOwogICAgICAgIGlmIChsZWdMZW5ndGggPiAxICYmIGVycm9yc1tteSAqIHNpemUgKyBteF0gPiBtYXhFcnJvciB8fCBsZWdMZW5ndGggPiBtYXhTY2FsZSkgewogICAgICAgICAgLy8gdHJpYW5nbGUgZG9lc24ndCBhcHByb3hpbWF0ZSB0aGUgc3VyZmFjZSB3ZWxsIGVub3VnaDsgZHJpbGwgZG93biBmdXJ0aGVyCiAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoYngsIGJ5LCBjeCwgY3ksIG14LCBteSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIGFkZCBhIHRyaWFuZ2xlCiAgICAgICAgICBjb25zdCBhID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gLSAxOwogICAgICAgICAgY29uc3QgYiA9IGluZGljZXNbYnkgKiBzaXplICsgYnhdIC0gMTsKICAgICAgICAgIGNvbnN0IGMgPSBpbmRpY2VzW2N5ICogc2l6ZSArIGN4XSAtIDE7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYV0gPSBheDsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBhICsgMV0gPSBheTsKICAgICAgICAgIHZlcnRpY2VzWzIgKiBiXSA9IGJ4OwogICAgICAgICAgdmVydGljZXNbMiAqIGIgKyAxXSA9IGJ5OwogICAgICAgICAgdmVydGljZXNbMiAqIGNdID0gY3g7CiAgICAgICAgICB2ZXJ0aWNlc1syICogYyArIDFdID0gY3k7CiAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBhOwogICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYjsKICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGM7CiAgICAgICAgfQogICAgICB9CiAgICAgIHByb2Nlc3NUcmlhbmdsZSgwLCAwLCBtYXgsIG1heCwgbWF4LCAwKTsKICAgICAgcHJvY2Vzc1RyaWFuZ2xlKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwogICAgICByZXR1cm4gewogICAgICAgIHZlcnRpY2VzLAogICAgICAgIHRyaWFuZ2xlcwogICAgICB9OwogICAgfQogIH0KCiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL0Nlc2l1bUdTL2Nlc2l1bS9ibG9iLzEuNzYvU291cmNlL1dvcmtlcnNFUzYvY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2guanMKCiAgdmFyIG1hcnRpbmkgPSBudWxsOwogIGZ1bmN0aW9uIGRlY29kZVRlcnJhaW4ocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgdmFyIGltYWdlRGF0YSA9IHBhcmFtZXRlcnMuaW1hZ2VEYXRhLAogICAgICBfcGFyYW1ldGVycyR0aWxlU2l6ZSA9IHBhcmFtZXRlcnMudGlsZVNpemUsCiAgICAgIHRpbGVTaXplID0gX3BhcmFtZXRlcnMkdGlsZVNpemUgPT09IHZvaWQgMCA/IDI1NiA6IF9wYXJhbWV0ZXJzJHRpbGVTaXplLAogICAgICBlcnJvckxldmVsID0gcGFyYW1ldGVycy5lcnJvckxldmVsOwogICAgdmFyIHBpeGVscyA9IG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoaW1hZ2VEYXRhKSwgW3RpbGVTaXplLCB0aWxlU2l6ZSwgNF0sIFs0LCA0ICogdGlsZVNpemUsIDFdLCAwKTsKCiAgICAvLyBUaWxlIHNpemUgbXVzdCBiZSBtYWludGFpbmVkIHRocm91Z2ggdGhlIGxpZmUgb2YgdGhlIHdvcmtlcgogICAgbWFydGluaSAhPT0gbnVsbCAmJiBtYXJ0aW5pICE9PSB2b2lkIDAgPyBtYXJ0aW5pIDogbWFydGluaSA9IG5ldyBNYXJ0aW5pKHRpbGVTaXplICsgMSk7CiAgICB2YXIgdGVycmFpbiA9IHJnYlRlcnJhaW5Ub0dyaWQocGl4ZWxzKTsKICAgIHZhciB0aWxlID0gbWFydGluaS5jcmVhdGVUaWxlKHRlcnJhaW4pOwoKICAgIC8vIGdldCBhIG1lc2ggKHZlcnRpY2VzIGFuZCB0cmlhbmdsZXMgaW5kaWNlcykgZm9yIGEgMTBtIGVycm9yCiAgICB2YXIgbWVzaCA9IHRpbGUuZ2V0TWVzaChlcnJvckxldmVsLCBwYXJhbWV0ZXJzLm1heExlbmd0aCk7CiAgICByZXR1cm4gY3JlYXRlUXVhbnRpemVkTWVzaERhdGEodGlsZSwgbWVzaCwgdGlsZVNpemUpOwogIH0KICBzZWxmLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChtc2cpIHsKICAgIHZhciBfbXNnJGRhdGEgPSBtc2cuZGF0YSwKICAgICAgaWQgPSBfbXNnJGRhdGEuaWQsCiAgICAgIHBheWxvYWQgPSBfbXNnJGRhdGEucGF5bG9hZDsKICAgIGlmIChpZCA9PSBudWxsKSByZXR1cm47CiAgICB2YXIgb2JqZWN0cyA9IFtdOwogICAgdmFyIHJlcyA9IG51bGw7CiAgICB0cnkgewogICAgICByZXMgPSBkZWNvZGVUZXJyYWluKHBheWxvYWQpOwogICAgICBvYmplY3RzLnB1c2gocmVzLmluZGljZXMuYnVmZmVyKTsKICAgICAgb2JqZWN0cy5wdXNoKHJlcy5xdWFudGl6ZWRWZXJ0aWNlcy5idWZmZXIpOwogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogaWQsCiAgICAgICAgcGF5bG9hZDogcmVzCiAgICAgIH0sIG9iamVjdHMpOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIHNlbGYucG9zdE1lc3NhZ2UoewogICAgICAgIGlkOiBpZCwKICAgICAgICBlcnI6IGVyci50b1N0cmluZygpCiAgICAgIH0pOwogICAgfSBmaW5hbGx5IHsKICAgICAgcmVzID0gbnVsbDsKICAgICAgb2JqZWN0cyA9IG51bGw7CiAgICB9CiAgfTsKCn0pKCk7Cgo=', null, false);
1587
+ 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);
1076
1588
  /* eslint-enable */
1077
1589
 
1078
1590
  var MapboxTerrainProvider = /*#__PURE__*/function (_MartiniTerrainProvid) {
@@ -1093,7 +1605,15 @@ var MapboxTerrainProvider = /*#__PURE__*/function (_MartiniTerrainProvid) {
1093
1605
  }(MartiniTerrainProvider);
1094
1606
 
1095
1607
  exports.DefaultHeightmapResource = DefaultHeightmapResource;
1608
+ exports.DefaultTerrainDecoder = DefaultTerrainDecoder;
1096
1609
  exports.MapboxTerrainResource = MapboxTerrainResource;
1097
1610
  exports.MartiniTerrainProvider = MartiniTerrainProvider;
1611
+ exports.StretchedTilingScheme = StretchedTilingScheme;
1612
+ exports.WorkerFarmTerrainDecoder = WorkerFarmTerrainDecoder;
1613
+ exports.createQuantizedMeshData = createQuantizedMeshData;
1098
1614
  exports["default"] = MapboxTerrainProvider;
1615
+ exports.emptyMesh = emptyMesh;
1616
+ exports.rgbTerrainToGrid = rgbTerrainToGrid;
1617
+ exports.subsetByWindow = subsetByWindow;
1618
+ exports.testMeshData = testMeshData;
1099
1619
  //# sourceMappingURL=index.cjs.map