@gisatcz/deckgl-geolib 2.7.0-dev.1 → 2.7.0-dev.2

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/esm/index.js CHANGED
@@ -5673,6 +5673,9 @@ function isF32NoData(val, noData) {
5673
5673
  return Number.isNaN(a);
5674
5674
  return a === b;
5675
5675
  }
5676
+ function isStitchedGrid(width) {
5677
+ return width > 1 && ((width - 1) & (width - 2)) === 0;
5678
+ }
5676
5679
 
5677
5680
  class BitmapGenerator {
5678
5681
  /**
@@ -6084,10 +6087,16 @@ class BitmapGenerator {
6084
6087
  /**
6085
6088
  * KernelGenerator — 3×3 neighborhood kernel calculations on elevation rasters.
6086
6089
  *
6087
- * Input contract: a Float32Array of 258×258 elevation values (row-major).
6088
- * Edge pixels (row/col 0 and 257) are used only as kernel neighbors and do
6090
+ * Input contract: a Float32Array of (N+2)×(N+2) elevation values (row-major),
6091
+ * where N is a power-of-2 tile size (256, 128, 64, …). The 2-pixel border is
6092
+ * stitched padding (+1) on one side and kernel neighborhood padding (+1) on
6093
+ * the opposite side. At native zoom (256×256 tile), this produces the classic
6094
+ * 258×258 input (256 + 1 stitching + 1 kernel). At extended zoom (e.g. 128×128
6095
+ * tile), it produces 130×130.
6096
+ *
6097
+ * Edge pixels (row/col 0 and N+1) are used only as kernel neighbors and do
6089
6098
  * not appear in the output.
6090
- * Output: Float32Array of 256×256 computed values.
6099
+ * Output: Float32Array of N×N computed values.
6091
6100
  */
6092
6101
  class KernelGenerator {
6093
6102
  /**
@@ -6114,8 +6123,8 @@ class KernelGenerator {
6114
6123
  * @param noDataValue Elevation value treated as noData; output is NaN for those pixels
6115
6124
  */
6116
6125
  static calculateSlope(src, cellSize, zFactor = 1, noDataValue) {
6117
- const OUT = 256;
6118
- const IN = 258;
6126
+ const IN = Math.round(Math.sqrt(src.length));
6127
+ const OUT = IN - 2;
6119
6128
  const out = new Float32Array(OUT * OUT);
6120
6129
  // Hoist division out of loop: multiplication is ~2-3x faster than division
6121
6130
  const cellSizeFactor = 1 / (8 * cellSize);
@@ -6158,8 +6167,8 @@ class KernelGenerator {
6158
6167
  * @param noDataValue Elevation value treated as noData; output is NaN for those pixels
6159
6168
  */
6160
6169
  static calculateHillshade(src, cellSize, azimuth = 315, altitude = 45, zFactor = 1, noDataValue) {
6161
- const OUT = 256;
6162
- const IN = 258;
6170
+ const IN = Math.round(Math.sqrt(src.length));
6171
+ const OUT = IN - 2;
6163
6172
  const out = new Float32Array(OUT * OUT);
6164
6173
  const zenithRad = (90 - altitude) * (Math.PI / 180);
6165
6174
  let azimuthMath = 360 - azimuth + 90;
@@ -6200,8 +6209,8 @@ class KernelGenerator {
6200
6209
  * Combines three light sources to reveal structure in shadows.
6201
6210
  */
6202
6211
  static calculateMultiHillshade(src, cellSize, zFactor = 1, noDataValue) {
6203
- const OUT = 256;
6204
- const IN = 258;
6212
+ const IN = Math.round(Math.sqrt(src.length));
6213
+ const OUT = IN - 2;
6205
6214
  const out = new Float32Array(OUT * OUT);
6206
6215
  // Hoist division out of loop: multiplication is ~2-3x faster than division
6207
6216
  const cellSizeFactor = 1 / (8 * cellSize);
@@ -6330,18 +6339,22 @@ class ReliefCompositor {
6330
6339
  }
6331
6340
 
6332
6341
  class TerrainGenerator {
6342
+ static isKernelMode(options) {
6343
+ return !!(options.useSlope || options.useHillshade || options.useSwissRelief);
6344
+ }
6333
6345
  static async generate(input, options, meshMaxError, workerPool, // TerrainWorkerPool (optional for flexibility)
6334
6346
  signal) {
6335
6347
  const { width, height } = input;
6336
- const isKernel = width === 258;
6348
+ const isKernel = TerrainGenerator.isKernelMode(options);
6349
+ const baseSize = isKernel ? width - 2 : width - 1;
6337
6350
  // 1. Compute Terrain Data (Extract Elevation)
6338
6351
  const terrain = this.computeTerrainData(input, options);
6339
- // For kernel tiles, the mesh uses the inner 257×257 sub-grid (rows 1–257, cols 1–257)
6352
+ // For kernel tiles, the mesh uses the inner sub-grid (rows 1–meshWidth, cols 1–meshWidth)
6340
6353
  // so that row 0 / col 0 (kernel padding) is dropped while the bottom/right stitching
6341
6354
  // overlap is preserved.
6342
- let meshTerrain = isKernel ? this.extractMeshRaster(terrain) : terrain;
6343
- const meshWidth = isKernel ? 257 : width;
6344
- const meshHeight = isKernel ? 257 : height;
6355
+ let meshTerrain = isKernel ? this.extractMeshRaster(terrain, width) : terrain;
6356
+ const meshWidth = isKernel ? width - 1 : width;
6357
+ const meshHeight = isKernel ? height - 1 : height;
6345
6358
  // 2. Tesselate (Generate Mesh)
6346
6359
  const { terrainSkirtHeight, verticalExaggeration = 1.0 } = options;
6347
6360
  let mesh;
@@ -6404,10 +6417,10 @@ class TerrainGenerator {
6404
6417
  indices: { value: Uint32Array.from(triangles), size: 1 },
6405
6418
  attributes,
6406
6419
  };
6407
- // For kernel tiles, raw holds the 257×257 mesh elevation (same as non-kernel).
6420
+ // For kernel tiles, raw holds the inner elevation grid (same as non-kernel).
6408
6421
  // gridWidth/gridHeight reflect the mesh dimensions.
6409
- const gridWidth = meshWidth === 257 ? 257 : meshWidth + 1;
6410
- const gridHeight = meshHeight === 257 ? 257 : meshHeight + 1;
6422
+ const gridWidth = meshWidth;
6423
+ const gridHeight = meshHeight;
6411
6424
  const tileResult = {
6412
6425
  map,
6413
6426
  raw: meshTerrain,
@@ -6417,22 +6430,22 @@ class TerrainGenerator {
6417
6430
  // 3. Kernel path: compute slope or hillshade, store as rawDerived, generate texture
6418
6431
  const shouldSkipTexture = !!options.skipTexture;
6419
6432
  if (isKernel && options.useSwissRelief) {
6420
- const cellSize = input.cellSizeMeters ?? ((input.bounds[2] - input.bounds[0]) / 256);
6433
+ const cellSize = input.cellSizeMeters ?? ((input.bounds[2] - input.bounds[0]) / baseSize);
6421
6434
  // Build a separate raster for kernel computation that preserves noData samples.
6422
6435
  const kernelTerrain = this.preserveNoDataForKernel(terrain, input.rasters[0], options.noDataValue);
6423
6436
  // Compose Swiss relief using ReliefCompositor
6424
- const swissReliefResult = ReliefCompositor.composeSwissRelief(kernelTerrain, options, cellSize, 256, 256);
6437
+ const swissReliefResult = ReliefCompositor.composeSwissRelief(kernelTerrain, options, cellSize, baseSize, baseSize);
6425
6438
  tileResult.rawDerived = swissReliefResult;
6426
6439
  if (!shouldSkipTexture && this.hasVisualizationOptions(options)) {
6427
- const cropped = this.cropRaster(meshTerrain, gridWidth, gridHeight, 256, 256);
6428
- const bitmapResult = await BitmapGenerator.generate({ width: 256, height: 256, rasters: [cropped, swissReliefResult] }, { ...options, type: 'image' });
6440
+ const cropped = this.cropRaster(meshTerrain, gridWidth, gridHeight, baseSize, baseSize);
6441
+ const bitmapResult = await BitmapGenerator.generate({ width: baseSize, height: baseSize, rasters: [cropped, swissReliefResult] }, { ...options, type: 'image' });
6429
6442
  tileResult.texture = bitmapResult.map;
6430
6443
  }
6431
6444
  }
6432
6445
  else if (isKernel && (options.useSlope || options.useHillshade)) {
6433
6446
  // Use pre-computed geographic cellSize (meters/pixel) from tile indices.
6434
6447
  // Falls back to bounds-derived estimate if not provided.
6435
- const cellSize = input.cellSizeMeters ?? ((input.bounds[2] - input.bounds[0]) / 256);
6448
+ const cellSize = input.cellSizeMeters ?? ((input.bounds[2] - input.bounds[0]) / baseSize);
6436
6449
  const zFactor = options.zFactor ?? 1;
6437
6450
  if (options.useSlope && options.useHillshade) {
6438
6451
  // eslint-disable-next-line no-console
@@ -6449,7 +6462,7 @@ class TerrainGenerator {
6449
6462
  }
6450
6463
  tileResult.rawDerived = kernelOutput;
6451
6464
  if (!shouldSkipTexture && this.hasVisualizationOptions(options)) {
6452
- const bitmapResult = await BitmapGenerator.generate({ width: 256, height: 256, rasters: [kernelOutput] }, { ...options, type: 'image' });
6465
+ const bitmapResult = await BitmapGenerator.generate({ width: baseSize, height: baseSize, rasters: [kernelOutput] }, { ...options, type: 'image' });
6453
6466
  tileResult.texture = bitmapResult.map;
6454
6467
  }
6455
6468
  }
@@ -6466,31 +6479,30 @@ class TerrainGenerator {
6466
6479
  // Determine samplesPerPixel for interleaved buffers (fallback to 1)
6467
6480
  const samplesPerPixel = Math.max(1, Math.round((srcRaster.length) / (srcWidth * srcHeight)));
6468
6481
  const channelIndex = options.useChannelIndex ?? (options.useChannel != null ? options.useChannel - 1 : 0);
6469
- const textureRaster = new Float32Array(256 * 256);
6470
- for (let ty = 0; ty < 256; ty++) {
6471
- for (let tx = 0; tx < 256; tx++) {
6472
- // Guard: if srcWidth < 256 (shouldn't happen), clamp indices
6482
+ const textureRaster = new Float32Array(baseSize * baseSize);
6483
+ for (let ty = 0; ty < baseSize; ty++) {
6484
+ for (let tx = 0; tx < baseSize; tx++) {
6485
+ // Guard: if srcWidth < baseSize (shouldn't happen), clamp indices
6473
6486
  const srcX = Math.min(tx, srcWidth - 1);
6474
6487
  const srcY = Math.min(ty, srcHeight - 1);
6475
6488
  const srcIdx = (srcY * srcWidth + srcX) * samplesPerPixel + channelIndex;
6476
6489
  const v = srcRaster[srcIdx];
6477
6490
  const isNoData = isF32NoData(v, noDataValue);
6478
- textureRaster[ty * 256 + tx] = isNoData ? noDataValue * multiplier : v * multiplier;
6491
+ textureRaster[ty * baseSize + tx] = isNoData ? noDataValue * multiplier : v * multiplier;
6479
6492
  }
6480
6493
  }
6481
6494
  const bitmapOptions = { ...options, type: 'image', useChannelIndex: 0, numOfChannels: 1, noDataValue: noDataValue !== undefined ? noDataValue * multiplier : undefined };
6482
- const bitmapResult = await BitmapGenerator.generate({ width: 256, height: 256, rasters: [textureRaster] }, bitmapOptions);
6495
+ const bitmapResult = await BitmapGenerator.generate({ width: baseSize, height: baseSize, rasters: [textureRaster] }, bitmapOptions);
6483
6496
  tileResult.texture = bitmapResult.map;
6484
6497
  }
6485
6498
  return tileResult;
6486
6499
  }
6487
- static extractMeshRaster(terrain258) {
6488
- const MESH = 257;
6489
- const IN = 258;
6490
- const out = new Float32Array(MESH * MESH);
6491
- for (let r = 0; r < MESH; r++) {
6492
- for (let c = 0; c < MESH; c++) {
6493
- out[r * MESH + c] = terrain258[(r + 1) * IN + (c + 1)];
6500
+ static extractMeshRaster(terrain, inWidth) {
6501
+ const meshWidth = inWidth - 1;
6502
+ const out = new Float32Array(meshWidth * meshWidth);
6503
+ for (let r = 0; r < meshWidth; r++) {
6504
+ for (let c = 0; c < meshWidth; c++) {
6505
+ out[r * meshWidth + c] = terrain[(r + 1) * inWidth + (c + 1)];
6494
6506
  }
6495
6507
  }
6496
6508
  return out;
@@ -6547,11 +6559,11 @@ class TerrainGenerator {
6547
6559
  const channel = isPlanar
6548
6560
  ? (rasters[optionsLocal.useChannelIndex ?? 0] ?? rasters[0])
6549
6561
  : rasters[0];
6550
- const isKernel = width === 258;
6551
- const isStitched = width === 257;
6552
- // Kernel: 258×258 flat array. Stitched: 257×257. Default: (width+1)×(height+1) with backfill.
6553
- const outWidth = isKernel ? 258 : (isStitched ? 257 : width + 1);
6554
- const outHeight = isKernel ? 258 : (isStitched ? 257 : height + 1);
6562
+ const isKernel = TerrainGenerator.isKernelMode(options);
6563
+ const isStitched = isStitchedGrid(width);
6564
+ // Kernel: flat array with kernel padding. Stitched: 2^n+1×2^n+1. Default: (width+1)×(height+1) with backfill.
6565
+ const outWidth = isKernel ? width : (isStitched ? width : width + 1);
6566
+ const outHeight = isKernel ? height : (isStitched ? height : height + 1);
6555
6567
  const terrain = new Float32Array(outWidth * outHeight);
6556
6568
  const samplesPerPixel = isPlanar ? 1 : (channel.length / (width * height));
6557
6569
  // If planar, we already selected the correct array, so start at index 0.
@@ -6588,15 +6600,15 @@ class TerrainGenerator {
6588
6600
  return terrain;
6589
6601
  }
6590
6602
  static getMartiniTileMesh(meshMaxError, width, terrain) {
6591
- const gridSize = width === 257 ? 257 : width + 1;
6603
+ const gridSize = isStitchedGrid(width) ? width : width + 1;
6592
6604
  const martini = new Martini(gridSize);
6593
6605
  const tile = martini.createTile(terrain);
6594
6606
  const { vertices, triangles } = tile.getMesh(meshMaxError);
6595
6607
  return { vertices, triangles };
6596
6608
  }
6597
6609
  static getDelatinTileMesh(meshMaxError, width, height, terrain) {
6598
- const widthPlus = width === 257 ? 257 : width + 1;
6599
- const heightPlus = height === 257 ? 257 : height + 1;
6610
+ const widthPlus = isStitchedGrid(width) ? width : width + 1;
6611
+ const heightPlus = isStitchedGrid(height) ? height : height + 1;
6600
6612
  const tin = new Delatin(terrain, widthPlus, heightPlus);
6601
6613
  tin.run(meshMaxError);
6602
6614
  // @ts-expect-error: Delatin instance properties 'coords' and 'triangles' are not explicitly typed in the library port
@@ -6605,17 +6617,18 @@ class TerrainGenerator {
6605
6617
  return { vertices, triangles };
6606
6618
  }
6607
6619
  static getMeshAttributes(vertices, terrain, width, height, bounds, verticalExaggeration = 1.0) {
6608
- const gridSize = width === 257 ? 257 : width + 1;
6620
+ const isStitchedGridFlag = isStitchedGrid(width);
6621
+ const gridSize = isStitchedGridFlag ? width : width + 1;
6609
6622
  const numOfVerticies = vertices.length / 2;
6610
6623
  // vec3. x, y in pixels, z in meters (scaled by verticalExaggeration)
6611
6624
  const positions = new Float32Array(numOfVerticies * 3);
6612
6625
  // vec2. 1 to 1 relationship with position. represents the uv on the texture image. 0,0 to 1,1.
6613
6626
  const texCoords = new Float32Array(numOfVerticies * 2);
6614
6627
  const [minX, minY, maxX, maxY] = bounds || [0, 0, width, height];
6615
- // If stitched (257), the spatial extent covers 0..256 pixels, so we divide by 256.
6616
- // If standard (256), the spatial extent covers 0..256 pixels (with backfill), so we divide by 256.
6617
- const effectiveWidth = width === 257 ? width - 1 : width;
6618
- const effectiveHeight = height === 257 ? height - 1 : height;
6628
+ // If stitched (2^n+1), the spatial extent covers 0..(width-1) pixels, so we divide by (width-1).
6629
+ // If standard (2^n), the spatial extent covers 0..width pixels (with backfill), so we divide by width.
6630
+ const effectiveWidth = isStitchedGridFlag ? width - 1 : width;
6631
+ const effectiveHeight = isStitchedGridFlag ? height - 1 : height;
6619
6632
  const xScale = (maxX - minX) / effectiveWidth;
6620
6633
  const yScale = (maxY - minY) / effectiveHeight;
6621
6634
  for (let i = 0; i < numOfVerticies; i++) {
@@ -6779,7 +6792,7 @@ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
6779
6792
  };
6780
6793
  }
6781
6794
 
6782
- var WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNsYXNzIE1hcnRpbmkgewogICAgICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgICAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgICAgICAgIGlmICh0aWxlU2l6ZSAmICh0aWxlU2l6ZSAtIDEpKSB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICAgICBgRXhwZWN0ZWQgZ3JpZCBzaXplIHRvIGJlIDJebisxLCBnb3QgJHtncmlkU2l6ZX0uYCk7CgogICAgICAgICAgICB0aGlzLm51bVRyaWFuZ2xlcyA9IHRpbGVTaXplICogdGlsZVNpemUgKiAyIC0gMjsKICAgICAgICAgICAgdGhpcy5udW1QYXJlbnRUcmlhbmdsZXMgPSB0aGlzLm51bVRyaWFuZ2xlcyAtIHRpbGVTaXplICogdGlsZVNpemU7CgogICAgICAgICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOwoKICAgICAgICAgICAgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7CgogICAgICAgICAgICAvLyBnZXQgdHJpYW5nbGUgY29vcmRpbmF0ZXMgZnJvbSBpdHMgaW5kZXggaW4gYW4gaW1wbGljaXQgYmluYXJ5IHRyZWUKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgaWQgPSBpICsgMjsKICAgICAgICAgICAgICAgIGxldCBheCA9IDAsIGF5ID0gMCwgYnggPSAwLCBieSA9IDAsIGN4ID0gMCwgY3kgPSAwOwogICAgICAgICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG15ID0gKGF5ICsgYnkpID4+IDE7CgogICAgICAgICAgICAgICAgICAgIGlmIChpZCAmIDEpIHsgLy8gbGVmdCBoYWxmCiAgICAgICAgICAgICAgICAgICAgICAgIGJ4ID0gYXg7IGJ5ID0gYXk7CiAgICAgICAgICAgICAgICAgICAgICAgIGF4ID0gY3g7IGF5ID0gY3k7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gcmlnaHQgaGFsZgogICAgICAgICAgICAgICAgICAgICAgICBheCA9IGJ4OyBheSA9IGJ5OwogICAgICAgICAgICAgICAgICAgICAgICBieCA9IGN4OyBieSA9IGN5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjeCA9IG14OyBjeSA9IG15OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDBdID0gYXg7CiAgICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICAgICAgICAgIHRoaXMuY29vcmRzW2sgKyAyXSA9IGJ4OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDNdID0gYnk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICAgICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFRpbGUgewogICAgICAgIGNvbnN0cnVjdG9yKHRlcnJhaW4sIG1hcnRpbmkpIHsKICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IG1hcnRpbmkuZ3JpZFNpemU7CiAgICAgICAgICAgIGlmICh0ZXJyYWluLmxlbmd0aCAhPT0gc2l6ZSAqIHNpemUpIHRocm93IG5ldyBFcnJvcigKICAgICAgICAgICAgICAgIGBFeHBlY3RlZCB0ZXJyYWluIGRhdGEgb2YgbGVuZ3RoICR7c2l6ZSAqIHNpemV9ICgke3NpemV9IHggJHtzaXplfSksIGdvdCAke3RlcnJhaW4ubGVuZ3RofS5gKTsKCiAgICAgICAgICAgIHRoaXMudGVycmFpbiA9IHRlcnJhaW47CiAgICAgICAgICAgIHRoaXMubWFydGluaSA9IG1hcnRpbmk7CiAgICAgICAgICAgIHRoaXMuZXJyb3JzID0gbmV3IEZsb2F0MzJBcnJheSh0ZXJyYWluLmxlbmd0aCk7CiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGUoKSB7CiAgICAgICAgICAgIGNvbnN0IHtudW1UcmlhbmdsZXMsIG51bVBhcmVudFRyaWFuZ2xlcywgY29vcmRzLCBncmlkU2l6ZTogc2l6ZX0gPSB0aGlzLm1hcnRpbmk7CiAgICAgICAgICAgIGNvbnN0IHt0ZXJyYWluLCBlcnJvcnN9ID0gdGhpczsKCiAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciBhbGwgcG9zc2libGUgdHJpYW5nbGVzLCBzdGFydGluZyBmcm9tIHRoZSBzbWFsbGVzdCBsZXZlbAogICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICAgICAgICAgIGNvbnN0IGF4ID0gY29vcmRzW2sgKyAwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ4ID0gY29vcmRzW2sgKyAyXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ5ID0gY29vcmRzW2sgKyAzXTsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgY3ggPSBteCArIG15IC0gYXk7CiAgICAgICAgICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsKCiAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQogICAgICAgICAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkSGVpZ2h0ID0gKHRlcnJhaW5bYXkgKiBzaXplICsgYXhdICsgdGVycmFpbltieSAqIHNpemUgKyBieF0pIC8gMjsKICAgICAgICAgICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgICAgICAgICBjb25zdCBtaWRkbGVFcnJvciA9IE1hdGguYWJzKGludGVycG9sYXRlZEhlaWdodCAtIHRlcnJhaW5bbWlkZGxlSW5kZXhdKTsKCiAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgbWlkZGxlRXJyb3IpOwoKICAgICAgICAgICAgICAgIGlmIChpIDwgbnVtUGFyZW50VHJpYW5nbGVzKSB7IC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRDaGlsZEluZGV4ID0gKChheSArIGN5KSA+PiAxKSAqIHNpemUgKyAoKGF4ICsgY3gpID4+IDEpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9ICgoYnkgKyBjeSkgPj4gMSkgKiBzaXplICsgKChieCArIGN4KSA+PiAxKTsKICAgICAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgZXJyb3JzW2xlZnRDaGlsZEluZGV4XSwgZXJyb3JzW3JpZ2h0Q2hpbGRJbmRleF0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBnZXRNZXNoKG1heEVycm9yID0gMCkgewogICAgICAgICAgICBjb25zdCB7Z3JpZFNpemU6IHNpemUsIGluZGljZXN9ID0gdGhpcy5tYXJ0aW5pOwogICAgICAgICAgICBjb25zdCB7ZXJyb3JzfSA9IHRoaXM7CiAgICAgICAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgICAgICAgIGxldCBudW1UcmlhbmdsZXMgPSAwOwogICAgICAgICAgICBjb25zdCBtYXggPSBzaXplIC0gMTsKCiAgICAgICAgICAgIC8vIHVzZSBhbiBpbmRleCBncmlkIHRvIGtlZXAgdHJhY2sgb2YgdmVydGljZXMgdGhhdCB3ZXJlIGFscmVhZHkgdXNlZCB0byBhdm9pZCBkdXBsaWNhdGlvbgogICAgICAgICAgICBpbmRpY2VzLmZpbGwoMCk7CgogICAgICAgICAgICAvLyByZXRyaWV2ZSBtZXNoIGluIHR3byBzdGFnZXMgdGhhdCBib3RoIHRyYXZlcnNlIHRoZSBlcnJvciBtYXA6CiAgICAgICAgICAgIC8vIC0gY291bnRFbGVtZW50czogZmluZCB1c2VkIHZlcnRpY2VzIChhbmQgYXNzaWduIGVhY2ggYW4gaW5kZXgpLCBhbmQgY291bnQgdHJpYW5nbGVzIChmb3IgbWluaW11bSBhbGxvY2F0aW9uKQogICAgICAgICAgICAvLyAtIHByb2Nlc3NUcmlhbmdsZTogZmlsbCB0aGUgYWxsb2NhdGVkIHZlcnRpY2VzICYgdHJpYW5nbGVzIHR5cGVkIGFycmF5cwoKICAgICAgICAgICAgZnVuY3Rpb24gY291bnRFbGVtZW50cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgbXkgPSAoYXkgKyBieSkgPj4gMTsKCiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KSA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgY291bnRFbGVtZW50cyhjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgICAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICAgICAgICAgICAgaW5kaWNlc1tieSAqIHNpemUgKyBieF0gPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgICAgICAgICAgICBudW1UcmlhbmdsZXMrKzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjb3VudEVsZW1lbnRzKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBjb3VudEVsZW1lbnRzKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwoKICAgICAgICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICAgICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAvLyB0cmlhbmdsZSBkb2Vzbid0IGFwcHJveGltYXRlIHRoZSBzdXJmYWNlIHdlbGwgZW5vdWdoOyBkcmlsbCBkb3duIGZ1cnRoZXIKICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwoKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgICAgICAgICAgICBjb25zdCBhID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gLSAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSAtIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKCiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGEgKyAxXSA9IGF5OwoKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CgogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjXSA9IGN4OwogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKCiAgICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgICAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBiOwogICAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CgogICAgICAgICAgICByZXR1cm4ge3ZlcnRpY2VzLCB0cmlhbmdsZXN9OwogICAgICAgIH0KICAgIH0KCiAgICAvLyBsb2FkZXJzLmdsCiAgICAvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUCiAgICAvLyBDb3B5cmlnaHQgKGMpIHZpcy5nbCBjb250cmlidXRvcnMKICAgIC8vIElTQyBMaWNlbnNlCiAgICAvLyBDb3B5cmlnaHQoYykgMjAxOSwgTWljaGFlbCBGb2dsZW1hbiwgVmxhZGltaXIgQWdhZm9ua2luCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnQgKi8KICAgIC8vIEB0cy1ub2NoZWNrCiAgICAvKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudCAqLwogICAgZnVuY3Rpb24gb3JpZW50KGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICByZXR1cm4gKGJ4IC0gY3gpICogKGF5IC0gY3kpIC0gKGJ5IC0gY3kpICogKGF4IC0gY3gpOwogICAgfQogICAgY2xhc3MgRGVsYXRpbiB7CiAgICAgICAgY29uc3RydWN0b3IoZGF0YSwgd2lkdGgsIGhlaWdodCA9IHdpZHRoKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7IC8vIGhlaWdodCBkYXRhCiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gW107IC8vIHZlcnRleCBjb29yZGluYXRlcyAoeCwgeSkKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXMgPSBbXTsgLy8gbWVzaCB0cmlhbmdsZSBpbmRpY2VzCiAgICAgICAgICAgIC8vIGFkZGl0aW9uYWwgdHJpYW5nbGUgZGF0YQogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fY2FuZGlkYXRlcyA9IFtdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcXVldWUgPSBbXTsgLy8gcXVldWUgb2YgYWRkZWQgdHJpYW5nbGVzCiAgICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IFtdOwogICAgICAgICAgICB0aGlzLl9ybXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcGVuZGluZyA9IFtdOyAvLyB0cmlhbmdsZXMgcGVuZGluZyBhZGRpdGlvbiB0byBxdWV1ZQogICAgICAgICAgICB0aGlzLl9wZW5kaW5nTGVuID0gMDsKICAgICAgICAgICAgdGhpcy5fcm1zU3VtID0gMDsKICAgICAgICAgICAgY29uc3QgeDEgPSB3aWR0aCAtIDE7CiAgICAgICAgICAgIGNvbnN0IHkxID0gaGVpZ2h0IC0gMTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLl9hZGRQb2ludCgwLCAwKTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLl9hZGRQb2ludCh4MSwgMCk7CiAgICAgICAgICAgIGNvbnN0IHAyID0gdGhpcy5fYWRkUG9pbnQoMCwgeTEpOwogICAgICAgICAgICBjb25zdCBwMyA9IHRoaXMuX2FkZFBvaW50KHgxLCB5MSk7CiAgICAgICAgICAgIC8vIGFkZCBpbml0aWFsIHR3byB0cmlhbmdsZXMKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMywgcDAsIHAyLCAtMSwgLTEsIC0xKTsKICAgICAgICAgICAgdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAzLCBwMSwgdDAsIC0xLCAtMSk7CiAgICAgICAgICAgIHRoaXMuX2ZsdXNoKCk7CiAgICAgICAgfQogICAgICAgIC8vIHJlZmluZSB0aGUgbWVzaCB1bnRpbCBpdHMgbWF4aW11bSBlcnJvciBnZXRzIGJlbG93IHRoZSBnaXZlbiBvbmUKICAgICAgICBydW4obWF4RXJyb3IgPSAxKSB7CiAgICAgICAgICAgIHdoaWxlICh0aGlzLmdldE1heEVycm9yKCkgPiBtYXhFcnJvcikgewogICAgICAgICAgICAgICAgdGhpcy5yZWZpbmUoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyByZWZpbmUgdGhlIG1lc2ggd2l0aCBhIHNpbmdsZSBwb2ludAogICAgICAgIHJlZmluZSgpIHsKICAgICAgICAgICAgdGhpcy5fc3RlcCgpOwogICAgICAgICAgICB0aGlzLl9mbHVzaCgpOwogICAgICAgIH0KICAgICAgICAvLyBtYXggZXJyb3Igb2YgdGhlIGN1cnJlbnQgbWVzaAogICAgICAgIGdldE1heEVycm9yKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzWzBdOwogICAgICAgIH0KICAgICAgICAvLyByb290LW1lYW4tc3F1YXJlIGRldmlhdGlvbiBvZiB0aGUgY3VycmVudCBtZXNoCiAgICAgICAgZ2V0Uk1TRCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Jtc1N1bSA+IDAgPyBNYXRoLnNxcnQodGhpcy5fcm1zU3VtIC8gKHRoaXMud2lkdGggKiB0aGlzLmhlaWdodCkpIDogMDsKICAgICAgICB9CiAgICAgICAgLy8gaGVpZ2h0IHZhbHVlIGF0IGEgZ2l2ZW4gcG9zaXRpb24KICAgICAgICBoZWlnaHRBdCh4LCB5KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy53aWR0aCAqIHkgKyB4XTsKICAgICAgICB9CiAgICAgICAgLy8gcmFzdGVyaXplIGFuZCBxdWV1ZSBhbGwgdHJpYW5nbGVzIHRoYXQgZ290IGFkZGVkIG9yIHVwZGF0ZWQgaW4gX3N0ZXAKICAgICAgICBfZmx1c2goKSB7CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3BlbmRpbmdMZW47IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3BlbmRpbmdbaV07CiAgICAgICAgICAgICAgICAvLyByYXN0ZXJpemUgdHJpYW5nbGUgdG8gZmluZCBtYXhpbXVtIHBpeGVsIGVycm9yCiAgICAgICAgICAgICAgICBjb25zdCBhID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMF07CiAgICAgICAgICAgICAgICBjb25zdCBiID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMV07CiAgICAgICAgICAgICAgICBjb25zdCBjID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMl07CiAgICAgICAgICAgICAgICB0aGlzLl9maW5kQ2FuZGlkYXRlKGNvb3Jkc1thXSwgY29vcmRzW2EgKyAxXSwgY29vcmRzW2JdLCBjb29yZHNbYiArIDFdLCBjb29yZHNbY10sIGNvb3Jkc1tjICsgMV0sIHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdMZW4gPSAwOwogICAgICAgIH0KICAgICAgICAvLyByYXN0ZXJpemUgYSB0cmlhbmdsZSwgZmluZCBpdHMgbWF4IGVycm9yLCBhbmQgcXVldWUgaXQgZm9yIHByb2Nlc3NpbmcKICAgICAgICBfZmluZENhbmRpZGF0ZShwMHgsIHAweSwgcDF4LCBwMXksIHAyeCwgcDJ5LCB0KSB7CiAgICAgICAgICAgIC8vIHRyaWFuZ2xlIGJvdW5kaW5nIGJveAogICAgICAgICAgICBjb25zdCBtaW5YID0gTWF0aC5taW4ocDB4LCBwMXgsIHAyeCk7CiAgICAgICAgICAgIGNvbnN0IG1pblkgPSBNYXRoLm1pbihwMHksIHAxeSwgcDJ5KTsKICAgICAgICAgICAgY29uc3QgbWF4WCA9IE1hdGgubWF4KHAweCwgcDF4LCBwMngpOwogICAgICAgICAgICBjb25zdCBtYXhZID0gTWF0aC5tYXgocDB5LCBwMXksIHAyeSk7CiAgICAgICAgICAgIC8vIGZvcndhcmQgZGlmZmVyZW5jaW5nIHZhcmlhYmxlcwogICAgICAgICAgICBsZXQgdzAwID0gb3JpZW50KHAxeCwgcDF5LCBwMngsIHAyeSwgbWluWCwgbWluWSk7CiAgICAgICAgICAgIGxldCB3MDEgPSBvcmllbnQocDJ4LCBwMnksIHAweCwgcDB5LCBtaW5YLCBtaW5ZKTsKICAgICAgICAgICAgbGV0IHcwMiA9IG9yaWVudChwMHgsIHAweSwgcDF4LCBwMXksIG1pblgsIG1pblkpOwogICAgICAgICAgICBjb25zdCBhMDEgPSBwMXkgLSBwMHk7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IHAweCAtIHAxeDsKICAgICAgICAgICAgY29uc3QgYTEyID0gcDJ5IC0gcDF5OwogICAgICAgICAgICBjb25zdCBiMTIgPSBwMXggLSBwMng7CiAgICAgICAgICAgIGNvbnN0IGEyMCA9IHAweSAtIHAyeTsKICAgICAgICAgICAgY29uc3QgYjIwID0gcDJ4IC0gcDB4OwogICAgICAgICAgICAvLyBwcmUtbXVsdGlwbGllZCB6IHZhbHVlcyBhdCB2ZXJ0aWNlcwogICAgICAgICAgICBjb25zdCBhID0gb3JpZW50KHAweCwgcDB5LCBwMXgsIHAxeSwgcDJ4LCBwMnkpOwogICAgICAgICAgICBjb25zdCB6MCA9IHRoaXMuaGVpZ2h0QXQocDB4LCBwMHkpIC8gYTsKICAgICAgICAgICAgY29uc3QgejEgPSB0aGlzLmhlaWdodEF0KHAxeCwgcDF5KSAvIGE7CiAgICAgICAgICAgIGNvbnN0IHoyID0gdGhpcy5oZWlnaHRBdChwMngsIHAyeSkgLyBhOwogICAgICAgICAgICAvLyBpdGVyYXRlIG92ZXIgcGl4ZWxzIGluIGJvdW5kaW5nIGJveAogICAgICAgICAgICBsZXQgbWF4RXJyb3IgPSAwOwogICAgICAgICAgICBsZXQgbXggPSAwOwogICAgICAgICAgICBsZXQgbXkgPSAwOwogICAgICAgICAgICBsZXQgcm1zID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgeSA9IG1pblk7IHkgPD0gbWF4WTsgeSsrKSB7CiAgICAgICAgICAgICAgICAvLyBjb21wdXRlIHN0YXJ0aW5nIG9mZnNldAogICAgICAgICAgICAgICAgbGV0IGR4ID0gMDsKICAgICAgICAgICAgICAgIGlmICh3MDAgPCAwICYmIGExMiAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgIGR4ID0gTWF0aC5tYXgoZHgsIE1hdGguZmxvb3IoLXcwMCAvIGExMikpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHcwMSA8IDAgJiYgYTIwICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgZHggPSBNYXRoLm1heChkeCwgTWF0aC5mbG9vcigtdzAxIC8gYTIwKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodzAyIDwgMCAmJiBhMDEgIT09IDApIHsKICAgICAgICAgICAgICAgICAgICBkeCA9IE1hdGgubWF4KGR4LCBNYXRoLmZsb29yKC13MDIgLyBhMDEpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxldCB3MCA9IHcwMCArIGExMiAqIGR4OwogICAgICAgICAgICAgICAgbGV0IHcxID0gdzAxICsgYTIwICogZHg7CiAgICAgICAgICAgICAgICBsZXQgdzIgPSB3MDIgKyBhMDEgKiBkeDsKICAgICAgICAgICAgICAgIGxldCB3YXNJbnNpZGUgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBtaW5YICsgZHg7IHggPD0gbWF4WDsgeCsrKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgaWYgaW5zaWRlIHRyaWFuZ2xlCiAgICAgICAgICAgICAgICAgICAgaWYgKHcwID49IDAgJiYgdzEgPj0gMCAmJiB3MiA+PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0luc2lkZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgeiB1c2luZyBiYXJ5Y2VudHJpYyBjb29yZGluYXRlcwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB6ID0gejAgKiB3MCArIHoxICogdzEgKyB6MiAqIHcyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkeiA9IE1hdGguYWJzKHogLSB0aGlzLmhlaWdodEF0KHgsIHkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcm1zICs9IGR6ICogZHo7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkeiA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhFcnJvciA9IGR6OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSB4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXkgPSB5OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHdhc0luc2lkZSkgewogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdzAgKz0gYTEyOwogICAgICAgICAgICAgICAgICAgIHcxICs9IGEyMDsKICAgICAgICAgICAgICAgICAgICB3MiArPSBhMDE7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3MDAgKz0gYjEyOwogICAgICAgICAgICAgICAgdzAxICs9IGIyMDsKICAgICAgICAgICAgICAgIHcwMiArPSBiMDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKChteCA9PT0gcDB4ICYmIG15ID09PSBwMHkpIHx8IChteCA9PT0gcDF4ICYmIG15ID09PSBwMXkpIHx8IChteCA9PT0gcDJ4ICYmIG15ID09PSBwMnkpKSB7CiAgICAgICAgICAgICAgICBtYXhFcnJvciA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gdXBkYXRlIHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHRdID0gbXg7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IG15OwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSBybXM7CiAgICAgICAgICAgIC8vIGFkZCB0cmlhbmdsZSB0byBwcmlvcml0eSBxdWV1ZQogICAgICAgICAgICB0aGlzLl9xdWV1ZVB1c2godCwgbWF4RXJyb3IsIHJtcyk7CiAgICAgICAgfQogICAgICAgIC8vIHByb2Nlc3MgdGhlIG5leHQgdHJpYW5nbGUgaW4gdGhlIHF1ZXVlLCBzcGxpdHRpbmcgaXQgd2l0aCBhIG5ldyBwb2ludAogICAgICAgIF9zdGVwKCkgewogICAgICAgICAgICAvLyBwb3AgdHJpYW5nbGUgd2l0aCBoaWdoZXN0IGVycm9yIGZyb20gcHJpb3JpdHkgcXVldWUKICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3F1ZXVlUG9wKCk7CiAgICAgICAgICAgIGNvbnN0IGUwID0gdCAqIDMgKyAwOwogICAgICAgICAgICBjb25zdCBlMSA9IHQgKiAzICsgMTsKICAgICAgICAgICAgY29uc3QgZTIgPSB0ICogMyArIDI7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbZTBdOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2UxXTsKICAgICAgICAgICAgY29uc3QgcDIgPSB0aGlzLnRyaWFuZ2xlc1tlMl07CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy5jb29yZHNbMiAqIHAwXTsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLmNvb3Jkc1syICogcDAgKyAxXTsKICAgICAgICAgICAgY29uc3QgYnggPSB0aGlzLmNvb3Jkc1syICogcDFdOwogICAgICAgICAgICBjb25zdCBieSA9IHRoaXMuY29vcmRzWzIgKiBwMSArIDFdOwogICAgICAgICAgICBjb25zdCBjeCA9IHRoaXMuY29vcmRzWzIgKiBwMl07CiAgICAgICAgICAgIGNvbnN0IGN5ID0gdGhpcy5jb29yZHNbMiAqIHAyICsgMV07CiAgICAgICAgICAgIGNvbnN0IHB4ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdF07CiAgICAgICAgICAgIGNvbnN0IHB5ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdCArIDFdOwogICAgICAgICAgICBjb25zdCBwbiA9IHRoaXMuX2FkZFBvaW50KHB4LCBweSk7CiAgICAgICAgICAgIGlmIChvcmllbnQoYXgsIGF5LCBieCwgYnksIHB4LCBweSkgPT09IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUNvbGxpbmVhcihwbiwgZTApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKG9yaWVudChieCwgYnksIGN4LCBjeSwgcHgsIHB5KSA9PT0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlQ29sbGluZWFyKHBuLCBlMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAob3JpZW50KGN4LCBjeSwgYXgsIGF5LCBweCwgcHkpID09PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVDb2xsaW5lYXIocG4sIGUyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnN0IGgwID0gdGhpcy5faGFsZmVkZ2VzW2UwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgxID0gdGhpcy5faGFsZmVkZ2VzW2UxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgyID0gdGhpcy5faGFsZmVkZ2VzW2UyXTsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAxLCBwbiwgaDAsIC0xLCAtMSwgZTApOwogICAgICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDIsIHBuLCBoMSwgLTEsIHQwICsgMSk7CiAgICAgICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAyLCBwMCwgcG4sIGgyLCB0MCArIDIsIHQxICsgMSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MCk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gYWRkIGNvb3JkaW5hdGVzIGZvciBhIG5ldyB2ZXJ0ZXgKICAgICAgICBfYWRkUG9pbnQoeCwgeSkgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5jb29yZHMubGVuZ3RoID4+IDE7CiAgICAgICAgICAgIHRoaXMuY29vcmRzLnB1c2goeCwgeSk7CiAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgIH0KICAgICAgICAvLyBhZGQgb3IgdXBkYXRlIGEgdHJpYW5nbGUgaW4gdGhlIG1lc2gKICAgICAgICBfYWRkVHJpYW5nbGUoYSwgYiwgYywgYWIsIGJjLCBjYSwgZSA9IHRoaXMudHJpYW5nbGVzLmxlbmd0aCkgewogICAgICAgICAgICBjb25zdCB0ID0gZSAvIDM7IC8vIG5ldyB0cmlhbmdsZSBpbmRleAogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdmVydGljZXMKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDBdID0gYTsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDFdID0gYjsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDJdID0gYzsKICAgICAgICAgICAgLy8gYWRkIHRyaWFuZ2xlIGhhbGZlZGdlcwogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbZSArIDBdID0gYWI7CiAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tlICsgMV0gPSBiYzsKICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2UgKyAyXSA9IGNhOwogICAgICAgICAgICAvLyBsaW5rIG5laWdoYm9yaW5nIGhhbGZlZGdlcwogICAgICAgICAgICBpZiAoYWIgPj0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2FiXSA9IGUgKyAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChiYyA+PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbYmNdID0gZSArIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNhID49IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tjYV0gPSBlICsgMjsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBpbml0IHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAwXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1t0XSA9IC0xOwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSAwOwogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdG8gcGVuZGluZyBxdWV1ZSBmb3IgbGF0ZXIgcmFzdGVyaXphdGlvbgogICAgICAgICAgICB0aGlzLl9wZW5kaW5nW3RoaXMuX3BlbmRpbmdMZW4rK10gPSB0OwogICAgICAgICAgICAvLyByZXR1cm4gZmlyc3QgaGFsZmVkZ2UgaW5kZXgKICAgICAgICAgICAgcmV0dXJuIGU7CiAgICAgICAgfQogICAgICAgIF9sZWdhbGl6ZShhKSB7CiAgICAgICAgICAgIC8vIGlmIHRoZSBwYWlyIG9mIHRyaWFuZ2xlcyBkb2Vzbid0IHNhdGlzZnkgdGhlIERlbGF1bmF5IGNvbmRpdGlvbgogICAgICAgICAgICAvLyAocDEgaXMgaW5zaWRlIHRoZSBjaXJjdW1jaXJjbGUgb2YgW3AwLCBwbCwgcHJdKSwgZmxpcCB0aGVtLAogICAgICAgICAgICAvLyB0aGVuIGRvIHRoZSBzYW1lIGNoZWNrL2ZsaXAgcmVjdXJzaXZlbHkgZm9yIHRoZSBuZXcgcGFpciBvZiB0cmlhbmdsZXMKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gICAgICAgICAgIHBsICAgICAgICAgICAgICAgICAgICBwbAogICAgICAgICAgICAvLyAgICAgICAgICAvfHxcICAgICAgICAgICAgICAgICAgLyAgXAogICAgICAgICAgICAvLyAgICAgICBhbC8gfHwgXGJsICAgICAgICAgICAgYWwvICAgIFxhCiAgICAgICAgICAgIC8vICAgICAgICAvICB8fCAgXCAgICAgICAgICAgICAgLyAgICAgIFwKICAgICAgICAgICAgLy8gICAgICAgLyAgYXx8YiAgXCAgICBmbGlwICAgIC9fX19hcl9fX1wKICAgICAgICAgICAgLy8gICAgIHAwXCAgIHx8ICAgL3AxICAgPT4gICBwMFwtLS1ibC0tLS9wMQogICAgICAgICAgICAvLyAgICAgICAgXCAgfHwgIC8gICAgICAgICAgICAgIFwgICAgICAvCiAgICAgICAgICAgIC8vICAgICAgIGFyXCB8fCAvYnIgICAgICAgICAgICAgYlwgICAgL2JyCiAgICAgICAgICAgIC8vICAgICAgICAgIFx8fC8gICAgICAgICAgICAgICAgICBcICAvCiAgICAgICAgICAgIC8vICAgICAgICAgICBwciAgICAgICAgICAgICAgICAgICAgcHIKICAgICAgICAgICAgY29uc3QgYiA9IHRoaXMuX2hhbGZlZGdlc1thXTsKICAgICAgICAgICAgaWYgKGIgPCAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYTAgPSBhIC0gKGEgJSAzKTsKICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYWwgPSBhMCArICgoYSArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFyID0gYTAgKyAoKGEgKyAyKSAlIDMpOwogICAgICAgICAgICBjb25zdCBibCA9IGIwICsgKChiICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgYnIgPSBiMCArICgoYiArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbYXJdOwogICAgICAgICAgICBjb25zdCBwciA9IHRoaXMudHJpYW5nbGVzW2FdOwogICAgICAgICAgICBjb25zdCBwbCA9IHRoaXMudHJpYW5nbGVzW2FsXTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLnRyaWFuZ2xlc1tibF07CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBpZiAoIWluQ2lyY2xlKGNvb3Jkc1syICogcDBdLCBjb29yZHNbMiAqIHAwICsgMV0sIGNvb3Jkc1syICogcHJdLCBjb29yZHNbMiAqIHByICsgMV0sIGNvb3Jkc1syICogcGxdLCBjb29yZHNbMiAqIHBsICsgMV0sIGNvb3Jkc1syICogcDFdLCBjb29yZHNbMiAqIHAxICsgMV0pKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgaGFsID0gdGhpcy5faGFsZmVkZ2VzW2FsXTsKICAgICAgICAgICAgY29uc3QgaGFyID0gdGhpcy5faGFsZmVkZ2VzW2FyXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYTAgLyAzKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcDEsIHBsLCAtMSwgaGJsLCBoYWwsIGEwKTsKICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDAsIHByLCB0MCwgaGFyLCBoYnIsIGIwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEgKyAyKTsKICAgICAgICB9CiAgICAgICAgLy8gaGFuZGxlIGEgY2FzZSB3aGVyZSBuZXcgdmVydGV4IGlzIG9uIHRoZSBlZGdlIG9mIGEgdHJpYW5nbGUKICAgICAgICBfaGFuZGxlQ29sbGluZWFyKHBuLCBhKSB7CiAgICAgICAgICAgIGNvbnN0IGEwID0gYSAtIChhICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFsID0gYTAgKyAoKGEgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBhciA9IGEwICsgKChhICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLnRyaWFuZ2xlc1thcl07CiAgICAgICAgICAgIGNvbnN0IHByID0gdGhpcy50cmlhbmdsZXNbYV07CiAgICAgICAgICAgIGNvbnN0IHBsID0gdGhpcy50cmlhbmdsZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYWwgPSB0aGlzLl9oYWxmZWRnZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYXIgPSB0aGlzLl9oYWxmZWRnZXNbYXJdOwogICAgICAgICAgICBjb25zdCBiID0gdGhpcy5faGFsZmVkZ2VzW2FdOwogICAgICAgICAgICBpZiAoYiA8IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocG4sIHAwLCBwciwgLTEsIGhhciwgLTEsIGEwKTsKICAgICAgICAgICAgICAgIGNvbnN0IHQxID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHBuLCBwbCwgdDAsIC0xLCBoYWwpOwogICAgICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQxICsgMik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYmwgPSBiMCArICgoYiArIDIpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGJyID0gYjAgKyAoKGIgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcHIsIHBuLCBoYXIsIC0xLCAtMSwgYTApOwogICAgICAgICAgICBjb25zdCB0MSA9IHRoaXMuX2FkZFRyaWFuZ2xlKHByLCBwMSwgcG4sIGhiciwgLTEsIHQwICsgMSwgYjApOwogICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAxLCBwbCwgcG4sIGhibCwgLTEsIHQxICsgMSk7CiAgICAgICAgICAgIGNvbnN0IHQzID0gdGhpcy5fYWRkVHJpYW5nbGUocGwsIHAwLCBwbiwgaGFsLCB0MCArIDIsIHQyICsgMSk7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEpOwogICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQzKTsKICAgICAgICB9CiAgICAgICAgLy8gcHJpb3JpdHkgcXVldWUgbWV0aG9kcwogICAgICAgIF9xdWV1ZVB1c2godCwgZXJyb3IsIHJtcykgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5fcXVldWUubGVuZ3RoOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSBpOwogICAgICAgICAgICB0aGlzLl9xdWV1ZS5wdXNoKHQpOwogICAgICAgICAgICB0aGlzLl9lcnJvcnMucHVzaChlcnJvcik7CiAgICAgICAgICAgIHRoaXMuX3Jtc1N1bSArPSBybXM7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcCgpIHsKICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlU3dhcCgwLCBuKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVEb3duKDAsIG4pOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcEJhY2soKSB7CiAgICAgICAgICAgIGNvbnN0IHQgPSB0aGlzLl9xdWV1ZS5wb3AoKTsKICAgICAgICAgICAgdGhpcy5fZXJyb3JzLnBvcCgpOwogICAgICAgICAgICB0aGlzLl9ybXNTdW0gLT0gdGhpcy5fcm1zW3RdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSAtMTsKICAgICAgICAgICAgcmV0dXJuIHQ7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVJlbW92ZSh0KSB7CiAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLl9xdWV1ZUluZGljZXNbdF07CiAgICAgICAgICAgIGlmIChpIDwgMCkgewogICAgICAgICAgICAgICAgY29uc3QgaXQgPSB0aGlzLl9wZW5kaW5nLmluZGV4T2YodCk7CiAgICAgICAgICAgICAgICBpZiAoaXQgIT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGVuZGluZ1tpdF0gPSB0aGlzLl9wZW5kaW5nWy0tdGhpcy5fcGVuZGluZ0xlbl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Jyb2tlbiB0cmlhbmd1bGF0aW9uIChzb21ldGhpbmcgd2VudCB3cm9uZykuJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIGlmIChuICE9PSBpKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZVN3YXAoaSwgbik7CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlRG93bihpLCBuKSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZUxlc3MoaSwgaikgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzW2ldID4gdGhpcy5fZXJyb3JzW2pdOwogICAgICAgIH0KICAgICAgICBfcXVldWVTd2FwKGksIGopIHsKICAgICAgICAgICAgY29uc3QgcGkgPSB0aGlzLl9xdWV1ZVtpXTsKICAgICAgICAgICAgY29uc3QgcGogPSB0aGlzLl9xdWV1ZVtqXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVbaV0gPSBwajsKICAgICAgICAgICAgdGhpcy5fcXVldWVbal0gPSBwaTsKICAgICAgICAgICAgdGhpcy5fcXVldWVJbmRpY2VzW3BpXSA9IGo7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1twal0gPSBpOwogICAgICAgICAgICBjb25zdCBlID0gdGhpcy5fZXJyb3JzW2ldOwogICAgICAgICAgICB0aGlzLl9lcnJvcnNbaV0gPSB0aGlzLl9lcnJvcnNbal07CiAgICAgICAgICAgIHRoaXMuX2Vycm9yc1tqXSA9IGU7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVVwKGowKSB7CiAgICAgICAgICAgIGxldCBqID0gajA7CiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpID0gKGogLSAxKSA+PiAxOwogICAgICAgICAgICAgICAgaWYgKGkgPT09IGogfHwgIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaiA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgX3F1ZXVlRG93bihpMCwgbikgewogICAgICAgICAgICBsZXQgaSA9IGkwOwogICAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICAgICAgY29uc3QgajEgPSAyICogaSArIDE7CiAgICAgICAgICAgICAgICBpZiAoajEgPj0gbiB8fCBqMSA8IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IGoyID0gajEgKyAxOwogICAgICAgICAgICAgICAgbGV0IGogPSBqMTsKICAgICAgICAgICAgICAgIGlmIChqMiA8IG4gJiYgdGhpcy5fcXVldWVMZXNzKGoyLCBqMSkpIHsKICAgICAgICAgICAgICAgICAgICBqID0gajI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaSA9IGo7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGkgPiBpMDsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbkNpcmNsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBweCwgcHkpIHsKICAgICAgICBjb25zdCBkeCA9IGF4IC0gcHg7CiAgICAgICAgY29uc3QgZHkgPSBheSAtIHB5OwogICAgICAgIGNvbnN0IGV4ID0gYnggLSBweDsKICAgICAgICBjb25zdCBleSA9IGJ5IC0gcHk7CiAgICAgICAgY29uc3QgZnggPSBjeCAtIHB4OwogICAgICAgIGNvbnN0IGZ5ID0gY3kgLSBweTsKICAgICAgICBjb25zdCBhcCA9IGR4ICogZHggKyBkeSAqIGR5OwogICAgICAgIGNvbnN0IGJwID0gZXggKiBleCArIGV5ICogZXk7CiAgICAgICAgY29uc3QgY3AgPSBmeCAqIGZ4ICsgZnkgKiBmeTsKICAgICAgICByZXR1cm4gZHggKiAoZXkgKiBjcCAtIGJwICogZnkpIC0gZHkgKiAoZXggKiBjcCAtIGJwICogZngpICsgYXAgKiAoZXggKiBmeSAtIGV5ICogZngpIDwgMDsKICAgIH0KCiAgICAvKioKICAgICAqIFdlYiBXb3JrZXIgZm9yIHRlcnJhaW4gbWVzaCB0ZXNzZWxsYXRpb24uCiAgICAgKiBSdW5zIE1hcnRpbmkvRGVsYXRpbiBhbGdvcml0aG1zIG9uIGEgYmFja2dyb3VuZCB0aHJlYWQgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIG1haW4gdGhyZWFkLgogICAgICovCiAgICAvLyBUcmFjayBhYm9ydGVkIHRhc2tzIHRvIGF2b2lkIHNlbmRpbmcgcmVzdWx0cyBmb3IgY2FuY2VsbGVkIHdvcmsKICAgIGNvbnN0IGFib3J0ZWRUYXNrcyA9IG5ldyBNYXAoKTsKICAgIHNlbGYub25tZXNzYWdlID0gKGUpID0+IHsKICAgICAgICBjb25zdCBkYXRhID0gZS5kYXRhOwogICAgICAgIGlmIChkYXRhLnR5cGUgPT09ICdhYm9ydCcpIHsKICAgICAgICAgICAgLy8gTWFyayB0YXNrIGFzIGFib3J0ZWQ7IGlmIGl0J3Mgc3RpbGwgY29tcHV0aW5nLCB3ZSdsbCBza2lwIHRoZSByZXNwb25zZQogICAgICAgICAgICBhYm9ydGVkVGFza3Muc2V0KGRhdGEudGFza0lkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBpZiAoZGF0YS50eXBlID09PSAnY29tcHV0ZU1lc2gnKSB7CiAgICAgICAgICAgIGNvbnN0IHsgdGFza0lkLCB0ZXJyYWluLCBtZXNoTWF4RXJyb3IsIHRlc3NlbGF0b3IsIHdpZHRoLCBoZWlnaHQgfSA9IGRhdGE7CiAgICAgICAgICAgIGxldCBtZXNoOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgaWYgKHRlc3NlbGF0b3IgPT09ICdkZWxhdGluJykgewogICAgICAgICAgICAgICAgICAgIC8vIERlbGF0aW4gdGVzc2VsbGF0aW9uCiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkdGhQbHVzID0gd2lkdGggPT09IDI1NyA/IDI1NyA6IHdpZHRoICsgMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHRQbHVzID0gaGVpZ2h0ID09PSAyNTcgPyAyNTcgOiBoZWlnaHQgKyAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbiA9IG5ldyBEZWxhdGluKHRlcnJhaW4sIHdpZHRoUGx1cywgaGVpZ2h0UGx1cyk7CiAgICAgICAgICAgICAgICAgICAgdGluLnJ1bihtZXNoTWF4RXJyb3IpOwogICAgICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3I6IERlbGF0aW4gaW5zdGFuY2UgcHJvcGVydGllcyAnY29vcmRzJyBhbmQgJ3RyaWFuZ2xlcycgYXJlIG5vdCBleHBsaWNpdGx5IHR5cGVkIGluIHRoZSBsaWJyYXJ5IHBvcnQKICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGNvb3JkcywgdHJpYW5nbGVzIH0gPSB0aW47CiAgICAgICAgICAgICAgICAgICAgLy8gY29vcmRzIGlzIGEgcGxhaW4gYXJyYXkg4oCUIGNvbnZlcnQgdG8gRmxvYXQ2NEFycmF5IHNvIGl0IGhhcyAuYnVmZmVyIGZvciB0cmFuc2ZlcgogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRpY2VzVHlwZWQgPSBGbG9hdDY0QXJyYXkuZnJvbShjb29yZHMpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyaWFuZ2xlc1R5cGVkID0gVWludDMyQXJyYXkuZnJvbSh0cmlhbmdsZXMpOwogICAgICAgICAgICAgICAgICAgIG1lc2ggPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzOiB2ZXJ0aWNlc1R5cGVkLAogICAgICAgICAgICAgICAgICAgICAgICB0cmlhbmdsZXM6IHRyaWFuZ2xlc1R5cGVkLAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyBNYXJ0aW5pIHRlc3NlbGxhdGlvbiAoZGVmYXVsdCkKICAgICAgICAgICAgICAgICAgICBjb25zdCBncmlkU2l6ZSA9IHdpZHRoID09PSAyNTcgPyAyNTcgOiB3aWR0aCArIDE7IC8vIE9ubHkgYWRkIDEgaWYgd2lkdGggaXMgbm90IGFscmVhZHkgMl5uKzEKICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXJ0aW5pID0gbmV3IE1hcnRpbmkoZ3JpZFNpemUpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbGUgPSBtYXJ0aW5pLmNyZWF0ZVRpbGUodGVycmFpbik7CiAgICAgICAgICAgICAgICAgICAgbWVzaCA9IHRpbGUuZ2V0TWVzaChtZXNoTWF4RXJyb3IpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gT25seSBzZW5kIHJlc3VsdCBpZiBub3QgYWJvcnRlZAogICAgICAgICAgICAgICAgaWYgKCFhYm9ydGVkVGFza3MuZ2V0KHRhc2tJZCkpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ21lc2hSZXN1bHQnLAogICAgICAgICAgICAgICAgICAgICAgICB0YXNrSWQsCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogbWVzaCwKICAgICAgICAgICAgICAgICAgICAgICAgdGVycmFpbiwgLy8g4oaQIENSSVRJQ0FMOiBSZXR1cm4gdGVycmFpbiBidWZmZXIgdG8gbWFpbiB0aHJlYWQKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIC8vIFRyYW5zZmVyIG93bmVyc2hpcCBvZiBBTEwgYnVmZmVycyBiYWNrIHRvIG1haW4gdGhyZWFkICh6ZXJvLWNvcHkgcm91bmR0cmlwKQogICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgYXZvaWRzIG1lc2hUZXJyYWluLnNsaWNlKCkgYWxsb2NhdGlvbiBvbiBtYWluIHRocmVhZAogICAgICAgICAgICAgICAgICAgIHNlbGYucG9zdE1lc3NhZ2UocmVzcG9uc2UsIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmZXI6IFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc2gudmVydGljZXMuYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzaC50cmlhbmdsZXMuYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVycmFpbi5idWZmZXIsIC8vIOKGkCBUcmFuc2ZlciB0ZXJyYWluIGJhY2sKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVwb3J0IGVycm9ycyBmb3Igbm9uLWFib3J0ZWQgdGFza3MKICAgICAgICAgICAgICAgIGlmICghYWJvcnRlZFRhc2tzLmdldCh0YXNrSWQpKSB7CiAgICAgICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdlcnJvcicsCiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2tJZCwKICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBmaW5hbGx5IHsKICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIGFib3J0IHRyYWNraW5nCiAgICAgICAgICAgICAgICBhYm9ydGVkVGFza3MuZGVsZXRlKHRhc2tJZCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9OwogICAgLy8gU2lnbmFsIHRoYXQgd29ya2VyIGlzIHJlYWR5CiAgICBzZWxmLnBvc3RNZXNzYWdlKHsgdHlwZTogJ3JlYWR5JyB9KTsKCn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPXRlcnJhaW4ud29ya2VyLmpzLm1hcAoK');
6795
+ var WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNsYXNzIE1hcnRpbmkgewogICAgICAgIGNvbnN0cnVjdG9yKGdyaWRTaXplID0gMjU3KSB7CiAgICAgICAgICAgIHRoaXMuZ3JpZFNpemUgPSBncmlkU2l6ZTsKICAgICAgICAgICAgY29uc3QgdGlsZVNpemUgPSBncmlkU2l6ZSAtIDE7CiAgICAgICAgICAgIGlmICh0aWxlU2l6ZSAmICh0aWxlU2l6ZSAtIDEpKSB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICAgICBgRXhwZWN0ZWQgZ3JpZCBzaXplIHRvIGJlIDJebisxLCBnb3QgJHtncmlkU2l6ZX0uYCk7CgogICAgICAgICAgICB0aGlzLm51bVRyaWFuZ2xlcyA9IHRpbGVTaXplICogdGlsZVNpemUgKiAyIC0gMjsKICAgICAgICAgICAgdGhpcy5udW1QYXJlbnRUcmlhbmdsZXMgPSB0aGlzLm51bVRyaWFuZ2xlcyAtIHRpbGVTaXplICogdGlsZVNpemU7CgogICAgICAgICAgICB0aGlzLmluZGljZXMgPSBuZXcgVWludDMyQXJyYXkodGhpcy5ncmlkU2l6ZSAqIHRoaXMuZ3JpZFNpemUpOwoKICAgICAgICAgICAgLy8gY29vcmRpbmF0ZXMgZm9yIGFsbCBwb3NzaWJsZSB0cmlhbmdsZXMgaW4gYW4gUlRJTiB0aWxlCiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gbmV3IFVpbnQxNkFycmF5KHRoaXMubnVtVHJpYW5nbGVzICogNCk7CgogICAgICAgICAgICAvLyBnZXQgdHJpYW5nbGUgY29vcmRpbmF0ZXMgZnJvbSBpdHMgaW5kZXggaW4gYW4gaW1wbGljaXQgYmluYXJ5IHRyZWUKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgICAgICAgICBsZXQgaWQgPSBpICsgMjsKICAgICAgICAgICAgICAgIGxldCBheCA9IDAsIGF5ID0gMCwgYnggPSAwLCBieSA9IDAsIGN4ID0gMCwgY3kgPSAwOwogICAgICAgICAgICAgICAgaWYgKGlkICYgMSkgewogICAgICAgICAgICAgICAgICAgIGJ4ID0gYnkgPSBjeCA9IHRpbGVTaXplOyAvLyBib3R0b20tbGVmdCB0cmlhbmdsZQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBheCA9IGF5ID0gY3kgPSB0aWxlU2l6ZTsgLy8gdG9wLXJpZ2h0IHRyaWFuZ2xlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAoKGlkID4+PSAxKSA+IDEpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG15ID0gKGF5ICsgYnkpID4+IDE7CgogICAgICAgICAgICAgICAgICAgIGlmIChpZCAmIDEpIHsgLy8gbGVmdCBoYWxmCiAgICAgICAgICAgICAgICAgICAgICAgIGJ4ID0gYXg7IGJ5ID0gYXk7CiAgICAgICAgICAgICAgICAgICAgICAgIGF4ID0gY3g7IGF5ID0gY3k7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gcmlnaHQgaGFsZgogICAgICAgICAgICAgICAgICAgICAgICBheCA9IGJ4OyBheSA9IGJ5OwogICAgICAgICAgICAgICAgICAgICAgICBieCA9IGN4OyBieSA9IGN5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjeCA9IG14OyBjeSA9IG15OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgayA9IGkgKiA0OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDBdID0gYXg7CiAgICAgICAgICAgICAgICB0aGlzLmNvb3Jkc1trICsgMV0gPSBheTsKICAgICAgICAgICAgICAgIHRoaXMuY29vcmRzW2sgKyAyXSA9IGJ4OwogICAgICAgICAgICAgICAgdGhpcy5jb29yZHNbayArIDNdID0gYnk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGNyZWF0ZVRpbGUodGVycmFpbikgewogICAgICAgICAgICByZXR1cm4gbmV3IFRpbGUodGVycmFpbiwgdGhpcyk7CiAgICAgICAgfQogICAgfQoKICAgIGNsYXNzIFRpbGUgewogICAgICAgIGNvbnN0cnVjdG9yKHRlcnJhaW4sIG1hcnRpbmkpIHsKICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IG1hcnRpbmkuZ3JpZFNpemU7CiAgICAgICAgICAgIGlmICh0ZXJyYWluLmxlbmd0aCAhPT0gc2l6ZSAqIHNpemUpIHRocm93IG5ldyBFcnJvcigKICAgICAgICAgICAgICAgIGBFeHBlY3RlZCB0ZXJyYWluIGRhdGEgb2YgbGVuZ3RoICR7c2l6ZSAqIHNpemV9ICgke3NpemV9IHggJHtzaXplfSksIGdvdCAke3RlcnJhaW4ubGVuZ3RofS5gKTsKCiAgICAgICAgICAgIHRoaXMudGVycmFpbiA9IHRlcnJhaW47CiAgICAgICAgICAgIHRoaXMubWFydGluaSA9IG1hcnRpbmk7CiAgICAgICAgICAgIHRoaXMuZXJyb3JzID0gbmV3IEZsb2F0MzJBcnJheSh0ZXJyYWluLmxlbmd0aCk7CiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7CiAgICAgICAgfQoKICAgICAgICB1cGRhdGUoKSB7CiAgICAgICAgICAgIGNvbnN0IHtudW1UcmlhbmdsZXMsIG51bVBhcmVudFRyaWFuZ2xlcywgY29vcmRzLCBncmlkU2l6ZTogc2l6ZX0gPSB0aGlzLm1hcnRpbmk7CiAgICAgICAgICAgIGNvbnN0IHt0ZXJyYWluLCBlcnJvcnN9ID0gdGhpczsKCiAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciBhbGwgcG9zc2libGUgdHJpYW5nbGVzLCBzdGFydGluZyBmcm9tIHRoZSBzbWFsbGVzdCBsZXZlbAogICAgICAgICAgICBmb3IgKGxldCBpID0gbnVtVHJpYW5nbGVzIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgICAgICAgIGNvbnN0IGsgPSBpICogNDsKICAgICAgICAgICAgICAgIGNvbnN0IGF4ID0gY29vcmRzW2sgKyAwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGF5ID0gY29vcmRzW2sgKyAxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ4ID0gY29vcmRzW2sgKyAyXTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ5ID0gY29vcmRzW2sgKyAzXTsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgY3ggPSBteCArIG15IC0gYXk7CiAgICAgICAgICAgICAgICBjb25zdCBjeSA9IG15ICsgYXggLSBteDsKCiAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgZXJyb3IgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbG9uZyBlZGdlIG9mIHRoZSB0cmlhbmdsZQogICAgICAgICAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkSGVpZ2h0ID0gKHRlcnJhaW5bYXkgKiBzaXplICsgYXhdICsgdGVycmFpbltieSAqIHNpemUgKyBieF0pIC8gMjsKICAgICAgICAgICAgICAgIGNvbnN0IG1pZGRsZUluZGV4ID0gbXkgKiBzaXplICsgbXg7CiAgICAgICAgICAgICAgICBjb25zdCBtaWRkbGVFcnJvciA9IE1hdGguYWJzKGludGVycG9sYXRlZEhlaWdodCAtIHRlcnJhaW5bbWlkZGxlSW5kZXhdKTsKCiAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgbWlkZGxlRXJyb3IpOwoKICAgICAgICAgICAgICAgIGlmIChpIDwgbnVtUGFyZW50VHJpYW5nbGVzKSB7IC8vIGJpZ2dlciB0cmlhbmdsZXM7IGFjY3VtdWxhdGUgZXJyb3Igd2l0aCBjaGlsZHJlbgogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRDaGlsZEluZGV4ID0gKChheSArIGN5KSA+PiAxKSAqIHNpemUgKyAoKGF4ICsgY3gpID4+IDEpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Q2hpbGRJbmRleCA9ICgoYnkgKyBjeSkgPj4gMSkgKiBzaXplICsgKChieCArIGN4KSA+PiAxKTsKICAgICAgICAgICAgICAgICAgICBlcnJvcnNbbWlkZGxlSW5kZXhdID0gTWF0aC5tYXgoZXJyb3JzW21pZGRsZUluZGV4XSwgZXJyb3JzW2xlZnRDaGlsZEluZGV4XSwgZXJyb3JzW3JpZ2h0Q2hpbGRJbmRleF0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBnZXRNZXNoKG1heEVycm9yID0gMCkgewogICAgICAgICAgICBjb25zdCB7Z3JpZFNpemU6IHNpemUsIGluZGljZXN9ID0gdGhpcy5tYXJ0aW5pOwogICAgICAgICAgICBjb25zdCB7ZXJyb3JzfSA9IHRoaXM7CiAgICAgICAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgICAgICAgIGxldCBudW1UcmlhbmdsZXMgPSAwOwogICAgICAgICAgICBjb25zdCBtYXggPSBzaXplIC0gMTsKCiAgICAgICAgICAgIC8vIHVzZSBhbiBpbmRleCBncmlkIHRvIGtlZXAgdHJhY2sgb2YgdmVydGljZXMgdGhhdCB3ZXJlIGFscmVhZHkgdXNlZCB0byBhdm9pZCBkdXBsaWNhdGlvbgogICAgICAgICAgICBpbmRpY2VzLmZpbGwoMCk7CgogICAgICAgICAgICAvLyByZXRyaWV2ZSBtZXNoIGluIHR3byBzdGFnZXMgdGhhdCBib3RoIHRyYXZlcnNlIHRoZSBlcnJvciBtYXA6CiAgICAgICAgICAgIC8vIC0gY291bnRFbGVtZW50czogZmluZCB1c2VkIHZlcnRpY2VzIChhbmQgYXNzaWduIGVhY2ggYW4gaW5kZXgpLCBhbmQgY291bnQgdHJpYW5nbGVzIChmb3IgbWluaW11bSBhbGxvY2F0aW9uKQogICAgICAgICAgICAvLyAtIHByb2Nlc3NUcmlhbmdsZTogZmlsbCB0aGUgYWxsb2NhdGVkIHZlcnRpY2VzICYgdHJpYW5nbGVzIHR5cGVkIGFycmF5cwoKICAgICAgICAgICAgZnVuY3Rpb24gY291bnRFbGVtZW50cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7CiAgICAgICAgICAgICAgICBjb25zdCBteCA9IChheCArIGJ4KSA+PiAxOwogICAgICAgICAgICAgICAgY29uc3QgbXkgPSAoYXkgKyBieSkgPj4gMTsKCiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoYXggLSBjeCkgKyBNYXRoLmFicyhheSAtIGN5KSA+IDEgJiYgZXJyb3JzW215ICogc2l6ZSArIG14XSA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgY291bnRFbGVtZW50cyhjeCwgY3ksIGF4LCBheSwgbXgsIG15KTsKICAgICAgICAgICAgICAgICAgICBjb3VudEVsZW1lbnRzKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpbmRpY2VzW2F5ICogc2l6ZSArIGF4XSA9IGluZGljZXNbYXkgKiBzaXplICsgYXhdIHx8ICsrbnVtVmVydGljZXM7CiAgICAgICAgICAgICAgICAgICAgaW5kaWNlc1tieSAqIHNpemUgKyBieF0gPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSB8fCArK251bVZlcnRpY2VzOwogICAgICAgICAgICAgICAgICAgIGluZGljZXNbY3kgKiBzaXplICsgY3hdID0gaW5kaWNlc1tjeSAqIHNpemUgKyBjeF0gfHwgKytudW1WZXJ0aWNlczsKICAgICAgICAgICAgICAgICAgICBudW1UcmlhbmdsZXMrKzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjb3VudEVsZW1lbnRzKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBjb3VudEVsZW1lbnRzKG1heCwgbWF4LCAwLCAwLCAwLCBtYXgpOwoKICAgICAgICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgVWludDE2QXJyYXkobnVtVmVydGljZXMgKiAyKTsKICAgICAgICAgICAgY29uc3QgdHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG51bVRyaWFuZ2xlcyAqIDMpOwogICAgICAgICAgICBsZXQgdHJpSW5kZXggPSAwOwoKICAgICAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc1RyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG14ID0gKGF4ICsgYngpID4+IDE7CiAgICAgICAgICAgICAgICBjb25zdCBteSA9IChheSArIGJ5KSA+PiAxOwoKICAgICAgICAgICAgICAgIGlmIChNYXRoLmFicyhheCAtIGN4KSArIE1hdGguYWJzKGF5IC0gY3kpID4gMSAmJiBlcnJvcnNbbXkgKiBzaXplICsgbXhdID4gbWF4RXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAvLyB0cmlhbmdsZSBkb2Vzbid0IGFwcHJveGltYXRlIHRoZSBzdXJmYWNlIHdlbGwgZW5vdWdoOyBkcmlsbCBkb3duIGZ1cnRoZXIKICAgICAgICAgICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUoY3gsIGN5LCBheCwgYXksIG14LCBteSk7CiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKGJ4LCBieSwgY3gsIGN5LCBteCwgbXkpOwoKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGEgdHJpYW5nbGUKICAgICAgICAgICAgICAgICAgICBjb25zdCBhID0gaW5kaWNlc1theSAqIHNpemUgKyBheF0gLSAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBpbmRpY2VzW2J5ICogc2l6ZSArIGJ4XSAtIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYyA9IGluZGljZXNbY3kgKiBzaXplICsgY3hdIC0gMTsKCiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGFdID0gYXg7CiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNbMiAqIGEgKyAxXSA9IGF5OwoKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYl0gPSBieDsKICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlc1syICogYiArIDFdID0gYnk7CgogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjXSA9IGN4OwogICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzWzIgKiBjICsgMV0gPSBjeTsKCiAgICAgICAgICAgICAgICAgICAgdHJpYW5nbGVzW3RyaUluZGV4KytdID0gYTsKICAgICAgICAgICAgICAgICAgICB0cmlhbmdsZXNbdHJpSW5kZXgrK10gPSBiOwogICAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlc1t0cmlJbmRleCsrXSA9IGM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHJvY2Vzc1RyaWFuZ2xlKDAsIDAsIG1heCwgbWF4LCBtYXgsIDApOwogICAgICAgICAgICBwcm9jZXNzVHJpYW5nbGUobWF4LCBtYXgsIDAsIDAsIDAsIG1heCk7CgogICAgICAgICAgICByZXR1cm4ge3ZlcnRpY2VzLCB0cmlhbmdsZXN9OwogICAgICAgIH0KICAgIH0KCiAgICAvLyBsb2FkZXJzLmdsCiAgICAvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUCiAgICAvLyBDb3B5cmlnaHQgKGMpIHZpcy5nbCBjb250cmlidXRvcnMKICAgIC8vIElTQyBMaWNlbnNlCiAgICAvLyBDb3B5cmlnaHQoYykgMjAxOSwgTWljaGFlbCBGb2dsZW1hbiwgVmxhZGltaXIgQWdhZm9ua2luCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnQgKi8KICAgIC8vIEB0cy1ub2NoZWNrCiAgICAvKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudCAqLwogICAgZnVuY3Rpb24gb3JpZW50KGF4LCBheSwgYngsIGJ5LCBjeCwgY3kpIHsKICAgICAgICByZXR1cm4gKGJ4IC0gY3gpICogKGF5IC0gY3kpIC0gKGJ5IC0gY3kpICogKGF4IC0gY3gpOwogICAgfQogICAgY2xhc3MgRGVsYXRpbiB7CiAgICAgICAgY29uc3RydWN0b3IoZGF0YSwgd2lkdGgsIGhlaWdodCA9IHdpZHRoKSB7CiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7IC8vIGhlaWdodCBkYXRhCiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgIHRoaXMuY29vcmRzID0gW107IC8vIHZlcnRleCBjb29yZGluYXRlcyAoeCwgeSkKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXMgPSBbXTsgLy8gbWVzaCB0cmlhbmdsZSBpbmRpY2VzCiAgICAgICAgICAgIC8vIGFkZGl0aW9uYWwgdHJpYW5nbGUgZGF0YQogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fY2FuZGlkYXRlcyA9IFtdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcXVldWUgPSBbXTsgLy8gcXVldWUgb2YgYWRkZWQgdHJpYW5nbGVzCiAgICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IFtdOwogICAgICAgICAgICB0aGlzLl9ybXMgPSBbXTsKICAgICAgICAgICAgdGhpcy5fcGVuZGluZyA9IFtdOyAvLyB0cmlhbmdsZXMgcGVuZGluZyBhZGRpdGlvbiB0byBxdWV1ZQogICAgICAgICAgICB0aGlzLl9wZW5kaW5nTGVuID0gMDsKICAgICAgICAgICAgdGhpcy5fcm1zU3VtID0gMDsKICAgICAgICAgICAgY29uc3QgeDEgPSB3aWR0aCAtIDE7CiAgICAgICAgICAgIGNvbnN0IHkxID0gaGVpZ2h0IC0gMTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLl9hZGRQb2ludCgwLCAwKTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLl9hZGRQb2ludCh4MSwgMCk7CiAgICAgICAgICAgIGNvbnN0IHAyID0gdGhpcy5fYWRkUG9pbnQoMCwgeTEpOwogICAgICAgICAgICBjb25zdCBwMyA9IHRoaXMuX2FkZFBvaW50KHgxLCB5MSk7CiAgICAgICAgICAgIC8vIGFkZCBpbml0aWFsIHR3byB0cmlhbmdsZXMKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMywgcDAsIHAyLCAtMSwgLTEsIC0xKTsKICAgICAgICAgICAgdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAzLCBwMSwgdDAsIC0xLCAtMSk7CiAgICAgICAgICAgIHRoaXMuX2ZsdXNoKCk7CiAgICAgICAgfQogICAgICAgIC8vIHJlZmluZSB0aGUgbWVzaCB1bnRpbCBpdHMgbWF4aW11bSBlcnJvciBnZXRzIGJlbG93IHRoZSBnaXZlbiBvbmUKICAgICAgICBydW4obWF4RXJyb3IgPSAxKSB7CiAgICAgICAgICAgIHdoaWxlICh0aGlzLmdldE1heEVycm9yKCkgPiBtYXhFcnJvcikgewogICAgICAgICAgICAgICAgdGhpcy5yZWZpbmUoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvLyByZWZpbmUgdGhlIG1lc2ggd2l0aCBhIHNpbmdsZSBwb2ludAogICAgICAgIHJlZmluZSgpIHsKICAgICAgICAgICAgdGhpcy5fc3RlcCgpOwogICAgICAgICAgICB0aGlzLl9mbHVzaCgpOwogICAgICAgIH0KICAgICAgICAvLyBtYXggZXJyb3Igb2YgdGhlIGN1cnJlbnQgbWVzaAogICAgICAgIGdldE1heEVycm9yKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzWzBdOwogICAgICAgIH0KICAgICAgICAvLyByb290LW1lYW4tc3F1YXJlIGRldmlhdGlvbiBvZiB0aGUgY3VycmVudCBtZXNoCiAgICAgICAgZ2V0Uk1TRCgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Jtc1N1bSA+IDAgPyBNYXRoLnNxcnQodGhpcy5fcm1zU3VtIC8gKHRoaXMud2lkdGggKiB0aGlzLmhlaWdodCkpIDogMDsKICAgICAgICB9CiAgICAgICAgLy8gaGVpZ2h0IHZhbHVlIGF0IGEgZ2l2ZW4gcG9zaXRpb24KICAgICAgICBoZWlnaHRBdCh4LCB5KSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy53aWR0aCAqIHkgKyB4XTsKICAgICAgICB9CiAgICAgICAgLy8gcmFzdGVyaXplIGFuZCBxdWV1ZSBhbGwgdHJpYW5nbGVzIHRoYXQgZ290IGFkZGVkIG9yIHVwZGF0ZWQgaW4gX3N0ZXAKICAgICAgICBfZmx1c2goKSB7CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3BlbmRpbmdMZW47IGkrKykgewogICAgICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3BlbmRpbmdbaV07CiAgICAgICAgICAgICAgICAvLyByYXN0ZXJpemUgdHJpYW5nbGUgdG8gZmluZCBtYXhpbXVtIHBpeGVsIGVycm9yCiAgICAgICAgICAgICAgICBjb25zdCBhID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMF07CiAgICAgICAgICAgICAgICBjb25zdCBiID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMV07CiAgICAgICAgICAgICAgICBjb25zdCBjID0gMiAqIHRoaXMudHJpYW5nbGVzW3QgKiAzICsgMl07CiAgICAgICAgICAgICAgICB0aGlzLl9maW5kQ2FuZGlkYXRlKGNvb3Jkc1thXSwgY29vcmRzW2EgKyAxXSwgY29vcmRzW2JdLCBjb29yZHNbYiArIDFdLCBjb29yZHNbY10sIGNvb3Jkc1tjICsgMV0sIHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdMZW4gPSAwOwogICAgICAgIH0KICAgICAgICAvLyByYXN0ZXJpemUgYSB0cmlhbmdsZSwgZmluZCBpdHMgbWF4IGVycm9yLCBhbmQgcXVldWUgaXQgZm9yIHByb2Nlc3NpbmcKICAgICAgICBfZmluZENhbmRpZGF0ZShwMHgsIHAweSwgcDF4LCBwMXksIHAyeCwgcDJ5LCB0KSB7CiAgICAgICAgICAgIC8vIHRyaWFuZ2xlIGJvdW5kaW5nIGJveAogICAgICAgICAgICBjb25zdCBtaW5YID0gTWF0aC5taW4ocDB4LCBwMXgsIHAyeCk7CiAgICAgICAgICAgIGNvbnN0IG1pblkgPSBNYXRoLm1pbihwMHksIHAxeSwgcDJ5KTsKICAgICAgICAgICAgY29uc3QgbWF4WCA9IE1hdGgubWF4KHAweCwgcDF4LCBwMngpOwogICAgICAgICAgICBjb25zdCBtYXhZID0gTWF0aC5tYXgocDB5LCBwMXksIHAyeSk7CiAgICAgICAgICAgIC8vIGZvcndhcmQgZGlmZmVyZW5jaW5nIHZhcmlhYmxlcwogICAgICAgICAgICBsZXQgdzAwID0gb3JpZW50KHAxeCwgcDF5LCBwMngsIHAyeSwgbWluWCwgbWluWSk7CiAgICAgICAgICAgIGxldCB3MDEgPSBvcmllbnQocDJ4LCBwMnksIHAweCwgcDB5LCBtaW5YLCBtaW5ZKTsKICAgICAgICAgICAgbGV0IHcwMiA9IG9yaWVudChwMHgsIHAweSwgcDF4LCBwMXksIG1pblgsIG1pblkpOwogICAgICAgICAgICBjb25zdCBhMDEgPSBwMXkgLSBwMHk7CiAgICAgICAgICAgIGNvbnN0IGIwMSA9IHAweCAtIHAxeDsKICAgICAgICAgICAgY29uc3QgYTEyID0gcDJ5IC0gcDF5OwogICAgICAgICAgICBjb25zdCBiMTIgPSBwMXggLSBwMng7CiAgICAgICAgICAgIGNvbnN0IGEyMCA9IHAweSAtIHAyeTsKICAgICAgICAgICAgY29uc3QgYjIwID0gcDJ4IC0gcDB4OwogICAgICAgICAgICAvLyBwcmUtbXVsdGlwbGllZCB6IHZhbHVlcyBhdCB2ZXJ0aWNlcwogICAgICAgICAgICBjb25zdCBhID0gb3JpZW50KHAweCwgcDB5LCBwMXgsIHAxeSwgcDJ4LCBwMnkpOwogICAgICAgICAgICBjb25zdCB6MCA9IHRoaXMuaGVpZ2h0QXQocDB4LCBwMHkpIC8gYTsKICAgICAgICAgICAgY29uc3QgejEgPSB0aGlzLmhlaWdodEF0KHAxeCwgcDF5KSAvIGE7CiAgICAgICAgICAgIGNvbnN0IHoyID0gdGhpcy5oZWlnaHRBdChwMngsIHAyeSkgLyBhOwogICAgICAgICAgICAvLyBpdGVyYXRlIG92ZXIgcGl4ZWxzIGluIGJvdW5kaW5nIGJveAogICAgICAgICAgICBsZXQgbWF4RXJyb3IgPSAwOwogICAgICAgICAgICBsZXQgbXggPSAwOwogICAgICAgICAgICBsZXQgbXkgPSAwOwogICAgICAgICAgICBsZXQgcm1zID0gMDsKICAgICAgICAgICAgZm9yIChsZXQgeSA9IG1pblk7IHkgPD0gbWF4WTsgeSsrKSB7CiAgICAgICAgICAgICAgICAvLyBjb21wdXRlIHN0YXJ0aW5nIG9mZnNldAogICAgICAgICAgICAgICAgbGV0IGR4ID0gMDsKICAgICAgICAgICAgICAgIGlmICh3MDAgPCAwICYmIGExMiAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgIGR4ID0gTWF0aC5tYXgoZHgsIE1hdGguZmxvb3IoLXcwMCAvIGExMikpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHcwMSA8IDAgJiYgYTIwICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgZHggPSBNYXRoLm1heChkeCwgTWF0aC5mbG9vcigtdzAxIC8gYTIwKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodzAyIDwgMCAmJiBhMDEgIT09IDApIHsKICAgICAgICAgICAgICAgICAgICBkeCA9IE1hdGgubWF4KGR4LCBNYXRoLmZsb29yKC13MDIgLyBhMDEpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxldCB3MCA9IHcwMCArIGExMiAqIGR4OwogICAgICAgICAgICAgICAgbGV0IHcxID0gdzAxICsgYTIwICogZHg7CiAgICAgICAgICAgICAgICBsZXQgdzIgPSB3MDIgKyBhMDEgKiBkeDsKICAgICAgICAgICAgICAgIGxldCB3YXNJbnNpZGUgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGZvciAobGV0IHggPSBtaW5YICsgZHg7IHggPD0gbWF4WDsgeCsrKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgaWYgaW5zaWRlIHRyaWFuZ2xlCiAgICAgICAgICAgICAgICAgICAgaWYgKHcwID49IDAgJiYgdzEgPj0gMCAmJiB3MiA+PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0luc2lkZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXB1dGUgeiB1c2luZyBiYXJ5Y2VudHJpYyBjb29yZGluYXRlcwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB6ID0gejAgKiB3MCArIHoxICogdzEgKyB6MiAqIHcyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkeiA9IE1hdGguYWJzKHogLSB0aGlzLmhlaWdodEF0KHgsIHkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcm1zICs9IGR6ICogZHo7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkeiA+IG1heEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhFcnJvciA9IGR6OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSB4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXkgPSB5OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHdhc0luc2lkZSkgewogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdzAgKz0gYTEyOwogICAgICAgICAgICAgICAgICAgIHcxICs9IGEyMDsKICAgICAgICAgICAgICAgICAgICB3MiArPSBhMDE7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3MDAgKz0gYjEyOwogICAgICAgICAgICAgICAgdzAxICs9IGIyMDsKICAgICAgICAgICAgICAgIHcwMiArPSBiMDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKChteCA9PT0gcDB4ICYmIG15ID09PSBwMHkpIHx8IChteCA9PT0gcDF4ICYmIG15ID09PSBwMXkpIHx8IChteCA9PT0gcDJ4ICYmIG15ID09PSBwMnkpKSB7CiAgICAgICAgICAgICAgICBtYXhFcnJvciA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gdXBkYXRlIHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHRdID0gbXg7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IG15OwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSBybXM7CiAgICAgICAgICAgIC8vIGFkZCB0cmlhbmdsZSB0byBwcmlvcml0eSBxdWV1ZQogICAgICAgICAgICB0aGlzLl9xdWV1ZVB1c2godCwgbWF4RXJyb3IsIHJtcyk7CiAgICAgICAgfQogICAgICAgIC8vIHByb2Nlc3MgdGhlIG5leHQgdHJpYW5nbGUgaW4gdGhlIHF1ZXVlLCBzcGxpdHRpbmcgaXQgd2l0aCBhIG5ldyBwb2ludAogICAgICAgIF9zdGVwKCkgewogICAgICAgICAgICAvLyBwb3AgdHJpYW5nbGUgd2l0aCBoaWdoZXN0IGVycm9yIGZyb20gcHJpb3JpdHkgcXVldWUKICAgICAgICAgICAgY29uc3QgdCA9IHRoaXMuX3F1ZXVlUG9wKCk7CiAgICAgICAgICAgIGNvbnN0IGUwID0gdCAqIDMgKyAwOwogICAgICAgICAgICBjb25zdCBlMSA9IHQgKiAzICsgMTsKICAgICAgICAgICAgY29uc3QgZTIgPSB0ICogMyArIDI7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbZTBdOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2UxXTsKICAgICAgICAgICAgY29uc3QgcDIgPSB0aGlzLnRyaWFuZ2xlc1tlMl07CiAgICAgICAgICAgIGNvbnN0IGF4ID0gdGhpcy5jb29yZHNbMiAqIHAwXTsKICAgICAgICAgICAgY29uc3QgYXkgPSB0aGlzLmNvb3Jkc1syICogcDAgKyAxXTsKICAgICAgICAgICAgY29uc3QgYnggPSB0aGlzLmNvb3Jkc1syICogcDFdOwogICAgICAgICAgICBjb25zdCBieSA9IHRoaXMuY29vcmRzWzIgKiBwMSArIDFdOwogICAgICAgICAgICBjb25zdCBjeCA9IHRoaXMuY29vcmRzWzIgKiBwMl07CiAgICAgICAgICAgIGNvbnN0IGN5ID0gdGhpcy5jb29yZHNbMiAqIHAyICsgMV07CiAgICAgICAgICAgIGNvbnN0IHB4ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdF07CiAgICAgICAgICAgIGNvbnN0IHB5ID0gdGhpcy5fY2FuZGlkYXRlc1syICogdCArIDFdOwogICAgICAgICAgICBjb25zdCBwbiA9IHRoaXMuX2FkZFBvaW50KHB4LCBweSk7CiAgICAgICAgICAgIGlmIChvcmllbnQoYXgsIGF5LCBieCwgYnksIHB4LCBweSkgPT09IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUNvbGxpbmVhcihwbiwgZTApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKG9yaWVudChieCwgYnksIGN4LCBjeSwgcHgsIHB5KSA9PT0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlQ29sbGluZWFyKHBuLCBlMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAob3JpZW50KGN4LCBjeSwgYXgsIGF5LCBweCwgcHkpID09PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVDb2xsaW5lYXIocG4sIGUyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnN0IGgwID0gdGhpcy5faGFsZmVkZ2VzW2UwXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgxID0gdGhpcy5faGFsZmVkZ2VzW2UxXTsKICAgICAgICAgICAgICAgIGNvbnN0IGgyID0gdGhpcy5faGFsZmVkZ2VzW2UyXTsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHAxLCBwbiwgaDAsIC0xLCAtMSwgZTApOwogICAgICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDIsIHBuLCBoMSwgLTEsIHQwICsgMSk7CiAgICAgICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAyLCBwMCwgcG4sIGgyLCB0MCArIDIsIHQxICsgMSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MCk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0MSk7CiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgLy8gYWRkIGNvb3JkaW5hdGVzIGZvciBhIG5ldyB2ZXJ0ZXgKICAgICAgICBfYWRkUG9pbnQoeCwgeSkgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5jb29yZHMubGVuZ3RoID4+IDE7CiAgICAgICAgICAgIHRoaXMuY29vcmRzLnB1c2goeCwgeSk7CiAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgIH0KICAgICAgICAvLyBhZGQgb3IgdXBkYXRlIGEgdHJpYW5nbGUgaW4gdGhlIG1lc2gKICAgICAgICBfYWRkVHJpYW5nbGUoYSwgYiwgYywgYWIsIGJjLCBjYSwgZSA9IHRoaXMudHJpYW5nbGVzLmxlbmd0aCkgewogICAgICAgICAgICBjb25zdCB0ID0gZSAvIDM7IC8vIG5ldyB0cmlhbmdsZSBpbmRleAogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdmVydGljZXMKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDBdID0gYTsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDFdID0gYjsKICAgICAgICAgICAgdGhpcy50cmlhbmdsZXNbZSArIDJdID0gYzsKICAgICAgICAgICAgLy8gYWRkIHRyaWFuZ2xlIGhhbGZlZGdlcwogICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbZSArIDBdID0gYWI7CiAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tlICsgMV0gPSBiYzsKICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2UgKyAyXSA9IGNhOwogICAgICAgICAgICAvLyBsaW5rIG5laWdoYm9yaW5nIGhhbGZlZGdlcwogICAgICAgICAgICBpZiAoYWIgPj0gMCkgewogICAgICAgICAgICAgICAgdGhpcy5faGFsZmVkZ2VzW2FiXSA9IGUgKyAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChiYyA+PSAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9oYWxmZWRnZXNbYmNdID0gZSArIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNhID49IDApIHsKICAgICAgICAgICAgICAgIHRoaXMuX2hhbGZlZGdlc1tjYV0gPSBlICsgMjsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBpbml0IHRyaWFuZ2xlIG1ldGFkYXRhCiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAwXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX2NhbmRpZGF0ZXNbMiAqIHQgKyAxXSA9IDA7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1t0XSA9IC0xOwogICAgICAgICAgICB0aGlzLl9ybXNbdF0gPSAwOwogICAgICAgICAgICAvLyBhZGQgdHJpYW5nbGUgdG8gcGVuZGluZyBxdWV1ZSBmb3IgbGF0ZXIgcmFzdGVyaXphdGlvbgogICAgICAgICAgICB0aGlzLl9wZW5kaW5nW3RoaXMuX3BlbmRpbmdMZW4rK10gPSB0OwogICAgICAgICAgICAvLyByZXR1cm4gZmlyc3QgaGFsZmVkZ2UgaW5kZXgKICAgICAgICAgICAgcmV0dXJuIGU7CiAgICAgICAgfQogICAgICAgIF9sZWdhbGl6ZShhKSB7CiAgICAgICAgICAgIC8vIGlmIHRoZSBwYWlyIG9mIHRyaWFuZ2xlcyBkb2Vzbid0IHNhdGlzZnkgdGhlIERlbGF1bmF5IGNvbmRpdGlvbgogICAgICAgICAgICAvLyAocDEgaXMgaW5zaWRlIHRoZSBjaXJjdW1jaXJjbGUgb2YgW3AwLCBwbCwgcHJdKSwgZmxpcCB0aGVtLAogICAgICAgICAgICAvLyB0aGVuIGRvIHRoZSBzYW1lIGNoZWNrL2ZsaXAgcmVjdXJzaXZlbHkgZm9yIHRoZSBuZXcgcGFpciBvZiB0cmlhbmdsZXMKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gICAgICAgICAgIHBsICAgICAgICAgICAgICAgICAgICBwbAogICAgICAgICAgICAvLyAgICAgICAgICAvfHxcICAgICAgICAgICAgICAgICAgLyAgXAogICAgICAgICAgICAvLyAgICAgICBhbC8gfHwgXGJsICAgICAgICAgICAgYWwvICAgIFxhCiAgICAgICAgICAgIC8vICAgICAgICAvICB8fCAgXCAgICAgICAgICAgICAgLyAgICAgIFwKICAgICAgICAgICAgLy8gICAgICAgLyAgYXx8YiAgXCAgICBmbGlwICAgIC9fX19hcl9fX1wKICAgICAgICAgICAgLy8gICAgIHAwXCAgIHx8ICAgL3AxICAgPT4gICBwMFwtLS1ibC0tLS9wMQogICAgICAgICAgICAvLyAgICAgICAgXCAgfHwgIC8gICAgICAgICAgICAgIFwgICAgICAvCiAgICAgICAgICAgIC8vICAgICAgIGFyXCB8fCAvYnIgICAgICAgICAgICAgYlwgICAgL2JyCiAgICAgICAgICAgIC8vICAgICAgICAgIFx8fC8gICAgICAgICAgICAgICAgICBcICAvCiAgICAgICAgICAgIC8vICAgICAgICAgICBwciAgICAgICAgICAgICAgICAgICAgcHIKICAgICAgICAgICAgY29uc3QgYiA9IHRoaXMuX2hhbGZlZGdlc1thXTsKICAgICAgICAgICAgaWYgKGIgPCAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYTAgPSBhIC0gKGEgJSAzKTsKICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYWwgPSBhMCArICgoYSArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFyID0gYTAgKyAoKGEgKyAyKSAlIDMpOwogICAgICAgICAgICBjb25zdCBibCA9IGIwICsgKChiICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgYnIgPSBiMCArICgoYiArIDEpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IHAwID0gdGhpcy50cmlhbmdsZXNbYXJdOwogICAgICAgICAgICBjb25zdCBwciA9IHRoaXMudHJpYW5nbGVzW2FdOwogICAgICAgICAgICBjb25zdCBwbCA9IHRoaXMudHJpYW5nbGVzW2FsXTsKICAgICAgICAgICAgY29uc3QgcDEgPSB0aGlzLnRyaWFuZ2xlc1tibF07CiAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzIH0gPSB0aGlzOwogICAgICAgICAgICBpZiAoIWluQ2lyY2xlKGNvb3Jkc1syICogcDBdLCBjb29yZHNbMiAqIHAwICsgMV0sIGNvb3Jkc1syICogcHJdLCBjb29yZHNbMiAqIHByICsgMV0sIGNvb3Jkc1syICogcGxdLCBjb29yZHNbMiAqIHBsICsgMV0sIGNvb3Jkc1syICogcDFdLCBjb29yZHNbMiAqIHAxICsgMV0pKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgaGFsID0gdGhpcy5faGFsZmVkZ2VzW2FsXTsKICAgICAgICAgICAgY29uc3QgaGFyID0gdGhpcy5faGFsZmVkZ2VzW2FyXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYTAgLyAzKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcDEsIHBsLCAtMSwgaGJsLCBoYWwsIGEwKTsKICAgICAgICAgICAgY29uc3QgdDEgPSB0aGlzLl9hZGRUcmlhbmdsZShwMSwgcDAsIHByLCB0MCwgaGFyLCBoYnIsIGIwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEgKyAyKTsKICAgICAgICB9CiAgICAgICAgLy8gaGFuZGxlIGEgY2FzZSB3aGVyZSBuZXcgdmVydGV4IGlzIG9uIHRoZSBlZGdlIG9mIGEgdHJpYW5nbGUKICAgICAgICBfaGFuZGxlQ29sbGluZWFyKHBuLCBhKSB7CiAgICAgICAgICAgIGNvbnN0IGEwID0gYSAtIChhICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGFsID0gYTAgKyAoKGEgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBhciA9IGEwICsgKChhICsgMikgJSAzKTsKICAgICAgICAgICAgY29uc3QgcDAgPSB0aGlzLnRyaWFuZ2xlc1thcl07CiAgICAgICAgICAgIGNvbnN0IHByID0gdGhpcy50cmlhbmdsZXNbYV07CiAgICAgICAgICAgIGNvbnN0IHBsID0gdGhpcy50cmlhbmdsZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYWwgPSB0aGlzLl9oYWxmZWRnZXNbYWxdOwogICAgICAgICAgICBjb25zdCBoYXIgPSB0aGlzLl9oYWxmZWRnZXNbYXJdOwogICAgICAgICAgICBjb25zdCBiID0gdGhpcy5faGFsZmVkZ2VzW2FdOwogICAgICAgICAgICBpZiAoYiA8IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IHQwID0gdGhpcy5fYWRkVHJpYW5nbGUocG4sIHAwLCBwciwgLTEsIGhhciwgLTEsIGEwKTsKICAgICAgICAgICAgICAgIGNvbnN0IHQxID0gdGhpcy5fYWRkVHJpYW5nbGUocDAsIHBuLCBwbCwgdDAsIC0xLCBoYWwpOwogICAgICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDAgKyAxKTsKICAgICAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQxICsgMik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYjAgPSBiIC0gKGIgJSAzKTsKICAgICAgICAgICAgY29uc3QgYmwgPSBiMCArICgoYiArIDIpICUgMyk7CiAgICAgICAgICAgIGNvbnN0IGJyID0gYjAgKyAoKGIgKyAxKSAlIDMpOwogICAgICAgICAgICBjb25zdCBwMSA9IHRoaXMudHJpYW5nbGVzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJsID0gdGhpcy5faGFsZmVkZ2VzW2JsXTsKICAgICAgICAgICAgY29uc3QgaGJyID0gdGhpcy5faGFsZmVkZ2VzW2JyXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVSZW1vdmUoYjAgLyAzKTsKICAgICAgICAgICAgY29uc3QgdDAgPSB0aGlzLl9hZGRUcmlhbmdsZShwMCwgcHIsIHBuLCBoYXIsIC0xLCAtMSwgYTApOwogICAgICAgICAgICBjb25zdCB0MSA9IHRoaXMuX2FkZFRyaWFuZ2xlKHByLCBwMSwgcG4sIGhiciwgLTEsIHQwICsgMSwgYjApOwogICAgICAgICAgICBjb25zdCB0MiA9IHRoaXMuX2FkZFRyaWFuZ2xlKHAxLCBwbCwgcG4sIGhibCwgLTEsIHQxICsgMSk7CiAgICAgICAgICAgIGNvbnN0IHQzID0gdGhpcy5fYWRkVHJpYW5nbGUocGwsIHAwLCBwbiwgaGFsLCB0MCArIDIsIHQyICsgMSk7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQwKTsKICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUodDEpOwogICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0Mik7CiAgICAgICAgICAgIHRoaXMuX2xlZ2FsaXplKHQzKTsKICAgICAgICB9CiAgICAgICAgLy8gcHJpb3JpdHkgcXVldWUgbWV0aG9kcwogICAgICAgIF9xdWV1ZVB1c2godCwgZXJyb3IsIHJtcykgewogICAgICAgICAgICBjb25zdCBpID0gdGhpcy5fcXVldWUubGVuZ3RoOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSBpOwogICAgICAgICAgICB0aGlzLl9xdWV1ZS5wdXNoKHQpOwogICAgICAgICAgICB0aGlzLl9lcnJvcnMucHVzaChlcnJvcik7CiAgICAgICAgICAgIHRoaXMuX3Jtc1N1bSArPSBybXM7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcCgpIHsKICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlU3dhcCgwLCBuKTsKICAgICAgICAgICAgdGhpcy5fcXVldWVEb3duKDAsIG4pOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVBvcEJhY2soKSB7CiAgICAgICAgICAgIGNvbnN0IHQgPSB0aGlzLl9xdWV1ZS5wb3AoKTsKICAgICAgICAgICAgdGhpcy5fZXJyb3JzLnBvcCgpOwogICAgICAgICAgICB0aGlzLl9ybXNTdW0gLT0gdGhpcy5fcm1zW3RdOwogICAgICAgICAgICB0aGlzLl9xdWV1ZUluZGljZXNbdF0gPSAtMTsKICAgICAgICAgICAgcmV0dXJuIHQ7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVJlbW92ZSh0KSB7CiAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLl9xdWV1ZUluZGljZXNbdF07CiAgICAgICAgICAgIGlmIChpIDwgMCkgewogICAgICAgICAgICAgICAgY29uc3QgaXQgPSB0aGlzLl9wZW5kaW5nLmluZGV4T2YodCk7CiAgICAgICAgICAgICAgICBpZiAoaXQgIT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGVuZGluZ1tpdF0gPSB0aGlzLl9wZW5kaW5nWy0tdGhpcy5fcGVuZGluZ0xlbl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Jyb2tlbiB0cmlhbmd1bGF0aW9uIChzb21ldGhpbmcgd2VudCB3cm9uZykuJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbiA9IHRoaXMuX3F1ZXVlLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIGlmIChuICE9PSBpKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZVN3YXAoaSwgbik7CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlRG93bihpLCBuKSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlVXAoaSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fcXVldWVQb3BCYWNrKCk7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZUxlc3MoaSwgaikgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZXJyb3JzW2ldID4gdGhpcy5fZXJyb3JzW2pdOwogICAgICAgIH0KICAgICAgICBfcXVldWVTd2FwKGksIGopIHsKICAgICAgICAgICAgY29uc3QgcGkgPSB0aGlzLl9xdWV1ZVtpXTsKICAgICAgICAgICAgY29uc3QgcGogPSB0aGlzLl9xdWV1ZVtqXTsKICAgICAgICAgICAgdGhpcy5fcXVldWVbaV0gPSBwajsKICAgICAgICAgICAgdGhpcy5fcXVldWVbal0gPSBwaTsKICAgICAgICAgICAgdGhpcy5fcXVldWVJbmRpY2VzW3BpXSA9IGo7CiAgICAgICAgICAgIHRoaXMuX3F1ZXVlSW5kaWNlc1twal0gPSBpOwogICAgICAgICAgICBjb25zdCBlID0gdGhpcy5fZXJyb3JzW2ldOwogICAgICAgICAgICB0aGlzLl9lcnJvcnNbaV0gPSB0aGlzLl9lcnJvcnNbal07CiAgICAgICAgICAgIHRoaXMuX2Vycm9yc1tqXSA9IGU7CiAgICAgICAgfQogICAgICAgIF9xdWV1ZVVwKGowKSB7CiAgICAgICAgICAgIGxldCBqID0gajA7CiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgICAgICBjb25zdCBpID0gKGogLSAxKSA+PiAxOwogICAgICAgICAgICAgICAgaWYgKGkgPT09IGogfHwgIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaiA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgX3F1ZXVlRG93bihpMCwgbikgewogICAgICAgICAgICBsZXQgaSA9IGkwOwogICAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICAgICAgY29uc3QgajEgPSAyICogaSArIDE7CiAgICAgICAgICAgICAgICBpZiAoajEgPj0gbiB8fCBqMSA8IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IGoyID0gajEgKyAxOwogICAgICAgICAgICAgICAgbGV0IGogPSBqMTsKICAgICAgICAgICAgICAgIGlmIChqMiA8IG4gJiYgdGhpcy5fcXVldWVMZXNzKGoyLCBqMSkpIHsKICAgICAgICAgICAgICAgICAgICBqID0gajI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3F1ZXVlTGVzcyhqLCBpKSkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdGhpcy5fcXVldWVTd2FwKGksIGopOwogICAgICAgICAgICAgICAgaSA9IGo7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGkgPiBpMDsKICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBpbkNpcmNsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBweCwgcHkpIHsKICAgICAgICBjb25zdCBkeCA9IGF4IC0gcHg7CiAgICAgICAgY29uc3QgZHkgPSBheSAtIHB5OwogICAgICAgIGNvbnN0IGV4ID0gYnggLSBweDsKICAgICAgICBjb25zdCBleSA9IGJ5IC0gcHk7CiAgICAgICAgY29uc3QgZnggPSBjeCAtIHB4OwogICAgICAgIGNvbnN0IGZ5ID0gY3kgLSBweTsKICAgICAgICBjb25zdCBhcCA9IGR4ICogZHggKyBkeSAqIGR5OwogICAgICAgIGNvbnN0IGJwID0gZXggKiBleCArIGV5ICogZXk7CiAgICAgICAgY29uc3QgY3AgPSBmeCAqIGZ4ICsgZnkgKiBmeTsKICAgICAgICByZXR1cm4gZHggKiAoZXkgKiBjcCAtIGJwICogZnkpIC0gZHkgKiAoZXggKiBjcCAtIGJwICogZngpICsgYXAgKiAoZXggKiBmeSAtIGV5ICogZngpIDwgMDsKICAgIH0KCiAgICBmdW5jdGlvbiBpc1N0aXRjaGVkR3JpZCh3aWR0aCkgewogICAgICAgIHJldHVybiB3aWR0aCA+IDEgJiYgKCh3aWR0aCAtIDEpICYgKHdpZHRoIC0gMikpID09PSAwOwogICAgfQoKICAgIC8qKgogICAgICogV2ViIFdvcmtlciBmb3IgdGVycmFpbiBtZXNoIHRlc3NlbGxhdGlvbi4KICAgICAqIFJ1bnMgTWFydGluaS9EZWxhdGluIGFsZ29yaXRobXMgb24gYSBiYWNrZ3JvdW5kIHRocmVhZCB0byBhdm9pZCBibG9ja2luZyB0aGUgbWFpbiB0aHJlYWQuCiAgICAgKi8KICAgIC8vIFRyYWNrIGFib3J0ZWQgdGFza3MgdG8gYXZvaWQgc2VuZGluZyByZXN1bHRzIGZvciBjYW5jZWxsZWQgd29yawogICAgY29uc3QgYWJvcnRlZFRhc2tzID0gbmV3IE1hcCgpOwogICAgc2VsZi5vbm1lc3NhZ2UgPSAoZSkgPT4gewogICAgICAgIGNvbnN0IGRhdGEgPSBlLmRhdGE7CiAgICAgICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Fib3J0JykgewogICAgICAgICAgICAvLyBNYXJrIHRhc2sgYXMgYWJvcnRlZDsgaWYgaXQncyBzdGlsbCBjb21wdXRpbmcsIHdlJ2xsIHNraXAgdGhlIHJlc3BvbnNlCiAgICAgICAgICAgIGFib3J0ZWRUYXNrcy5zZXQoZGF0YS50YXNrSWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGlmIChkYXRhLnR5cGUgPT09ICdjb21wdXRlTWVzaCcpIHsKICAgICAgICAgICAgY29uc3QgeyB0YXNrSWQsIHRlcnJhaW4sIG1lc2hNYXhFcnJvciwgdGVzc2VsYXRvciwgd2lkdGgsIGhlaWdodCB9ID0gZGF0YTsKICAgICAgICAgICAgbGV0IG1lc2g7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBpZiAodGVzc2VsYXRvciA9PT0gJ2RlbGF0aW4nKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gRGVsYXRpbiB0ZXNzZWxsYXRpb24KICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aFBsdXMgPSBpc1N0aXRjaGVkR3JpZCh3aWR0aCkgPyB3aWR0aCA6IHdpZHRoICsgMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHRQbHVzID0gaXNTdGl0Y2hlZEdyaWQoaGVpZ2h0KSA/IGhlaWdodCA6IGhlaWdodCArIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGluID0gbmV3IERlbGF0aW4odGVycmFpbiwgd2lkdGhQbHVzLCBoZWlnaHRQbHVzKTsKICAgICAgICAgICAgICAgICAgICB0aW4ucnVuKG1lc2hNYXhFcnJvcik7CiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvcjogRGVsYXRpbiBpbnN0YW5jZSBwcm9wZXJ0aWVzICdjb29yZHMnIGFuZCAndHJpYW5nbGVzJyBhcmUgbm90IGV4cGxpY2l0bHkgdHlwZWQgaW4gdGhlIGxpYnJhcnkgcG9ydAogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgY29vcmRzLCB0cmlhbmdsZXMgfSA9IHRpbjsKICAgICAgICAgICAgICAgICAgICAvLyBjb29yZHMgaXMgYSBwbGFpbiBhcnJheSDigJQgY29udmVydCB0byBGbG9hdDY0QXJyYXkgc28gaXQgaGFzIC5idWZmZXIgZm9yIHRyYW5zZmVyCiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmVydGljZXNUeXBlZCA9IEZsb2F0NjRBcnJheS5mcm9tKGNvb3Jkcyk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJpYW5nbGVzVHlwZWQgPSBVaW50MzJBcnJheS5mcm9tKHRyaWFuZ2xlcyk7CiAgICAgICAgICAgICAgICAgICAgbWVzaCA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgdmVydGljZXM6IHZlcnRpY2VzVHlwZWQsCiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWFuZ2xlczogdHJpYW5nbGVzVHlwZWQsCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIC8vIE1hcnRpbmkgdGVzc2VsbGF0aW9uIChkZWZhdWx0KQogICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyaWRTaXplID0gaXNTdGl0Y2hlZEdyaWQod2lkdGgpID8gd2lkdGggOiB3aWR0aCArIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFydGluaSA9IG5ldyBNYXJ0aW5pKGdyaWRTaXplKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB0aWxlID0gbWFydGluaS5jcmVhdGVUaWxlKHRlcnJhaW4pOwogICAgICAgICAgICAgICAgICAgIG1lc2ggPSB0aWxlLmdldE1lc2gobWVzaE1heEVycm9yKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIE9ubHkgc2VuZCByZXN1bHQgaWYgbm90IGFib3J0ZWQKICAgICAgICAgICAgICAgIGlmICghYWJvcnRlZFRhc2tzLmdldCh0YXNrSWQpKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdtZXNoUmVzdWx0JywKICAgICAgICAgICAgICAgICAgICAgICAgdGFza0lkLAogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQ6IG1lc2gsCiAgICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4sIC8vIOKGkCBDUklUSUNBTDogUmV0dXJuIHRlcnJhaW4gYnVmZmVyIHRvIG1haW4gdGhyZWFkCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAvLyBUcmFuc2ZlciBvd25lcnNoaXAgb2YgQUxMIGJ1ZmZlcnMgYmFjayB0byBtYWluIHRocmVhZCAoemVyby1jb3B5IHJvdW5kdHJpcCkKICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGF2b2lkcyBtZXNoVGVycmFpbi5zbGljZSgpIGFsbG9jYXRpb24gb24gbWFpbiB0aHJlYWQKICAgICAgICAgICAgICAgICAgICBzZWxmLnBvc3RNZXNzYWdlKHJlc3BvbnNlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZmVyOiBbCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNoLnZlcnRpY2VzLmJ1ZmZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc2gudHJpYW5nbGVzLmJ1ZmZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlcnJhaW4uYnVmZmVyLCAvLyDihpAgVHJhbnNmZXIgdGVycmFpbiBiYWNrCiAgICAgICAgICAgICAgICAgICAgICAgIF0sCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlcG9ydCBlcnJvcnMgZm9yIG5vbi1hYm9ydGVkIHRhc2tzCiAgICAgICAgICAgICAgICBpZiAoIWFib3J0ZWRUYXNrcy5nZXQodGFza0lkKSkgewogICAgICAgICAgICAgICAgICAgIHNlbGYucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZXJyb3InLAogICAgICAgICAgICAgICAgICAgICAgICB0YXNrSWQsCiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZmluYWxseSB7CiAgICAgICAgICAgICAgICAvLyBDbGVhbiB1cCBhYm9ydCB0cmFja2luZwogICAgICAgICAgICAgICAgYWJvcnRlZFRhc2tzLmRlbGV0ZSh0YXNrSWQpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfTsKICAgIC8vIFNpZ25hbCB0aGF0IHdvcmtlciBpcyByZWFkeQogICAgc2VsZi5wb3N0TWVzc2FnZSh7IHR5cGU6ICdyZWFkeScgfSk7Cgp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD10ZXJyYWluLndvcmtlci5qcy5tYXAKCg==');
6783
6796
  /* eslint-enable */
6784
6797
 
6785
6798
  /**
@@ -7500,6 +7513,13 @@ class CogTiles {
7500
7513
  getImageIndexForZoomLevel(zoom) {
7501
7514
  return getImageIndexForZoomLevel(zoom, this.cogZoomLookup);
7502
7515
  }
7516
+ getScaledTileSize(z) {
7517
+ const imageIndex = this.getImageIndexForZoomLevel(z);
7518
+ const imageZoom = this.cogZoomLookup[imageIndex];
7519
+ const zoomDiff = Math.max(0, z - imageZoom);
7520
+ const clampedDiff = Math.min(zoomDiff, 4);
7521
+ return this.tileSize >> clampedDiff;
7522
+ }
7503
7523
  async getTileFromImage(tileX, tileY, zoom, fetchSize, signal) {
7504
7524
  // Create a fresh local AbortController for this specific fetch.
7505
7525
  // We do NOT pass `signal` directly to readRasters because deck.gl may reuse tile
@@ -7749,7 +7769,8 @@ class CogTiles {
7749
7769
  const controller = new AbortController();
7750
7770
  const pipeline = (async () => {
7751
7771
  const isKernel = this.options.useSlope || this.options.useHillshade || this.options.useSwissRelief;
7752
- const requiredSize = this.tileSize + (isKernel ? 2 : 1);
7772
+ const scaledTileSize = this.getScaledTileSize(z);
7773
+ const requiredSize = scaledTileSize + (isKernel ? 2 : 1);
7753
7774
  const tileData = await this.getTileFromImage(x, y, z, requiredSize, controller.signal);
7754
7775
  // === Step F: detect all-noData tiles before tessellation ===
7755
7776
  const raster = tileData[0];
@@ -7901,11 +7922,12 @@ class CogTiles {
7901
7922
  async getGlazeTile(x, y, z, bounds, cellSizeMeters, meshMaxError, signal) {
7902
7923
  const maskKey = this.cache.getTileCacheKey(x, y, z);
7903
7924
  let maskPromise = this.cache.getReliefMask(maskKey);
7925
+ const scaledTileSize = this.getScaledTileSize(z);
7904
7926
  if (!maskPromise) {
7905
7927
  const controller = new AbortController();
7906
7928
  maskPromise = (async () => {
7907
- const tileData = await this.getTileFromImage(x, y, z, this.tileSize + 2, controller.signal);
7908
- return ReliefCompositor.composeSwissRelief(tileData[0], this.options, cellSizeMeters, this.tileSize, this.tileSize);
7929
+ const tileData = await this.getTileFromImage(x, y, z, scaledTileSize + 2, controller.signal);
7930
+ return ReliefCompositor.composeSwissRelief(tileData[0], this.options, cellSizeMeters, scaledTileSize, scaledTileSize);
7909
7931
  })();
7910
7932
  this.cache.setReliefMask(maskKey, maskPromise);
7911
7933
  maskPromise.catch(() => this.cache.deleteReliefMask(maskKey));
@@ -7917,8 +7939,8 @@ class CogTiles {
7917
7939
  return null;
7918
7940
  return this.geo.getMap({
7919
7941
  rasters: [reliefMask],
7920
- width: this.tileSize,
7921
- height: this.tileSize,
7942
+ width: scaledTileSize,
7943
+ height: scaledTileSize,
7922
7944
  bounds: bounds ?? [0, 0, 0, 0],
7923
7945
  cellSizeMeters,
7924
7946
  }, this.options, meshMaxError ?? 4.0, this.workerPool, signal);
@@ -7926,9 +7948,10 @@ class CogTiles {
7926
7948
  async getBitmapTile(x, y, z, bounds, cellSizeMeters, meshMaxError, signal) {
7927
7949
  const rasterKey = this.cache.getTileCacheKey(x, y, z);
7928
7950
  let rasterPromise = this.cache.getRaster(rasterKey);
7951
+ const scaledTileSize = this.getScaledTileSize(z);
7929
7952
  if (!rasterPromise) {
7930
7953
  const controller = new AbortController();
7931
- rasterPromise = this.getTileFromImage(x, y, z, this.tileSize, controller.signal);
7954
+ rasterPromise = this.getTileFromImage(x, y, z, scaledTileSize, controller.signal);
7932
7955
  this.cache.setRaster(rasterKey, rasterPromise);
7933
7956
  rasterPromise.catch(() => this.cache.deleteRaster(rasterKey));
7934
7957
  }
@@ -7939,8 +7962,8 @@ class CogTiles {
7939
7962
  return null;
7940
7963
  return this.geo.getMap({
7941
7964
  rasters: [tileData[0]],
7942
- width: this.tileSize,
7943
- height: this.tileSize,
7965
+ width: scaledTileSize,
7966
+ height: scaledTileSize,
7944
7967
  bounds: bounds ?? [0, 0, 0, 0],
7945
7968
  cellSizeMeters,
7946
7969
  }, this.options, meshMaxError ?? 4.0, this.workerPool);
@@ -8645,7 +8668,7 @@ class CogTerrainLayer extends CompositeLayer {
8645
8668
  zRange: this.state.zRange || null,
8646
8669
  tileSize,
8647
8670
  minZoom: effectiveMinZoom,
8648
- maxZoom: effectiveMaxZoom,
8671
+ maxZoom: this.props.maxZoom ?? effectiveMaxZoom,
8649
8672
  extent,
8650
8673
  maxRequests,
8651
8674
  onTileLoad: (tile) => {