From 05e47611f0e69449574cd11428c4efce498a72c8 Mon Sep 17 00:00:00 2001 From: Lembot Date: Fri, 9 Jan 2026 15:12:36 -0500 Subject: [PATCH 1/3] feat: Embedded local worker for offline/local mode (v0.3.4) Implement inline worker creation using embedded worker bundle: - Add separate webpack configs for worker and main bundles - Worker is built first, then embedded as base64 in TypeScript - WorkerWrapper creates inline worker via Blob URL when URL not provided - Version number now injected at build time from package.json This enables ai-delegate to work without requiring a separate worker file to be served, useful for offline/local development scenarios. Co-Authored-By: Claude Opus 4.5 --- example-project/public/test-inline.html | 60 +++++++++++++ package.json | 15 ++-- scripts/embed-worker.js | 104 ++++++++++++++++++++++ src/core/AiDelegate.ts | 18 +--- src/worker/WorkerWrapper.ts | 30 +++++-- src/worker/embedded-worker.ts | 53 +++++++++++ src/worker/worker.ts | 5 +- webpack.main.config.js | 111 ++++++++++++++++++++++++ webpack.worker.config.js | 38 ++++++++ 9 files changed, 409 insertions(+), 25 deletions(-) create mode 100644 example-project/public/test-inline.html create mode 100755 scripts/embed-worker.js create mode 100644 src/worker/embedded-worker.ts create mode 100644 webpack.main.config.js create mode 100644 webpack.worker.config.js diff --git a/example-project/public/test-inline.html b/example-project/public/test-inline.html new file mode 100644 index 0000000..7a29291 --- /dev/null +++ b/example-project/public/test-inline.html @@ -0,0 +1,60 @@ + + + + Inline Worker Test + + + +

AI-Delegate Inline Worker Test

+

This test verifies the inline worker works without a server.

+
+ + + + + diff --git a/package.json b/package.json index 033d592..c16c13c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@peerverity/ai-delegate", - "version": "0.3.3", + "version": "0.3.4", "description": "AI request manager with credential management and weight-based model selection", "main": "dist/ai-delegate.js", "types": "dist/index.d.ts", @@ -25,12 +25,17 @@ "dist" ], "scripts": { - "build": "webpack --mode production && npm run build:types", - "build:dev": "webpack --mode development && npm run build:types", + "build": "npm run build:worker && npm run embed-worker && npm run build:main && npm run build:types", + "build:dev": "npm run build:worker:dev && npm run embed-worker && npm run build:main:dev && npm run build:types", + "build:worker": "webpack --mode production --config webpack.worker.config.js", + "build:worker:dev": "webpack --mode development --config webpack.worker.config.js", + "build:main": "webpack --mode production --config webpack.main.config.js", + "build:main:dev": "webpack --mode development --config webpack.main.config.js", "build:types": "tsc --emitDeclarationOnly --declaration --declarationMap", + "embed-worker": "node scripts/embed-worker.js", "prepare": "npm run build", - "watch": "webpack --mode development --watch", - "clean": "rimraf dist", + "watch": "npm run build:worker:dev && npm run embed-worker && webpack --mode development --config webpack.main.config.js --watch", + "clean": "rimraf dist src/worker/embedded-worker.ts", "serve": "node scripts/serve.js", "example:install": "npm --prefix example-project install", "example:start": "npm --prefix example-project start", diff --git a/scripts/embed-worker.js b/scripts/embed-worker.js new file mode 100755 index 0000000..20bdaec --- /dev/null +++ b/scripts/embed-worker.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node +/** + * Embeds the compiled worker bundle into a TypeScript file + * that can be imported by the main bundle. + * + * This enables inline worker creation via Blob URL for offline/local mode. + * + * We use base64 encoding to safely embed the worker code without escaping issues. + */ + +const fs = require('fs'); +const path = require('path'); + +const WORKER_PATH = path.resolve(__dirname, '../dist/ai-delegate-worker.js'); +const OUTPUT_PATH = path.resolve(__dirname, '../src/worker/embedded-worker.ts'); + +function embedWorker() { + console.log('[embed-worker] Reading worker bundle...'); + + if (!fs.existsSync(WORKER_PATH)) { + console.error(`[embed-worker] ERROR: Worker bundle not found at ${WORKER_PATH}`); + console.error('[embed-worker] Run "npm run build:worker" first.'); + process.exit(1); + } + + const workerCode = fs.readFileSync(WORKER_PATH, 'utf8'); + const version = extractVersion(workerCode); + + // Base64 encode the worker code to avoid any escaping issues + const base64Code = Buffer.from(workerCode, 'utf8').toString('base64'); + + const output = `/** + * AUTO-GENERATED FILE - DO NOT EDIT + * + * This file contains the embedded worker bundle for inline worker creation. + * Generated by scripts/embed-worker.js + * + * To regenerate: npm run build:worker && npm run embed-worker + */ + +/** + * The worker source code as a base64-encoded string. + */ +const EMBEDDED_WORKER_BASE64 = '${base64Code}'; + +/** + * Decode the base64-encoded worker source. + */ +function decodeWorkerSource(): string { + // Use atob for browser environment + if (typeof atob === 'function') { + return atob(EMBEDDED_WORKER_BASE64); + } + // Fallback for Node.js environment (for testing) + return Buffer.from(EMBEDDED_WORKER_BASE64, 'base64').toString('utf8'); +} + +/** + * The worker source code as a string. + * Lazily decoded on first access. + */ +let _cachedSource: string | null = null; +export function getWorkerSource(): string { + if (_cachedSource === null) { + _cachedSource = decodeWorkerSource(); + } + return _cachedSource; +} + +/** + * Creates a Blob URL for the embedded worker. + * The URL should be revoked with URL.revokeObjectURL() when no longer needed. + */ +export function createWorkerBlobUrl(): string { + const source = getWorkerSource(); + const blob = new Blob([source], { type: 'application/javascript' }); + return URL.createObjectURL(blob); +} + +/** + * Version marker to help with debugging cache issues. + * This is extracted from the worker bundle if present. + */ +export const EMBEDDED_WORKER_VERSION: string = '${version}'; +`; + + console.log('[embed-worker] Writing embedded worker source...'); + fs.writeFileSync(OUTPUT_PATH, output, 'utf8'); + + const stats = fs.statSync(WORKER_PATH); + const base64Size = base64Code.length; + console.log(`[embed-worker] Original size: ${(stats.size / 1024).toFixed(1)}KB`); + console.log(`[embed-worker] Base64 size: ${(base64Size / 1024).toFixed(1)}KB`); + console.log(`[embed-worker] Worker version: ${version}`); + console.log(`[embed-worker] Output: ${OUTPUT_PATH}`); +} + +function extractVersion(code) { + // Try to extract version from worker code (looks for Version: X.Y.Z pattern) + const match = code.match(/Version:\s*([\d.]+)/); + return match ? match[1] : 'unknown'; +} + +embedWorker(); diff --git a/src/core/AiDelegate.ts b/src/core/AiDelegate.ts index 54891b6..77a5c64 100644 --- a/src/core/AiDelegate.ts +++ b/src/core/AiDelegate.ts @@ -123,8 +123,10 @@ export class AiDelegate { return; } - const workerUrl = this.getWorkerUrl(); - await this.worker.initialize(workerUrl, this.credentialServerUrl, this.allowLocalMode); + await this.worker.initialize( + this.credentialServerUrl, + this.allowLocalMode + ); // Set up prompt handler for worker this.setupPromptHandler(); @@ -151,18 +153,6 @@ export class AiDelegate { } } - /** - * Get the URL for the worker script based on the configured endpoint - */ - private getWorkerUrl(): string { - if (!this.endpoint) { - throw new Error('Cannot get worker URL: endpoint not configured'); - } - - // Worker is served at the endpoint path - return `${this.endpoint}/ai-delegate-worker.js`; - } - /** * Set up handler for prompt requests from worker */ diff --git a/src/worker/WorkerWrapper.ts b/src/worker/WorkerWrapper.ts index 5eb7262..9451f48 100644 --- a/src/worker/WorkerWrapper.ts +++ b/src/worker/WorkerWrapper.ts @@ -17,6 +17,7 @@ import { InitPayload } from './types'; import { MessageProtocol } from './MessageProtocol'; +import { createWorkerBlobUrl, EMBEDDED_WORKER_VERSION } from './embedded-worker'; /** * Main thread wrapper for worker communication @@ -24,6 +25,7 @@ import { MessageProtocol } from './MessageProtocol'; */ export class WorkerWrapper { private worker: Worker | null = null; + private blobUrl: string | null = null; // Track blob URL for cleanup private pendingRequests: Map void; reject: (error: Error) => void; @@ -32,22 +34,25 @@ export class WorkerWrapper { /** * Initialize the worker - * @param workerUrl - URL to the worker script * @param credentialServerUrl - Optional URL of the credential server for proxied mode * @param allowLocalMode - Whether to allow users to switch to local mode */ - async initialize(workerUrl: string, credentialServerUrl?: string, allowLocalMode?: boolean): Promise { + async initialize( + credentialServerUrl?: string, + allowLocalMode?: boolean + ): Promise { if (this.worker) { return; // Already initialized } - this.worker = new Worker(workerUrl); + // Always use inline worker via Blob URL + this.createInlineWorker(); - this.worker.addEventListener('message', (event: MessageEvent) => { + this.worker!.addEventListener('message', (event: MessageEvent) => { this.handleWorkerMessage(event.data); }); - this.worker.addEventListener('error', (event: ErrorEvent) => { + this.worker!.addEventListener('error', (event: ErrorEvent) => { console.error('[WorkerWrapper] Worker error:', event.error); // Reject all pending requests this.pendingRequests.forEach(({ reject }) => { @@ -61,6 +66,15 @@ export class WorkerWrapper { await this.sendCommand(WorkerCommand.INIT, payload); } + /** + * Create worker from embedded source using Blob URL + */ + private createInlineWorker(): void { + console.log(`[WorkerWrapper] Creating inline worker (embedded version: ${EMBEDDED_WORKER_VERSION})`); + this.blobUrl = createWorkerBlobUrl(); + this.worker = new Worker(this.blobUrl); + } + /** * Handle messages from worker */ @@ -251,6 +265,12 @@ export class WorkerWrapper { this.worker = null; } + // Revoke blob URL if we created one + if (this.blobUrl) { + URL.revokeObjectURL(this.blobUrl); + this.blobUrl = null; + } + // Reject all pending requests this.pendingRequests.forEach(({ reject }) => { reject(new Error('Worker terminated')); diff --git a/src/worker/embedded-worker.ts b/src/worker/embedded-worker.ts new file mode 100644 index 0000000..dd61196 --- /dev/null +++ b/src/worker/embedded-worker.ts @@ -0,0 +1,53 @@ +/** + * AUTO-GENERATED FILE - DO NOT EDIT + * + * This file contains the embedded worker bundle for inline worker creation. + * Generated by scripts/embed-worker.js + * + * To regenerate: npm run build:worker && npm run embed-worker + */ + +/** + * The worker source code as a base64-encoded string. + */ +const EMBEDDED_WORKER_BASE64 = 'KCgpPT57InVzZSBzdHJpY3QiO2NsYXNzIGV7Y29uc3RydWN0b3IoZSx0KXt0aGlzLnByb3ZpZGVyPWUsdGhpcy5tb2RlbE1hcHBpbmc9dHx8e319Z2V0TW9kZWwoZSl7cmV0dXJuIHRoaXMubW9kZWxNYXBwaW5nW2VdfWdldE1hcHBpbmcoKXtyZXR1cm57Li4udGhpcy5tb2RlbE1hcHBpbmd9fXNldE1vZGVsKGUsdCl7dGhpcy5tb2RlbE1hcHBpbmdbZV09dH11cGRhdGVNYXBwaW5nKGUpe3RoaXMubW9kZWxNYXBwaW5nPXsuLi50aGlzLm1vZGVsTWFwcGluZywuLi5lfX1yZXNldFRvRGVmYXVsdHMoKXt0aGlzLm1vZGVsTWFwcGluZz17fX1jbGVhcigpe3RoaXMubW9kZWxNYXBwaW5nPXt9fXZhbGlkYXRlKCl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB0aGlzLm1vZGVsTWFwcGluZy5saWdodCYmdGhpcy5tb2RlbE1hcHBpbmcubGlnaHQubGVuZ3RoPjAmJiJzdHJpbmciPT10eXBlb2YgdGhpcy5tb2RlbE1hcHBpbmcubW9kZXJhdGUmJnRoaXMubW9kZWxNYXBwaW5nLm1vZGVyYXRlLmxlbmd0aD4wJiYic3RyaW5nIj09dHlwZW9mIHRoaXMubW9kZWxNYXBwaW5nLmhlYXZ5JiZ0aGlzLm1vZGVsTWFwcGluZy5oZWF2eS5sZW5ndGg+MH1nZXRQcm92aWRlcigpe3JldHVybiB0aGlzLnByb3ZpZGVyfXNldFByb3ZpZGVyKGUpe3RoaXMucHJvdmlkZXI9ZSx0aGlzLnJlc2V0VG9EZWZhdWx0cygpfX1mdW5jdGlvbiB0KGUsdCxzLHIsbil7aWYoIm0iPT09cil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGUiKTtpZigiYSI9PT1yJiYhbil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXIiKTtpZigiZnVuY3Rpb24iPT10eXBlb2YgdD9lIT09dHx8IW46IXQuaGFzKGUpKXRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0Iik7cmV0dXJuImEiPT09cj9uLmNhbGwoZSxzKTpuP24udmFsdWU9czp0LnNldChlLHMpLHN9ZnVuY3Rpb24gcyhlLHQscyxyKXtpZigiYSI9PT1zJiYhcil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXIiKTtpZigiZnVuY3Rpb24iPT10eXBlb2YgdD9lIT09dHx8IXI6IXQuaGFzKGUpKXRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdCIpO3JldHVybiJtIj09PXM/cjoiYSI9PT1zP3IuY2FsbChlKTpyP3IudmFsdWU6dC5nZXQoZSl9bGV0IHI9ZnVuY3Rpb24oKXtjb25zdHtjcnlwdG86ZX09Z2xvYmFsVGhpcztpZihlPy5yYW5kb21VVUlEKXJldHVybiByPWUucmFuZG9tVVVJRC5iaW5kKGUpLGUucmFuZG9tVVVJRCgpO2NvbnN0IHQ9bmV3IFVpbnQ4QXJyYXkoMSkscz1lPygpPT5lLmdldFJhbmRvbVZhbHVlcyh0KVswXTooKT0+MjU1Kk1hdGgucmFuZG9tKCkmMjU1O3JldHVybiIxMDAwMDAwMC0xMDAwLTQwMDAtODAwMC0xMDAwMDAwMDAwMDAiLnJlcGxhY2UoL1swMThdL2csZT0+KCtlXnMoKSYxNT4+K2UvNCkudG9TdHJpbmcoMTYpKX07ZnVuY3Rpb24gbihlKXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIGUmJm51bGwhPT1lJiYoIm5hbWUiaW4gZSYmIkFib3J0RXJyb3IiPT09ZS5uYW1lfHwibWVzc2FnZSJpbiBlJiZTdHJpbmcoZS5tZXNzYWdlKS5pbmNsdWRlcygiRmV0Y2hSZXF1ZXN0Q2FuY2VsZWRFeGNlcHRpb24iKSl9Y29uc3QgYT1lPT57aWYoZSBpbnN0YW5jZW9mIEVycm9yKXJldHVybiBlO2lmKCJvYmplY3QiPT10eXBlb2YgZSYmbnVsbCE9PWUpe3RyeXtpZigiW29iamVjdCBFcnJvcl0iPT09T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUpKXtjb25zdCB0PW5ldyBFcnJvcihlLm1lc3NhZ2UsZS5jYXVzZT97Y2F1c2U6ZS5jYXVzZX06e30pO3JldHVybiBlLnN0YWNrJiYodC5zdGFjaz1lLnN0YWNrKSxlLmNhdXNlJiYhdC5jYXVzZSYmKHQuY2F1c2U9ZS5jYXVzZSksZS5uYW1lJiYodC5uYW1lPWUubmFtZSksdH19Y2F0Y2h7fXRyeXtyZXR1cm4gbmV3IEVycm9yKEpTT04uc3RyaW5naWZ5KGUpKX1jYXRjaHt9fXJldHVybiBuZXcgRXJyb3IoZSl9O2NsYXNzIG8gZXh0ZW5kcyBFcnJvcnt9Y2xhc3MgaSBleHRlbmRzIG97Y29uc3RydWN0b3IoZSx0LHMscil7c3VwZXIoYCR7aS5tYWtlTWVzc2FnZShlLHQscyl9YCksdGhpcy5zdGF0dXM9ZSx0aGlzLmhlYWRlcnM9cix0aGlzLnJlcXVlc3RJRD1yPy5nZXQoInJlcXVlc3QtaWQiKSx0aGlzLmVycm9yPXR9c3RhdGljIG1ha2VNZXNzYWdlKGUsdCxzKXtjb25zdCByPXQ/Lm1lc3NhZ2U/InN0cmluZyI9PXR5cGVvZiB0Lm1lc3NhZ2U/dC5tZXNzYWdlOkpTT04uc3RyaW5naWZ5KHQubWVzc2FnZSk6dD9KU09OLnN0cmluZ2lmeSh0KTpzO3JldHVybiBlJiZyP2Ake2V9ICR7cn1gOmU/YCR7ZX0gc3RhdHVzIGNvZGUgKG5vIGJvZHkpYDpyfHwiKG5vIHN0YXR1cyBjb2RlIG9yIGJvZHkpIn1zdGF0aWMgZ2VuZXJhdGUoZSx0LHMscil7aWYoIWV8fCFyKXJldHVybiBuZXcgbCh7bWVzc2FnZTpzLGNhdXNlOmEodCl9KTtjb25zdCBuPXQ7cmV0dXJuIDQwMD09PWU/bmV3IGgoZSxuLHMscik6NDAxPT09ZT9uZXcgdShlLG4scyxyKTo0MDM9PT1lP25ldyBwKGUsbixzLHIpOjQwND09PWU/bmV3IGYoZSxuLHMscik6NDA5PT09ZT9uZXcgbShlLG4scyxyKTo0MjI9PT1lP25ldyBnKGUsbixzLHIpOjQyOT09PWU/bmV3IHcoZSxuLHMscik6ZT49NTAwP25ldyB5KGUsbixzLHIpOm5ldyBpKGUsbixzLHIpfX1jbGFzcyBjIGV4dGVuZHMgaXtjb25zdHJ1Y3Rvcih7bWVzc2FnZTplfT17fSl7c3VwZXIodm9pZCAwLHZvaWQgMCxlfHwiUmVxdWVzdCB3YXMgYWJvcnRlZC4iLHZvaWQgMCl9fWNsYXNzIGwgZXh0ZW5kcyBpe2NvbnN0cnVjdG9yKHttZXNzYWdlOmUsY2F1c2U6dH0pe3N1cGVyKHZvaWQgMCx2b2lkIDAsZXx8IkNvbm5lY3Rpb24gZXJyb3IuIix2b2lkIDApLHQmJih0aGlzLmNhdXNlPXQpfX1jbGFzcyBkIGV4dGVuZHMgbHtjb25zdHJ1Y3Rvcih7bWVzc2FnZTplfT17fSl7c3VwZXIoe21lc3NhZ2U6ZT8/IlJlcXVlc3QgdGltZWQgb3V0LiJ9KX19Y2xhc3MgaCBleHRlbmRzIGl7fWNsYXNzIHUgZXh0ZW5kcyBpe31jbGFzcyBwIGV4dGVuZHMgaXt9Y2xhc3MgZiBleHRlbmRzIGl7fWNsYXNzIG0gZXh0ZW5kcyBpe31jbGFzcyBnIGV4dGVuZHMgaXt9Y2xhc3MgdyBleHRlbmRzIGl7fWNsYXNzIHkgZXh0ZW5kcyBpe31jb25zdCBiPS9eW2Etel1bYS16MC05Ky4tXSo6L2k7bGV0IHY9ZT0+KHY9QXJyYXkuaXNBcnJheSx2KGUpKSxfPXY7ZnVuY3Rpb24gayhlKXtyZXR1cm4ib2JqZWN0IiE9dHlwZW9mIGU/e306ZT8/e319Y29uc3QgUz1lPT57dHJ5e3JldHVybiBKU09OLnBhcnNlKGUpfWNhdGNoKGUpe3JldHVybn19LE09IjAuNzEuMCIsUD0oKT0+e2NvbnN0IGU9InVuZGVmaW5lZCIhPXR5cGVvZiBEZW5vJiZudWxsIT1EZW5vLmJ1aWxkPyJkZW5vIjoidW5kZWZpbmVkIiE9dHlwZW9mIEVkZ2VSdW50aW1lPyJlZGdlIjoiW29iamVjdCBwcm9jZXNzXSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodm9pZCAwIT09Z2xvYmFsVGhpcy5wcm9jZXNzP2dsb2JhbFRoaXMucHJvY2VzczowKT8ibm9kZSI6InVua25vd24iO2lmKCJkZW5vIj09PWUpcmV0dXJueyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjpSKERlbm8uYnVpbGQub3MpLCJYLVN0YWlubGVzcy1BcmNoIjpFKERlbm8uYnVpbGQuYXJjaCksIlgtU3RhaW5sZXNzLVJ1bnRpbWUiOiJkZW5vIiwiWC1TdGFpbmxlc3MtUnVudGltZS1WZXJzaW9uIjoic3RyaW5nIj09dHlwZW9mIERlbm8udmVyc2lvbj9EZW5vLnZlcnNpb246RGVuby52ZXJzaW9uPy5kZW5vPz8idW5rbm93biJ9O2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgRWRnZVJ1bnRpbWUpcmV0dXJueyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjoiVW5rbm93biIsIlgtU3RhaW5sZXNzLUFyY2giOmBvdGhlcjoke0VkZ2VSdW50aW1lfWAsIlgtU3RhaW5sZXNzLVJ1bnRpbWUiOiJlZGdlIiwiWC1TdGFpbmxlc3MtUnVudGltZS1WZXJzaW9uIjpnbG9iYWxUaGlzLnByb2Nlc3MudmVyc2lvbn07aWYoIm5vZGUiPT09ZSlyZXR1cm57IlgtU3RhaW5sZXNzLUxhbmciOiJqcyIsIlgtU3RhaW5sZXNzLVBhY2thZ2UtVmVyc2lvbiI6TSwiWC1TdGFpbmxlc3MtT1MiOlIoZ2xvYmFsVGhpcy5wcm9jZXNzLnBsYXRmb3JtPz8idW5rbm93biIpLCJYLVN0YWlubGVzcy1BcmNoIjpFKGdsb2JhbFRoaXMucHJvY2Vzcy5hcmNoPz8idW5rbm93biIpLCJYLVN0YWlubGVzcy1SdW50aW1lIjoibm9kZSIsIlgtU3RhaW5sZXNzLVJ1bnRpbWUtVmVyc2lvbiI6Z2xvYmFsVGhpcy5wcm9jZXNzLnZlcnNpb24/PyJ1bmtub3duIn07Y29uc3QgdD1mdW5jdGlvbigpe2lmKCJ1bmRlZmluZWQiPT10eXBlb2YgbmF2aWdhdG9yfHwhbmF2aWdhdG9yKXJldHVybiBudWxsO2NvbnN0IGU9W3trZXk6ImVkZ2UiLHBhdHRlcm46L0VkZ2UoPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6ImllIixwYXR0ZXJuOi9NU0lFKD86XFcrKFxkKylcLihcZCspKD86XC4oXGQrKSk/KT8vfSx7a2V5OiJpZSIscGF0dGVybjovVHJpZGVudCg/Oi4qcnZcOihcZCspXC4oXGQrKSg/OlwuKFxkKykpPyk/L30se2tleToiY2hyb21lIixwYXR0ZXJuOi9DaHJvbWUoPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6ImZpcmVmb3giLHBhdHRlcm46L0ZpcmVmb3goPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6InNhZmFyaSIscGF0dGVybjovKD86VmVyc2lvblxXKyhcZCspXC4oXGQrKSg/OlwuKFxkKykpPyk/KD86XFcrTW9iaWxlXFMqKT9cVytTYWZhcmkvfV07Zm9yKGNvbnN0e2tleTp0LHBhdHRlcm46c31vZiBlKXtjb25zdCBlPXMuZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KTtpZihlKXJldHVybnticm93c2VyOnQsdmVyc2lvbjpgJHtlWzFdfHwwfS4ke2VbMl18fDB9LiR7ZVszXXx8MH1gfX1yZXR1cm4gbnVsbH0oKTtyZXR1cm4gdD97IlgtU3RhaW5sZXNzLUxhbmciOiJqcyIsIlgtU3RhaW5sZXNzLVBhY2thZ2UtVmVyc2lvbiI6TSwiWC1TdGFpbmxlc3MtT1MiOiJVbmtub3duIiwiWC1TdGFpbmxlc3MtQXJjaCI6InVua25vd24iLCJYLVN0YWlubGVzcy1SdW50aW1lIjpgYnJvd3Nlcjoke3QuYnJvd3Nlcn1gLCJYLVN0YWlubGVzcy1SdW50aW1lLVZlcnNpb24iOnQudmVyc2lvbn06eyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjoiVW5rbm93biIsIlgtU3RhaW5sZXNzLUFyY2giOiJ1bmtub3duIiwiWC1TdGFpbmxlc3MtUnVudGltZSI6InVua25vd24iLCJYLVN0YWlubGVzcy1SdW50aW1lLVZlcnNpb24iOiJ1bmtub3duIn19LEU9ZT0+IngzMiI9PT1lPyJ4MzIiOiJ4ODZfNjQiPT09ZXx8Ing2NCI9PT1lPyJ4NjQiOiJhcm0iPT09ZT8iYXJtIjoiYWFyY2g2NCI9PT1lfHwiYXJtNjQiPT09ZT8iYXJtNjQiOmU/YG90aGVyOiR7ZX1gOiJ1bmtub3duIixSPWU9PihlPWUudG9Mb3dlckNhc2UoKSkuaW5jbHVkZXMoImlvcyIpPyJpT1MiOiJhbmRyb2lkIj09PWU/IkFuZHJvaWQiOiJkYXJ3aW4iPT09ZT8iTWFjT1MiOiJ3aW4zMiI9PT1lPyJXaW5kb3dzIjoiZnJlZWJzZCI9PT1lPyJGcmVlQlNEIjoib3BlbmJzZCI9PT1lPyJPcGVuQlNEIjoibGludXgiPT09ZT8iTGludXgiOmU/YE90aGVyOiR7ZX1gOiJVbmtub3duIjtsZXQgeDtmdW5jdGlvbiBUKC4uLmUpe2NvbnN0IHQ9Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTtpZih2b2lkIDA9PT10KXRocm93IG5ldyBFcnJvcigiYFJlYWRhYmxlU3RyZWFtYCBpcyBub3QgZGVmaW5lZCBhcyBhIGdsb2JhbDsgWW91IHdpbGwgbmVlZCB0byBwb2x5ZmlsbCBpdCwgYGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0gPSBSZWFkYWJsZVN0cmVhbWAiKTtyZXR1cm4gbmV3IHQoLi4uZSl9ZnVuY3Rpb24gQShlKXtsZXQgdD1TeW1ib2wuYXN5bmNJdGVyYXRvciBpbiBlP2VbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk6ZVtTeW1ib2wuaXRlcmF0b3JdKCk7cmV0dXJuIFQoe3N0YXJ0KCl7fSxhc3luYyBwdWxsKGUpe2NvbnN0e2RvbmU6cyx2YWx1ZTpyfT1hd2FpdCB0Lm5leHQoKTtzP2UuY2xvc2UoKTplLmVucXVldWUocil9LGFzeW5jIGNhbmNlbCgpe2F3YWl0KHQucmV0dXJuPy4oKSl9fSl9ZnVuY3Rpb24gQyhlKXtpZihlW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSlyZXR1cm4gZTtjb25zdCB0PWUuZ2V0UmVhZGVyKCk7cmV0dXJue2FzeW5jIG5leHQoKXt0cnl7Y29uc3QgZT1hd2FpdCB0LnJlYWQoKTtyZXR1cm4gZT8uZG9uZSYmdC5yZWxlYXNlTG9jaygpLGV9Y2F0Y2goZSl7dGhyb3cgdC5yZWxlYXNlTG9jaygpLGV9fSxhc3luYyByZXR1cm4oKXtjb25zdCBlPXQuY2FuY2VsKCk7cmV0dXJuIHQucmVsZWFzZUxvY2soKSxhd2FpdCBlLHtkb25lOiEwLHZhbHVlOnZvaWQgMH19LFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKXtyZXR1cm4gdGhpc319fWNvbnN0IEk9KHtoZWFkZXJzOmUsYm9keTp0fSk9Pih7Ym9keUhlYWRlcnM6eyJjb250ZW50LXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIn0sYm9keTpKU09OLnN0cmluZ2lmeSh0KX0pO2xldCBPLCQ7ZnVuY3Rpb24gTChlKXtsZXQgdDtyZXR1cm4oTz8/KHQ9bmV3IGdsb2JhbFRoaXMuVGV4dEVuY29kZXIsTz10LmVuY29kZS5iaW5kKHQpKSkoZSl9ZnVuY3Rpb24gTihlKXtsZXQgdDtyZXR1cm4oJD8/KHQ9bmV3IGdsb2JhbFRoaXMuVGV4dERlY29kZXIsJD10LmRlY29kZS5iaW5kKHQpKSkoZSl9dmFyIEQsVTtjbGFzcyBxe2NvbnN0cnVjdG9yKCl7RC5zZXQodGhpcyx2b2lkIDApLFUuc2V0KHRoaXMsdm9pZCAwKSx0KHRoaXMsRCxuZXcgVWludDhBcnJheSwiZiIpLHQodGhpcyxVLG51bGwsImYiKX1kZWNvZGUoZSl7aWYobnVsbD09ZSlyZXR1cm5bXTtjb25zdCByPWUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9uZXcgVWludDhBcnJheShlKToic3RyaW5nIj09dHlwZW9mIGU/TChlKTplO3QodGhpcyxELGZ1bmN0aW9uKGUpe2xldCB0PTA7Zm9yKGNvbnN0IHMgb2YgZSl0Kz1zLmxlbmd0aDtjb25zdCBzPW5ldyBVaW50OEFycmF5KHQpO2xldCByPTA7Zm9yKGNvbnN0IHQgb2YgZSlzLnNldCh0LHIpLHIrPXQubGVuZ3RoO3JldHVybiBzfShbcyh0aGlzLEQsImYiKSxyXSksImYiKTtjb25zdCBuPVtdO2xldCBhO2Zvcig7bnVsbCE9KGE9aihzKHRoaXMsRCwiZiIpLHModGhpcyxVLCJmIikpKTspe2lmKGEuY2FycmlhZ2UmJm51bGw9PXModGhpcyxVLCJmIikpe3QodGhpcyxVLGEuaW5kZXgsImYiKTtjb250aW51ZX1pZihudWxsIT1zKHRoaXMsVSwiZiIpJiYoYS5pbmRleCE9PXModGhpcyxVLCJmIikrMXx8YS5jYXJyaWFnZSkpe24ucHVzaChOKHModGhpcyxELCJmIikuc3ViYXJyYXkoMCxzKHRoaXMsVSwiZiIpLTEpKSksdCh0aGlzLEQscyh0aGlzLEQsImYiKS5zdWJhcnJheShzKHRoaXMsVSwiZiIpKSwiZiIpLHQodGhpcyxVLG51bGwsImYiKTtjb250aW51ZX1jb25zdCBlPW51bGwhPT1zKHRoaXMsVSwiZiIpP2EucHJlY2VkaW5nLTE6YS5wcmVjZWRpbmcscj1OKHModGhpcyxELCJmIikuc3ViYXJyYXkoMCxlKSk7bi5wdXNoKHIpLHQodGhpcyxELHModGhpcyxELCJmIikuc3ViYXJyYXkoYS5pbmRleCksImYiKSx0KHRoaXMsVSxudWxsLCJmIil9cmV0dXJuIG59Zmx1c2goKXtyZXR1cm4gcyh0aGlzLEQsImYiKS5sZW5ndGg/dGhpcy5kZWNvZGUoIlxuIik6W119fWZ1bmN0aW9uIGooZSx0KXtmb3IobGV0IHM9dD8/MDtzPGUubGVuZ3RoO3MrKyl7aWYoMTA9PT1lW3NdKXJldHVybntwcmVjZWRpbmc6cyxpbmRleDpzKzEsY2FycmlhZ2U6ITF9O2lmKDEzPT09ZVtzXSlyZXR1cm57cHJlY2VkaW5nOnMsaW5kZXg6cysxLGNhcnJpYWdlOiEwfX1yZXR1cm4gbnVsbH1mdW5jdGlvbiBGKGUpe2ZvcihsZXQgdD0wO3Q8ZS5sZW5ndGgtMTt0Kyspe2lmKDEwPT09ZVt0XSYmMTA9PT1lW3QrMV0pcmV0dXJuIHQrMjtpZigxMz09PWVbdF0mJjEzPT09ZVt0KzFdKXJldHVybiB0KzI7aWYoMTM9PT1lW3RdJiYxMD09PWVbdCsxXSYmdCszPGUubGVuZ3RoJiYxMz09PWVbdCsyXSYmMTA9PT1lW3QrM10pcmV0dXJuIHQrNH1yZXR1cm4tMX1EPW5ldyBXZWFrTWFwLFU9bmV3IFdlYWtNYXAscS5ORVdMSU5FX0NIQVJTPW5ldyBTZXQoWyJcbiIsIlxyIl0pLHEuTkVXTElORV9SRUdFWFA9L1xyXG58W1xuXHJdL2c7Y29uc3QgVz17b2ZmOjAsZXJyb3I6MjAwLHdhcm46MzAwLGluZm86NDAwLGRlYnVnOjUwMH0sQj0oZSx0LHMpPT57dmFyIHIsbjtpZihlKXJldHVybiByPVcsbj1lLE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyLG4pP2U6dm9pZCBWKHMpLndhcm4oYCR7dH0gd2FzIHNldCB0byAke0pTT04uc3RyaW5naWZ5KGUpfSwgZXhwZWN0ZWQgb25lIG9mICR7SlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXMoVykpfWApfTtmdW5jdGlvbiBKKCl7fWZ1bmN0aW9uIHooZSx0LHMpe3JldHVybiF0fHxXW2VdPldbc10/Sjp0W2VdLmJpbmQodCl9Y29uc3QgSD17ZXJyb3I6Six3YXJuOkosaW5mbzpKLGRlYnVnOkp9O2xldCBLPW5ldyBXZWFrTWFwO2Z1bmN0aW9uIFYoZSl7Y29uc3QgdD1lLmxvZ2dlcixzPWUubG9nTGV2ZWw/PyJvZmYiO2lmKCF0KXJldHVybiBIO2NvbnN0IHI9Sy5nZXQodCk7aWYociYmclswXT09PXMpcmV0dXJuIHJbMV07Y29uc3Qgbj17ZXJyb3I6eigiZXJyb3IiLHQscyksd2Fybjp6KCJ3YXJuIix0LHMpLGluZm86eigiaW5mbyIsdCxzKSxkZWJ1Zzp6KCJkZWJ1ZyIsdCxzKX07cmV0dXJuIEsuc2V0KHQsW3Msbl0pLG59Y29uc3QgWD1lPT4oZS5vcHRpb25zJiYoZS5vcHRpb25zPXsuLi5lLm9wdGlvbnN9LGRlbGV0ZSBlLm9wdGlvbnMuaGVhZGVycyksZS5oZWFkZXJzJiYoZS5oZWFkZXJzPU9iamVjdC5mcm9tRW50cmllcygoZS5oZWFkZXJzIGluc3RhbmNlb2YgSGVhZGVycz9bLi4uZS5oZWFkZXJzXTpPYmplY3QuZW50cmllcyhlLmhlYWRlcnMpKS5tYXAoKFtlLHRdKT0+W2UsIngtYXBpLWtleSI9PT1lLnRvTG93ZXJDYXNlKCl8fCJhdXRob3JpemF0aW9uIj09PWUudG9Mb3dlckNhc2UoKXx8ImNvb2tpZSI9PT1lLnRvTG93ZXJDYXNlKCl8fCJzZXQtY29va2llIj09PWUudG9Mb3dlckNhc2UoKT8iKioqIjp0XSkpKSwicmV0cnlPZlJlcXVlc3RMb2dJRCJpbiBlJiYoZS5yZXRyeU9mUmVxdWVzdExvZ0lEJiYoZS5yZXRyeU9mPWUucmV0cnlPZlJlcXVlc3RMb2dJRCksZGVsZXRlIGUucmV0cnlPZlJlcXVlc3RMb2dJRCksZSk7dmFyIEcsWSxRO2NsYXNzIFp7Y29uc3RydWN0b3IoZSxzLHIpe3RoaXMuaXRlcmF0b3I9ZSxHLnNldCh0aGlzLHZvaWQgMCksdGhpcy5jb250cm9sbGVyPXMsdCh0aGlzLEcsciwiZiIpfXN0YXRpYyBmcm9tU1NFUmVzcG9uc2UoZSx0LHMpe2xldCByPSExO2NvbnN0IGE9cz9WKHMpOmNvbnNvbGU7cmV0dXJuIG5ldyBaKGFzeW5jIGZ1bmN0aW9uKigpe2lmKHIpdGhyb3cgbmV3IG8oIkNhbm5vdCBpdGVyYXRlIG92ZXIgYSBjb25zdW1lZCBzdHJlYW0sIHVzZSBgLnRlZSgpYCB0byBzcGxpdCB0aGUgc3RyZWFtLiIpO3I9ITA7bGV0IHM9ITE7dHJ5e2ZvciBhd2FpdChjb25zdCBzIG9mIGFzeW5jIGZ1bmN0aW9uKihlLHQpe2lmKCFlLmJvZHkpe2lmKHQuYWJvcnQoKSx2b2lkIDAhPT1nbG9iYWxUaGlzLm5hdmlnYXRvciYmIlJlYWN0TmF0aXZlIj09PWdsb2JhbFRoaXMubmF2aWdhdG9yLnByb2R1Y3QpdGhyb3cgbmV3IG8oIlRoZSBkZWZhdWx0IHJlYWN0LW5hdGl2ZSBmZXRjaCBpbXBsZW1lbnRhdGlvbiBkb2VzIG5vdCBzdXBwb3J0IHN0cmVhbWluZy4gUGxlYXNlIHVzZSBleHBvL2ZldGNoOiBodHRwczovL2RvY3MuZXhwby5kZXYvdmVyc2lvbnMvbGF0ZXN0L3Nkay9leHBvLyNleHBvZmV0Y2gtYXBpIik7dGhyb3cgbmV3IG8oIkF0dGVtcHRlZCB0byBpdGVyYXRlIG92ZXIgYSByZXNwb25zZSB3aXRoIG5vIGJvZHkiKX1jb25zdCBzPW5ldyBlZSxyPW5ldyBxLG49QyhlLmJvZHkpO2ZvciBhd2FpdChjb25zdCBlIG9mIGFzeW5jIGZ1bmN0aW9uKihlKXtsZXQgdD1uZXcgVWludDhBcnJheTtmb3IgYXdhaXQoY29uc3QgcyBvZiBlKXtpZihudWxsPT1zKWNvbnRpbnVlO2NvbnN0IGU9cyBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP25ldyBVaW50OEFycmF5KHMpOiJzdHJpbmciPT10eXBlb2Ygcz9MKHMpOnM7bGV0IHIsbj1uZXcgVWludDhBcnJheSh0Lmxlbmd0aCtlLmxlbmd0aCk7Zm9yKG4uc2V0KHQpLG4uc2V0KGUsdC5sZW5ndGgpLHQ9bjstMSE9PShyPUYodCkpOyl5aWVsZCB0LnNsaWNlKDAsciksdD10LnNsaWNlKHIpfXQubGVuZ3RoPjAmJih5aWVsZCB0KX0obikpZm9yKGNvbnN0IHQgb2Ygci5kZWNvZGUoZSkpe2NvbnN0IGU9cy5kZWNvZGUodCk7ZSYmKHlpZWxkIGUpfWZvcihjb25zdCBlIG9mIHIuZmx1c2goKSl7Y29uc3QgdD1zLmRlY29kZShlKTt0JiYoeWllbGQgdCl9fShlLHQpKXtpZigiY29tcGxldGlvbiI9PT1zLmV2ZW50KXRyeXt5aWVsZCBKU09OLnBhcnNlKHMuZGF0YSl9Y2F0Y2goZSl7dGhyb3cgYS5lcnJvcigiQ291bGQgbm90IHBhcnNlIG1lc3NhZ2UgaW50byBKU09OOiIscy5kYXRhKSxhLmVycm9yKCJGcm9tIGNodW5rOiIscy5yYXcpLGV9aWYoIm1lc3NhZ2Vfc3RhcnQiPT09cy5ldmVudHx8Im1lc3NhZ2VfZGVsdGEiPT09cy5ldmVudHx8Im1lc3NhZ2Vfc3RvcCI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19zdGFydCI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19kZWx0YSI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19zdG9wIj09PXMuZXZlbnQpdHJ5e3lpZWxkIEpTT04ucGFyc2Uocy5kYXRhKX1jYXRjaChlKXt0aHJvdyBhLmVycm9yKCJDb3VsZCBub3QgcGFyc2UgbWVzc2FnZSBpbnRvIEpTT046IixzLmRhdGEpLGEuZXJyb3IoIkZyb20gY2h1bms6IixzLnJhdyksZX1pZigicGluZyIhPT1zLmV2ZW50JiYiZXJyb3IiPT09cy5ldmVudCl0aHJvdyBuZXcgaSh2b2lkIDAsUyhzLmRhdGEpPz9zLmRhdGEsdm9pZCAwLGUuaGVhZGVycyl9cz0hMH1jYXRjaChlKXtpZihuKGUpKXJldHVybjt0aHJvdyBlfWZpbmFsbHl7c3x8dC5hYm9ydCgpfX0sdCxzKX1zdGF0aWMgZnJvbVJlYWRhYmxlU3RyZWFtKGUsdCxzKXtsZXQgcj0hMTtyZXR1cm4gbmV3IFooYXN5bmMgZnVuY3Rpb24qKCl7aWYocil0aHJvdyBuZXcgbygiQ2Fubm90IGl0ZXJhdGUgb3ZlciBhIGNvbnN1bWVkIHN0cmVhbSwgdXNlIGAudGVlKClgIHRvIHNwbGl0IHRoZSBzdHJlYW0uIik7cj0hMDtsZXQgcz0hMTt0cnl7Zm9yIGF3YWl0KGNvbnN0IHQgb2YgYXN5bmMgZnVuY3Rpb24qKCl7Y29uc3QgdD1uZXcgcSxzPUMoZSk7Zm9yIGF3YWl0KGNvbnN0IGUgb2Ygcylmb3IoY29uc3QgcyBvZiB0LmRlY29kZShlKSl5aWVsZCBzO2Zvcihjb25zdCBlIG9mIHQuZmx1c2goKSl5aWVsZCBlfSgpKXN8fHQmJih5aWVsZCBKU09OLnBhcnNlKHQpKTtzPSEwfWNhdGNoKGUpe2lmKG4oZSkpcmV0dXJuO3Rocm93IGV9ZmluYWxseXtzfHx0LmFib3J0KCl9fSx0LHMpfVsoRz1uZXcgV2Vha01hcCxTeW1ib2wuYXN5bmNJdGVyYXRvcildKCl7cmV0dXJuIHRoaXMuaXRlcmF0b3IoKX10ZWUoKXtjb25zdCBlPVtdLHQ9W10scj10aGlzLml0ZXJhdG9yKCksbj1zPT4oe25leHQ6KCk9PntpZigwPT09cy5sZW5ndGgpe2NvbnN0IHM9ci5uZXh0KCk7ZS5wdXNoKHMpLHQucHVzaChzKX1yZXR1cm4gcy5zaGlmdCgpfX0pO3JldHVybltuZXcgWigoKT0+bihlKSx0aGlzLmNvbnRyb2xsZXIscyh0aGlzLEcsImYiKSksbmV3IFooKCk9Pm4odCksdGhpcy5jb250cm9sbGVyLHModGhpcyxHLCJmIikpXX10b1JlYWRhYmxlU3RyZWFtKCl7Y29uc3QgZT10aGlzO2xldCB0O3JldHVybiBUKHthc3luYyBzdGFydCgpe3Q9ZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKX0sYXN5bmMgcHVsbChlKXt0cnl7Y29uc3R7dmFsdWU6cyxkb25lOnJ9PWF3YWl0IHQubmV4dCgpO2lmKHIpcmV0dXJuIGUuY2xvc2UoKTtjb25zdCBuPUwoSlNPTi5zdHJpbmdpZnkocykrIlxuIik7ZS5lbnF1ZXVlKG4pfWNhdGNoKHQpe2UuZXJyb3IodCl9fSxhc3luYyBjYW5jZWwoKXthd2FpdCh0LnJldHVybj8uKCkpfX0pfX1jbGFzcyBlZXtjb25zdHJ1Y3Rvcigpe3RoaXMuZXZlbnQ9bnVsbCx0aGlzLmRhdGE9W10sdGhpcy5jaHVua3M9W119ZGVjb2RlKGUpe2lmKGUuZW5kc1dpdGgoIlxyIikmJihlPWUuc3Vic3RyaW5nKDAsZS5sZW5ndGgtMSkpLCFlKXtpZighdGhpcy5ldmVudCYmIXRoaXMuZGF0YS5sZW5ndGgpcmV0dXJuIG51bGw7Y29uc3QgZT17ZXZlbnQ6dGhpcy5ldmVudCxkYXRhOnRoaXMuZGF0YS5qb2luKCJcbiIpLHJhdzp0aGlzLmNodW5rc307cmV0dXJuIHRoaXMuZXZlbnQ9bnVsbCx0aGlzLmRhdGE9W10sdGhpcy5jaHVua3M9W10sZX1pZih0aGlzLmNodW5rcy5wdXNoKGUpLGUuc3RhcnRzV2l0aCgiOiIpKXJldHVybiBudWxsO2xldFt0LHMscl09ZnVuY3Rpb24oZSl7Y29uc3QgdD1lLmluZGV4T2YoIjoiKTtyZXR1cm4tMSE9PXQ/W2Uuc3Vic3RyaW5nKDAsdCksIjoiLGUuc3Vic3RyaW5nKHQrMSldOltlLCIiLCIiXX0oZSk7cmV0dXJuIHIuc3RhcnRzV2l0aCgiICIpJiYocj1yLnN1YnN0cmluZygxKSksImV2ZW50Ij09PXQ/dGhpcy5ldmVudD1yOiJkYXRhIj09PXQmJnRoaXMuZGF0YS5wdXNoKHIpLG51bGx9fWFzeW5jIGZ1bmN0aW9uIHRlKGUsdCl7Y29uc3R7cmVzcG9uc2U6cyxyZXF1ZXN0TG9nSUQ6cixyZXRyeU9mUmVxdWVzdExvZ0lEOm4sc3RhcnRUaW1lOmF9PXQsbz1hd2FpdChhc3luYygpPT57aWYodC5vcHRpb25zLnN0cmVhbSlyZXR1cm4gVihlKS5kZWJ1ZygicmVzcG9uc2UiLHMuc3RhdHVzLHMudXJsLHMuaGVhZGVycyxzLmJvZHkpLHQub3B0aW9ucy5fX3N0cmVhbUNsYXNzP3Qub3B0aW9ucy5fX3N0cmVhbUNsYXNzLmZyb21TU0VSZXNwb25zZShzLHQuY29udHJvbGxlcik6Wi5mcm9tU1NFUmVzcG9uc2Uocyx0LmNvbnRyb2xsZXIpO2lmKDIwND09PXMuc3RhdHVzKXJldHVybiBudWxsO2lmKHQub3B0aW9ucy5fX2JpbmFyeVJlc3BvbnNlKXJldHVybiBzO2NvbnN0IHI9cy5oZWFkZXJzLmdldCgiY29udGVudC10eXBlIiksbj1yPy5zcGxpdCgiOyIpWzBdPy50cmltKCk7cmV0dXJuIG4/LmluY2x1ZGVzKCJhcHBsaWNhdGlvbi9qc29uIil8fG4/LmVuZHNXaXRoKCIranNvbiIpP3NlKGF3YWl0IHMuanNvbigpLHMpOmF3YWl0IHMudGV4dCgpfSkoKTtyZXR1cm4gVihlKS5kZWJ1ZyhgWyR7cn1dIHJlc3BvbnNlIHBhcnNlZGAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpuLHVybDpzLnVybCxzdGF0dXM6cy5zdGF0dXMsYm9keTpvLGR1cmF0aW9uTXM6RGF0ZS5ub3coKS1hfSkpLG99ZnVuY3Rpb24gc2UoZSx0KXtyZXR1cm4hZXx8Im9iamVjdCIhPXR5cGVvZiBlfHxBcnJheS5pc0FycmF5KGUpP2U6T2JqZWN0LmRlZmluZVByb3BlcnR5KGUsIl9yZXF1ZXN0X2lkIix7dmFsdWU6dC5oZWFkZXJzLmdldCgicmVxdWVzdC1pZCIpLGVudW1lcmFibGU6ITF9KX1jbGFzcyByZSBleHRlbmRzIFByb21pc2V7Y29uc3RydWN0b3IoZSxzLHI9dGUpe3N1cGVyKGU9PntlKG51bGwpfSksdGhpcy5yZXNwb25zZVByb21pc2U9cyx0aGlzLnBhcnNlUmVzcG9uc2U9cixZLnNldCh0aGlzLHZvaWQgMCksdCh0aGlzLFksZSwiZiIpfV90aGVuVW53cmFwKGUpe3JldHVybiBuZXcgcmUocyh0aGlzLFksImYiKSx0aGlzLnJlc3BvbnNlUHJvbWlzZSxhc3luYyh0LHMpPT5zZShlKGF3YWl0IHRoaXMucGFyc2VSZXNwb25zZSh0LHMpLHMpLHMucmVzcG9uc2UpKX1hc1Jlc3BvbnNlKCl7cmV0dXJuIHRoaXMucmVzcG9uc2VQcm9taXNlLnRoZW4oZT0+ZS5yZXNwb25zZSl9YXN5bmMgd2l0aFJlc3BvbnNlKCl7Y29uc3RbZSx0XT1hd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wYXJzZSgpLHRoaXMuYXNSZXNwb25zZSgpXSk7cmV0dXJue2RhdGE6ZSxyZXNwb25zZTp0LHJlcXVlc3RfaWQ6dC5oZWFkZXJzLmdldCgicmVxdWVzdC1pZCIpfX1wYXJzZSgpe3JldHVybiB0aGlzLnBhcnNlZFByb21pc2V8fCh0aGlzLnBhcnNlZFByb21pc2U9dGhpcy5yZXNwb25zZVByb21pc2UudGhlbihlPT50aGlzLnBhcnNlUmVzcG9uc2Uocyh0aGlzLFksImYiKSxlKSkpLHRoaXMucGFyc2VkUHJvbWlzZX10aGVuKGUsdCl7cmV0dXJuIHRoaXMucGFyc2UoKS50aGVuKGUsdCl9Y2F0Y2goZSl7cmV0dXJuIHRoaXMucGFyc2UoKS5jYXRjaChlKX1maW5hbGx5KGUpe3JldHVybiB0aGlzLnBhcnNlKCkuZmluYWxseShlKX19WT1uZXcgV2Vha01hcDtjbGFzcyBuZXtjb25zdHJ1Y3RvcihlLHMscixuKXtRLnNldCh0aGlzLHZvaWQgMCksdCh0aGlzLFEsZSwiZiIpLHRoaXMub3B0aW9ucz1uLHRoaXMucmVzcG9uc2U9cyx0aGlzLmJvZHk9cn1oYXNOZXh0UGFnZSgpe3JldHVybiEhdGhpcy5nZXRQYWdpbmF0ZWRJdGVtcygpLmxlbmd0aCYmbnVsbCE9dGhpcy5uZXh0UGFnZVJlcXVlc3RPcHRpb25zKCl9YXN5bmMgZ2V0TmV4dFBhZ2UoKXtjb25zdCBlPXRoaXMubmV4dFBhZ2VSZXF1ZXN0T3B0aW9ucygpO2lmKCFlKXRocm93IG5ldyBvKCJObyBuZXh0IHBhZ2UgZXhwZWN0ZWQ7IHBsZWFzZSBjaGVjayBgLmhhc05leHRQYWdlKClgIGJlZm9yZSBjYWxsaW5nIGAuZ2V0TmV4dFBhZ2UoKWAuIik7cmV0dXJuIGF3YWl0IHModGhpcyxRLCJmIikucmVxdWVzdEFQSUxpc3QodGhpcy5jb25zdHJ1Y3RvcixlKX1hc3luYyppdGVyUGFnZXMoKXtsZXQgZT10aGlzO2Zvcih5aWVsZCBlO2UuaGFzTmV4dFBhZ2UoKTspZT1hd2FpdCBlLmdldE5leHRQYWdlKCkseWllbGQgZX1hc3luYypbKFE9bmV3IFdlYWtNYXAsU3ltYm9sLmFzeW5jSXRlcmF0b3IpXSgpe2ZvciBhd2FpdChjb25zdCBlIG9mIHRoaXMuaXRlclBhZ2VzKCkpZm9yKGNvbnN0IHQgb2YgZS5nZXRQYWdpbmF0ZWRJdGVtcygpKXlpZWxkIHR9fWNsYXNzIGFlIGV4dGVuZHMgcmV7Y29uc3RydWN0b3IoZSx0LHMpe3N1cGVyKGUsdCxhc3luYyhlLHQpPT5uZXcgcyhlLHQucmVzcG9uc2UsYXdhaXQgdGUoZSx0KSx0Lm9wdGlvbnMpKX1hc3luYypbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7Y29uc3QgZT1hd2FpdCh0aGlzKTtmb3IgYXdhaXQoY29uc3QgdCBvZiBlKXlpZWxkIHR9fWNsYXNzIG9lIGV4dGVuZHMgbmV7Y29uc3RydWN0b3IoZSx0LHMscil7c3VwZXIoZSx0LHMsciksdGhpcy5kYXRhPXMuZGF0YXx8W10sdGhpcy5oYXNfbW9yZT1zLmhhc19tb3JlfHwhMSx0aGlzLmZpcnN0X2lkPXMuZmlyc3RfaWR8fG51bGwsdGhpcy5sYXN0X2lkPXMubGFzdF9pZHx8bnVsbH1nZXRQYWdpbmF0ZWRJdGVtcygpe3JldHVybiB0aGlzLmRhdGE/P1tdfWhhc05leHRQYWdlKCl7cmV0dXJuITEhPT10aGlzLmhhc19tb3JlJiZzdXBlci5oYXNOZXh0UGFnZSgpfW5leHRQYWdlUmVxdWVzdE9wdGlvbnMoKXtpZih0aGlzLm9wdGlvbnMucXVlcnk/LmJlZm9yZV9pZCl7Y29uc3QgZT10aGlzLmZpcnN0X2lkO3JldHVybiBlP3suLi50aGlzLm9wdGlvbnMscXVlcnk6ey4uLmsodGhpcy5vcHRpb25zLnF1ZXJ5KSxiZWZvcmVfaWQ6ZX19Om51bGx9Y29uc3QgZT10aGlzLmxhc3RfaWQ7cmV0dXJuIGU/ey4uLnRoaXMub3B0aW9ucyxxdWVyeTp7Li4uayh0aGlzLm9wdGlvbnMucXVlcnkpLGFmdGVyX2lkOmV9fTpudWxsfX1jbGFzcyBpZSBleHRlbmRzIG5le2NvbnN0cnVjdG9yKGUsdCxzLHIpe3N1cGVyKGUsdCxzLHIpLHRoaXMuZGF0YT1zLmRhdGF8fFtdLHRoaXMuaGFzX21vcmU9cy5oYXNfbW9yZXx8ITEsdGhpcy5uZXh0X3BhZ2U9cy5uZXh0X3BhZ2V8fG51bGx9Z2V0UGFnaW5hdGVkSXRlbXMoKXtyZXR1cm4gdGhpcy5kYXRhPz9bXX1oYXNOZXh0UGFnZSgpe3JldHVybiExIT09dGhpcy5oYXNfbW9yZSYmc3VwZXIuaGFzTmV4dFBhZ2UoKX1uZXh0UGFnZVJlcXVlc3RPcHRpb25zKCl7Y29uc3QgZT10aGlzLm5leHRfcGFnZTtyZXR1cm4gZT97Li4udGhpcy5vcHRpb25zLHF1ZXJ5OnsuLi5rKHRoaXMub3B0aW9ucy5xdWVyeSkscGFnZTplfX06bnVsbH19Y29uc3QgY2U9KCk9PntpZigidW5kZWZpbmVkIj09dHlwZW9mIEZpbGUpe2NvbnN0e3Byb2Nlc3M6ZX09Z2xvYmFsVGhpcyx0PSJzdHJpbmciPT10eXBlb2YgZT8udmVyc2lvbnM/Lm5vZGUmJnBhcnNlSW50KGUudmVyc2lvbnMubm9kZS5zcGxpdCgiLiIpKTwyMDt0aHJvdyBuZXcgRXJyb3IoImBGaWxlYCBpcyBub3QgZGVmaW5lZCBhcyBhIGdsb2JhbCwgd2hpY2ggaXMgcmVxdWlyZWQgZm9yIGZpbGUgdXBsb2Fkcy4iKyh0PyIgVXBkYXRlIHRvIE5vZGUgMjAgTFRTIG9yIG5ld2VyLCBvciBzZXQgYGdsb2JhbFRoaXMuRmlsZWAgdG8gYGltcG9ydCgnbm9kZTpidWZmZXInKS5GaWxlYC4iOiIiKSl9fTtmdW5jdGlvbiBsZShlLHQscyl7cmV0dXJuIGNlKCksbmV3IEZpbGUoZSx0Pz8idW5rbm93bl9maWxlIixzKX1mdW5jdGlvbiBkZShlKXtyZXR1cm4oIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSYmKCJuYW1lImluIGUmJmUubmFtZSYmU3RyaW5nKGUubmFtZSl8fCJ1cmwiaW4gZSYmZS51cmwmJlN0cmluZyhlLnVybCl8fCJmaWxlbmFtZSJpbiBlJiZlLmZpbGVuYW1lJiZTdHJpbmcoZS5maWxlbmFtZSl8fCJwYXRoImluIGUmJmUucGF0aCYmU3RyaW5nKGUucGF0aCkpfHwiIikuc3BsaXQoL1tcXC9dLykucG9wKCl8fHZvaWQgMH1jb25zdCBoZT1lPT5udWxsIT1lJiYib2JqZWN0Ij09dHlwZW9mIGUmJiJmdW5jdGlvbiI9PXR5cGVvZiBlW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSx1ZT1hc3luYyhlLHQpPT4oey4uLmUsYm9keTphd2FpdCBmZShlLmJvZHksdCl9KSxwZT1uZXcgV2Vha01hcCxmZT1hc3luYyhlLHQpPT57aWYoIWF3YWl0IGZ1bmN0aW9uKGUpe2NvbnN0IHQ9ImZ1bmN0aW9uIj09dHlwZW9mIGU/ZTplLmZldGNoLHM9cGUuZ2V0KHQpO2lmKHMpcmV0dXJuIHM7Y29uc3Qgcj0oYXN5bmMoKT0+e3RyeXtjb25zdCBlPSJSZXNwb25zZSJpbiB0P3QuUmVzcG9uc2U6KGF3YWl0IHQoImRhdGE6LCIpKS5jb25zdHJ1Y3RvcixzPW5ldyBGb3JtRGF0YTtyZXR1cm4gcy50b1N0cmluZygpIT09YXdhaXQgbmV3IGUocykudGV4dCgpfWNhdGNoe3JldHVybiEwfX0pKCk7cmV0dXJuIHBlLnNldCh0LHIpLHJ9KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIlRoZSBwcm92aWRlZCBmZXRjaCBmdW5jdGlvbiBkb2VzIG5vdCBzdXBwb3J0IGZpbGUgdXBsb2FkcyB3aXRoIHRoZSBjdXJyZW50IGdsb2JhbCBGb3JtRGF0YSBjbGFzcy4iKTtjb25zdCBzPW5ldyBGb3JtRGF0YTtyZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoT2JqZWN0LmVudHJpZXMoZXx8e30pLm1hcCgoW2UsdF0pPT5tZShzLGUsdCkpKSxzfSxtZT1hc3luYyhlLHQscyk9PntpZih2b2lkIDAhPT1zKXtpZihudWxsPT1zKXRocm93IG5ldyBUeXBlRXJyb3IoYFJlY2VpdmVkIG51bGwgZm9yICIke3R9IjsgdG8gcGFzcyBudWxsIGluIEZvcm1EYXRhLCB5b3UgbXVzdCB1c2UgdGhlIHN0cmluZyAnbnVsbCdgKTtpZigic3RyaW5nIj09dHlwZW9mIHN8fCJudW1iZXIiPT10eXBlb2Ygc3x8ImJvb2xlYW4iPT10eXBlb2YgcyllLmFwcGVuZCh0LFN0cmluZyhzKSk7ZWxzZSBpZihzIGluc3RhbmNlb2YgUmVzcG9uc2Upe2xldCByPXt9O2NvbnN0IG49cy5oZWFkZXJzLmdldCgiQ29udGVudC1UeXBlIik7biYmKHI9e3R5cGU6bn0pLGUuYXBwZW5kKHQsbGUoW2F3YWl0IHMuYmxvYigpXSxkZShzKSxyKSl9ZWxzZSBpZihoZShzKSllLmFwcGVuZCh0LGxlKFthd2FpdCBuZXcgUmVzcG9uc2UoQShzKSkuYmxvYigpXSxkZShzKSkpO2Vsc2UgaWYoKGU9PmUgaW5zdGFuY2VvZiBCbG9iJiYibmFtZSJpbiBlKShzKSllLmFwcGVuZCh0LGxlKFtzXSxkZShzKSx7dHlwZTpzLnR5cGV9KSk7ZWxzZSBpZihBcnJheS5pc0FycmF5KHMpKWF3YWl0IFByb21pc2UuYWxsKHMubWFwKHM9Pm1lKGUsdCsiW10iLHMpKSk7ZWxzZXtpZigib2JqZWN0IiE9dHlwZW9mIHMpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCB2YWx1ZSBnaXZlbiB0byBmb3JtLCBleHBlY3RlZCBhIHN0cmluZywgbnVtYmVyLCBib29sZWFuLCBvYmplY3QsIEFycmF5LCBGaWxlIG9yIEJsb2IgYnV0IGdvdCAke3N9IGluc3RlYWRgKTthd2FpdCBQcm9taXNlLmFsbChPYmplY3QuZW50cmllcyhzKS5tYXAoKFtzLHJdKT0+bWUoZSxgJHt0fVske3N9XWAscikpKX19fSxnZT1lPT5udWxsIT1lJiYib2JqZWN0Ij09dHlwZW9mIGUmJiJudW1iZXIiPT10eXBlb2YgZS5zaXplJiYic3RyaW5nIj09dHlwZW9mIGUudHlwZSYmImZ1bmN0aW9uIj09dHlwZW9mIGUudGV4dCYmImZ1bmN0aW9uIj09dHlwZW9mIGUuc2xpY2UmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLmFycmF5QnVmZmVyO2FzeW5jIGZ1bmN0aW9uIHdlKGUpe2xldCB0PVtdO2lmKCJzdHJpbmciPT10eXBlb2YgZXx8QXJyYXlCdWZmZXIuaXNWaWV3KGUpfHxlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpdC5wdXNoKGUpO2Vsc2UgaWYoZ2UoZSkpdC5wdXNoKGUgaW5zdGFuY2VvZiBCbG9iP2U6YXdhaXQgZS5hcnJheUJ1ZmZlcigpKTtlbHNle2lmKCFoZShlKSl7Y29uc3QgdD1lPy5jb25zdHJ1Y3Rvcj8ubmFtZTt0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZGF0YSB0eXBlOiAke3R5cGVvZiBlfSR7dD9gOyBjb25zdHJ1Y3RvcjogJHt0fWA6IiJ9JHtmdW5jdGlvbihlKXtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lKXJldHVybiIiO3JldHVybmA7IHByb3BzOiBbJHtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhlKS5tYXAoZT0+YCIke2V9ImApLmpvaW4oIiwgIil9XWB9KGUpfWApfWZvciBhd2FpdChjb25zdCBzIG9mIGUpdC5wdXNoKC4uLmF3YWl0IHdlKHMpKX1yZXR1cm4gdH1jbGFzcyB5ZXtjb25zdHJ1Y3RvcihlKXt0aGlzLl9jbGllbnQ9ZX19Y29uc3QgYmU9U3ltYm9sLmZvcigiYnJhbmQucHJpdmF0ZU51bGxhYmxlSGVhZGVycyIpO2Z1bmN0aW9uKnZlKGUpe2lmKCFlKXJldHVybjtpZihiZSBpbiBlKXtjb25zdHt2YWx1ZXM6dCxudWxsczpzfT1lO3lpZWxkKnQuZW50cmllcygpO2Zvcihjb25zdCBlIG9mIHMpeWllbGRbZSxudWxsXTtyZXR1cm59bGV0IHQscz0hMTtlIGluc3RhbmNlb2YgSGVhZGVycz90PWUuZW50cmllcygpOl8oZSk/dD1lOihzPSEwLHQ9T2JqZWN0LmVudHJpZXMoZT8/e30pKTtmb3IobGV0IGUgb2YgdCl7Y29uc3QgdD1lWzBdO2lmKCJzdHJpbmciIT10eXBlb2YgdCl0aHJvdyBuZXcgVHlwZUVycm9yKCJleHBlY3RlZCBoZWFkZXIgbmFtZSB0byBiZSBhIHN0cmluZyIpO2NvbnN0IHI9XyhlWzFdKT9lWzFdOltlWzFdXTtsZXQgbj0hMTtmb3IoY29uc3QgZSBvZiByKXZvaWQgMCE9PWUmJihzJiYhbiYmKG49ITAseWllbGRbdCxudWxsXSkseWllbGRbdCxlXSl9fWNvbnN0IF9lPWU9Pntjb25zdCB0PW5ldyBIZWFkZXJzLHM9bmV3IFNldDtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPW5ldyBTZXQ7Zm9yKGNvbnN0W24sYV1vZiB2ZShyKSl7Y29uc3Qgcj1uLnRvTG93ZXJDYXNlKCk7ZS5oYXMocil8fCh0LmRlbGV0ZShuKSxlLmFkZChyKSksbnVsbD09PWE/KHQuZGVsZXRlKG4pLHMuYWRkKHIpKToodC5hcHBlbmQobixhKSxzLmRlbGV0ZShyKSl9fXJldHVybntbYmVdOiEwLHZhbHVlczp0LG51bGxzOnN9fTtmdW5jdGlvbiBrZShlKXtyZXR1cm4gZS5yZXBsYWNlKC9bXkEtWmEtejAtOVwtLl9+ISQmJygpKissOz06QF0rL2csZW5jb2RlVVJJQ29tcG9uZW50KX1jb25zdCBTZT1PYmplY3QuZnJlZXplKE9iamVjdC5jcmVhdGUobnVsbCkpLE1lPShlPWtlKT0+ZnVuY3Rpb24odCwuLi5zKXtpZigxPT09dC5sZW5ndGgpcmV0dXJuIHRbMF07bGV0IHI9ITE7Y29uc3Qgbj1bXSxhPXQucmVkdWNlKCh0LGEsbyk9PnsvWz8jXS8udGVzdChhKSYmKHI9ITApO2NvbnN0IGk9c1tvXTtsZXQgYz0ocj9lbmNvZGVVUklDb21wb25lbnQ6ZSkoIiIraSk7cmV0dXJuIG8hPT1zLmxlbmd0aCYmKG51bGw9PWl8fCJvYmplY3QiPT10eXBlb2YgaSYmaS50b1N0cmluZz09PU9iamVjdC5nZXRQcm90b3R5cGVPZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoaS5oYXNPd25Qcm9wZXJ0eT8/U2UpPz9TZSk/LnRvU3RyaW5nKSYmKGM9aSsiIixuLnB1c2goe3N0YXJ0OnQubGVuZ3RoK2EubGVuZ3RoLGxlbmd0aDpjLmxlbmd0aCxlcnJvcjpgVmFsdWUgb2YgdHlwZSAke09iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpKS5zbGljZSg4LC0xKX0gaXMgbm90IGEgdmFsaWQgcGF0aCBwYXJhbWV0ZXJgfSkpLHQrYSsobz09PXMubGVuZ3RoPyIiOmMpfSwiIiksaT1hLnNwbGl0KC9bPyNdLywxKVswXSxjPS8oPzw9XnxcLykoPzpcLnwlMmUpezEsMn0oPz1cL3wkKS9naTtsZXQgbDtmb3IoO251bGwhPT0obD1jLmV4ZWMoaSkpOyluLnB1c2goe3N0YXJ0OmwuaW5kZXgsbGVuZ3RoOmxbMF0ubGVuZ3RoLGVycm9yOmBWYWx1ZSAiJHtsWzBdfSIgY2FuJ3QgYmUgc2FmZWx5IHBhc3NlZCBhcyBhIHBhdGggcGFyYW1ldGVyYH0pO2lmKG4uc29ydCgoZSx0KT0+ZS5zdGFydC10LnN0YXJ0KSxuLmxlbmd0aD4wKXtsZXQgZT0wO2NvbnN0IHQ9bi5yZWR1Y2UoKHQscyk9Pntjb25zdCByPSIgIi5yZXBlYXQocy5zdGFydC1lKSxuPSJeIi5yZXBlYXQocy5sZW5ndGgpO3JldHVybiBlPXMuc3RhcnQrcy5sZW5ndGgsdCtyK259LCIiKTt0aHJvdyBuZXcgbyhgUGF0aCBwYXJhbWV0ZXJzIHJlc3VsdCBpbiBwYXRoIHdpdGggaW52YWxpZCBzZWdtZW50czpcbiR7bi5tYXAoZT0+ZS5lcnJvcikuam9pbigiXG4iKX1cbiR7YX1cbiR7dH1gKX1yZXR1cm4gYX0sUGU9TWUoa2UpO2NsYXNzIEVlIGV4dGVuZHMgeWV7bGlzdChlPXt9LHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZT8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvZmlsZXMiLG9lLHtxdWVyeTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0pfWRlbGV0ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5kZWxldGUoUGVgL3YxL2ZpbGVzLyR7ZX1gLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwiZmlsZXMtYXBpLTIwMjUtMDQtMTQiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1kb3dubG9hZChlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL2ZpbGVzLyR7ZX0vY29udGVudGAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCksQWNjZXB0OiJhcHBsaWNhdGlvbi9iaW5hcnkifSxzPy5oZWFkZXJzXSksX19iaW5hcnlSZXNwb25zZTohMH0pfXJldHJpZXZlTWV0YWRhdGEoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9maWxlcy8ke2V9YCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucj8/W10sImZpbGVzLWFwaS0yMDI1LTA0LTE0Il0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9dXBsb2FkKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL2ZpbGVzIix1ZSh7Ym9keTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0sdGhpcy5fY2xpZW50KSl9fWNsYXNzIFJlIGV4dGVuZHMgeWV7cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9tb2RlbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3suLi5udWxsIT1yPy50b1N0cmluZygpP3siYW50aHJvcGljLWJldGEiOnI/LnRvU3RyaW5nKCl9OnZvaWQgMH0scz8uaGVhZGVyc10pfSl9bGlzdChlPXt9LHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZT8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvbW9kZWxzP2JldGE9dHJ1ZSIsb2Use3F1ZXJ5OnIsLi4udCxoZWFkZXJzOl9lKFt7Li4ubnVsbCE9cz8udG9TdHJpbmcoKT97ImFudGhyb3BpYy1iZXRhIjpzPy50b1N0cmluZygpfTp2b2lkIDB9LHQ/LmhlYWRlcnNdKX0pfX1jb25zdCB4ZT17ImNsYXVkZS1vcHVzLTQtMjAyNTA1MTQiOjgxOTIsImNsYXVkZS1vcHVzLTQtMCI6ODE5MiwiY2xhdWRlLTQtb3B1cy0yMDI1MDUxNCI6ODE5MiwiYW50aHJvcGljLmNsYXVkZS1vcHVzLTQtMjAyNTA1MTQtdjE6MCI6ODE5MiwiY2xhdWRlLW9wdXMtNEAyMDI1MDUxNCI6ODE5MiwiY2xhdWRlLW9wdXMtNC0xLTIwMjUwODA1Ijo4MTkyLCJhbnRocm9waWMuY2xhdWRlLW9wdXMtNC0xLTIwMjUwODA1LXYxOjAiOjgxOTIsImNsYXVkZS1vcHVzLTQtMUAyMDI1MDgwNSI6ODE5Mn07ZnVuY3Rpb24gVGUoZSx0KXtyZXR1cm4gdCYmInBhcnNlImluKHQub3V0cHV0X2Zvcm1hdD8/e30pP0FlKGUsdCk6ey4uLmUsY29udGVudDplLmNvbnRlbnQubWFwKGU9PiJ0ZXh0Ij09PWUudHlwZT97Li4uZSxwYXJzZWQ6bnVsbH06ZSkscGFyc2VkX291dHB1dDpudWxsfX1mdW5jdGlvbiBBZShlLHQpe2xldCBzPW51bGw7Y29uc3Qgcj1lLmNvbnRlbnQubWFwKGU9PntpZigidGV4dCI9PT1lLnR5cGUpe2NvbnN0IHI9ZnVuY3Rpb24oZSx0KXtpZigianNvbl9zY2hlbWEiIT09ZS5vdXRwdXRfZm9ybWF0Py50eXBlKXJldHVybiBudWxsO3RyeXtyZXR1cm4icGFyc2UiaW4gZS5vdXRwdXRfZm9ybWF0P2Uub3V0cHV0X2Zvcm1hdC5wYXJzZSh0KTpKU09OLnBhcnNlKHQpfWNhdGNoKGUpe3Rocm93IG5ldyBvKGBGYWlsZWQgdG8gcGFyc2Ugc3RydWN0dXJlZCBvdXRwdXQ6ICR7ZX1gKX19KHQsZS50ZXh0KTtyZXR1cm4gbnVsbD09PXMmJihzPXIpLHsuLi5lLHBhcnNlZDpyfX1yZXR1cm4gZX0pO3JldHVybnsuLi5lLGNvbnRlbnQ6cixwYXJzZWRfb3V0cHV0OnN9fWNvbnN0IENlPWU9PntpZigwPT09ZS5sZW5ndGgpcmV0dXJuIGU7bGV0IHQ9ZVtlLmxlbmd0aC0xXTtzd2l0Y2godC50eXBlKXtjYXNlInNlcGFyYXRvciI6cmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2Nhc2UibnVtYmVyIjpsZXQgcz10LnZhbHVlW3QudmFsdWUubGVuZ3RoLTFdO2lmKCIuIj09PXN8fCItIj09PXMpcmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2Nhc2Uic3RyaW5nIjpsZXQgcj1lW2UubGVuZ3RoLTJdO2lmKCJkZWxpbWl0ZXIiPT09cj8udHlwZSlyZXR1cm4gZT1lLnNsaWNlKDAsZS5sZW5ndGgtMSksQ2UoZSk7aWYoImJyYWNlIj09PXI/LnR5cGUmJiJ7Ij09PXIudmFsdWUpcmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2JyZWFrO2Nhc2UiZGVsaW1pdGVyIjpyZXR1cm4gZT1lLnNsaWNlKDAsZS5sZW5ndGgtMSksQ2UoZSl9cmV0dXJuIGV9LEllPWU9PkpTT04ucGFyc2UoKGU9PntsZXQgdD0iIjtyZXR1cm4gZS5tYXAoZT0+eyJzdHJpbmciPT09ZS50eXBlP3QrPSciJytlLnZhbHVlKyciJzp0Kz1lLnZhbHVlfSksdH0pKChlPT57bGV0IHQ9W107cmV0dXJuIGUubWFwKGU9PnsiYnJhY2UiPT09ZS50eXBlJiYoInsiPT09ZS52YWx1ZT90LnB1c2goIn0iKTp0LnNwbGljZSh0Lmxhc3RJbmRleE9mKCJ9IiksMSkpLCJwYXJlbiI9PT1lLnR5cGUmJigiWyI9PT1lLnZhbHVlP3QucHVzaCgiXSIpOnQuc3BsaWNlKHQubGFzdEluZGV4T2YoIl0iKSwxKSl9KSx0Lmxlbmd0aD4wJiZ0LnJldmVyc2UoKS5tYXAodD0+eyJ9Ij09PXQ/ZS5wdXNoKHt0eXBlOiJicmFjZSIsdmFsdWU6In0ifSk6Il0iPT09dCYmZS5wdXNoKHt0eXBlOiJwYXJlbiIsdmFsdWU6Il0ifSl9KSxlfSkoQ2UoKGU9PntsZXQgdD0wLHM9W107Zm9yKDt0PGUubGVuZ3RoOyl7bGV0IHI9ZVt0XTtpZigiXFwiPT09cil7dCsrO2NvbnRpbnVlfWlmKCJ7Ij09PXIpe3MucHVzaCh7dHlwZToiYnJhY2UiLHZhbHVlOiJ7In0pLHQrKztjb250aW51ZX1pZigifSI9PT1yKXtzLnB1c2goe3R5cGU6ImJyYWNlIix2YWx1ZToifSJ9KSx0Kys7Y29udGludWV9aWYoIlsiPT09cil7cy5wdXNoKHt0eXBlOiJwYXJlbiIsdmFsdWU6IlsifSksdCsrO2NvbnRpbnVlfWlmKCJdIj09PXIpe3MucHVzaCh7dHlwZToicGFyZW4iLHZhbHVlOiJdIn0pLHQrKztjb250aW51ZX1pZigiOiI9PT1yKXtzLnB1c2goe3R5cGU6InNlcGFyYXRvciIsdmFsdWU6IjoifSksdCsrO2NvbnRpbnVlfWlmKCIsIj09PXIpe3MucHVzaCh7dHlwZToiZGVsaW1pdGVyIix2YWx1ZToiLCJ9KSx0Kys7Y29udGludWV9aWYoJyInPT09cil7bGV0IG49IiIsYT0hMTtmb3Iocj1lWysrdF07JyInIT09cjspe2lmKHQ9PT1lLmxlbmd0aCl7YT0hMDticmVha31pZigiXFwiPT09cil7aWYodCsrLHQ9PT1lLmxlbmd0aCl7YT0hMDticmVha31uKz1yK2VbdF0scj1lWysrdF19ZWxzZSBuKz1yLHI9ZVsrK3RdfXI9ZVsrK3RdLGF8fHMucHVzaCh7dHlwZToic3RyaW5nIix2YWx1ZTpufSk7Y29udGludWV9aWYociYmL1xzLy50ZXN0KHIpKXt0Kys7Y29udGludWV9bGV0IG49L1swLTldLztpZihyJiZuLnRlc3Qocil8fCItIj09PXJ8fCIuIj09PXIpe2xldCBhPSIiO2ZvcigiLSI9PT1yJiYoYSs9cixyPWVbKyt0XSk7ciYmbi50ZXN0KHIpfHwiLiI9PT1yOylhKz1yLHI9ZVsrK3RdO3MucHVzaCh7dHlwZToibnVtYmVyIix2YWx1ZTphfSk7Y29udGludWV9bGV0IGE9L1thLXpdL2k7aWYociYmYS50ZXN0KHIpKXtsZXQgbj0iIjtmb3IoO3ImJmEudGVzdChyKSYmdCE9PWUubGVuZ3RoOyluKz1yLHI9ZVsrK3RdO2lmKCJ0cnVlIiE9biYmImZhbHNlIiE9biYmIm51bGwiIT09bil7dCsrO2NvbnRpbnVlfXMucHVzaCh7dHlwZToibmFtZSIsdmFsdWU6bn0pO2NvbnRpbnVlfXQrK31yZXR1cm4gc30pKGUpKSkpKTt2YXIgT2UsJGUsTGUsTmUsRGUsVWUscWUsamUsRmUsV2UsQmUsSmUsemUsSGUsS2UsVmUsWGUsR2UsWWUsUWUsWmUsZXQsdHQ7Y29uc3Qgc3Q9Il9fanNvbl9idWYiO2Z1bmN0aW9uIHJ0KGUpe3JldHVybiJ0b29sX3VzZSI9PT1lLnR5cGV8fCJzZXJ2ZXJfdG9vbF91c2UiPT09ZS50eXBlfHwibWNwX3Rvb2xfdXNlIj09PWUudHlwZX1jbGFzcyBudHtjb25zdHJ1Y3RvcihlKXtPZS5hZGQodGhpcyksdGhpcy5tZXNzYWdlcz1bXSx0aGlzLnJlY2VpdmVkTWVzc2FnZXM9W10sJGUuc2V0KHRoaXMsdm9pZCAwKSxMZS5zZXQodGhpcyxudWxsKSx0aGlzLmNvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcixOZS5zZXQodGhpcyx2b2lkIDApLERlLnNldCh0aGlzLCgpPT57fSksVWUuc2V0KHRoaXMsKCk9Pnt9KSxxZS5zZXQodGhpcyx2b2lkIDApLGplLnNldCh0aGlzLCgpPT57fSksRmUuc2V0KHRoaXMsKCk9Pnt9KSxXZS5zZXQodGhpcyx7fSksQmUuc2V0KHRoaXMsITEpLEplLnNldCh0aGlzLCExKSx6ZS5zZXQodGhpcywhMSksSGUuc2V0KHRoaXMsITEpLEtlLnNldCh0aGlzLHZvaWQgMCksVmUuc2V0KHRoaXMsdm9pZCAwKSxZZS5zZXQodGhpcyxlPT57aWYodCh0aGlzLEplLCEwLCJmIiksbihlKSYmKGU9bmV3IGMpLGUgaW5zdGFuY2VvZiBjKXJldHVybiB0KHRoaXMsemUsITAsImYiKSx0aGlzLl9lbWl0KCJhYm9ydCIsZSk7aWYoZSBpbnN0YW5jZW9mIG8pcmV0dXJuIHRoaXMuX2VtaXQoImVycm9yIixlKTtpZihlIGluc3RhbmNlb2YgRXJyb3Ipe2NvbnN0IHQ9bmV3IG8oZS5tZXNzYWdlKTtyZXR1cm4gdC5jYXVzZT1lLHRoaXMuX2VtaXQoImVycm9yIix0KX1yZXR1cm4gdGhpcy5fZW1pdCgiZXJyb3IiLG5ldyBvKFN0cmluZyhlKSkpfSksdCh0aGlzLE5lLG5ldyBQcm9taXNlKChlLHMpPT57dCh0aGlzLERlLGUsImYiKSx0KHRoaXMsVWUscywiZiIpfSksImYiKSx0KHRoaXMscWUsbmV3IFByb21pc2UoKGUscyk9Pnt0KHRoaXMsamUsZSwiZiIpLHQodGhpcyxGZSxzLCJmIil9KSwiZiIpLHModGhpcyxOZSwiZiIpLmNhdGNoKCgpPT57fSkscyh0aGlzLHFlLCJmIikuY2F0Y2goKCk9Pnt9KSx0KHRoaXMsTGUsZSwiZiIpfWdldCByZXNwb25zZSgpe3JldHVybiBzKHRoaXMsS2UsImYiKX1nZXQgcmVxdWVzdF9pZCgpe3JldHVybiBzKHRoaXMsVmUsImYiKX1hc3luYyB3aXRoUmVzcG9uc2UoKXtjb25zdCBlPWF3YWl0IHModGhpcyxOZSwiZiIpO2lmKCFlKXRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IHJlc29sdmUgYSBgUmVzcG9uc2VgIG9iamVjdCIpO3JldHVybntkYXRhOnRoaXMscmVzcG9uc2U6ZSxyZXF1ZXN0X2lkOmUuaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKX19c3RhdGljIGZyb21SZWFkYWJsZVN0cmVhbShlKXtjb25zdCB0PW5ldyBudChudWxsKTtyZXR1cm4gdC5fcnVuKCgpPT50Ll9mcm9tUmVhZGFibGVTdHJlYW0oZSkpLHR9c3RhdGljIGNyZWF0ZU1lc3NhZ2UoZSxzLHIpe2NvbnN0IG49bmV3IG50KHMpO2Zvcihjb25zdCBlIG9mIHMubWVzc2FnZXMpbi5fYWRkTWVzc2FnZVBhcmFtKGUpO3JldHVybiB0KG4sTGUsey4uLnMsc3RyZWFtOiEwfSwiZiIpLG4uX3J1bigoKT0+bi5fY3JlYXRlTWVzc2FnZShlLHsuLi5zLHN0cmVhbTohMH0sey4uLnIsaGVhZGVyczp7Li4ucj8uaGVhZGVycywiWC1TdGFpbmxlc3MtSGVscGVyLU1ldGhvZCI6InN0cmVhbSJ9fSkpLG59X3J1bihlKXtlKCkudGhlbigoKT0+e3RoaXMuX2VtaXRGaW5hbCgpLHRoaXMuX2VtaXQoImVuZCIpfSxzKHRoaXMsWWUsImYiKSl9X2FkZE1lc3NhZ2VQYXJhbShlKXt0aGlzLm1lc3NhZ2VzLnB1c2goZSl9X2FkZE1lc3NhZ2UoZSx0PSEwKXt0aGlzLnJlY2VpdmVkTWVzc2FnZXMucHVzaChlKSx0JiZ0aGlzLl9lbWl0KCJtZXNzYWdlIixlKX1hc3luYyBfY3JlYXRlTWVzc2FnZShlLHQscil7Y29uc3Qgbj1yPy5zaWduYWw7bGV0IGE7biYmKG4uYWJvcnRlZCYmdGhpcy5jb250cm9sbGVyLmFib3J0KCksYT10aGlzLmNvbnRyb2xsZXIuYWJvcnQuYmluZCh0aGlzLmNvbnRyb2xsZXIpLG4uYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLGEpKTt0cnl7cyh0aGlzLE9lLCJtIixRZSkuY2FsbCh0aGlzKTtjb25zdHtyZXNwb25zZTpuLGRhdGE6YX09YXdhaXQgZS5jcmVhdGUoey4uLnQsc3RyZWFtOiEwfSx7Li4ucixzaWduYWw6dGhpcy5jb250cm9sbGVyLnNpZ25hbH0pLndpdGhSZXNwb25zZSgpO3RoaXMuX2Nvbm5lY3RlZChuKTtmb3IgYXdhaXQoY29uc3QgZSBvZiBhKXModGhpcyxPZSwibSIsWmUpLmNhbGwodGhpcyxlKTtpZihhLmNvbnRyb2xsZXIuc2lnbmFsPy5hYm9ydGVkKXRocm93IG5ldyBjO3ModGhpcyxPZSwibSIsZXQpLmNhbGwodGhpcyl9ZmluYWxseXtuJiZhJiZuLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0IixhKX19X2Nvbm5lY3RlZChlKXt0aGlzLmVuZGVkfHwodCh0aGlzLEtlLGUsImYiKSx0KHRoaXMsVmUsZT8uaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKSwiZiIpLHModGhpcyxEZSwiZiIpLmNhbGwodGhpcyxlKSx0aGlzLl9lbWl0KCJjb25uZWN0IikpfWdldCBlbmRlZCgpe3JldHVybiBzKHRoaXMsQmUsImYiKX1nZXQgZXJyb3JlZCgpe3JldHVybiBzKHRoaXMsSmUsImYiKX1nZXQgYWJvcnRlZCgpe3JldHVybiBzKHRoaXMsemUsImYiKX1hYm9ydCgpe3RoaXMuY29udHJvbGxlci5hYm9ydCgpfW9uKGUsdCl7cmV0dXJuKHModGhpcyxXZSwiZiIpW2VdfHwocyh0aGlzLFdlLCJmIilbZV09W10pKS5wdXNoKHtsaXN0ZW5lcjp0fSksdGhpc31vZmYoZSx0KXtjb25zdCByPXModGhpcyxXZSwiZiIpW2VdO2lmKCFyKXJldHVybiB0aGlzO2NvbnN0IG49ci5maW5kSW5kZXgoZT0+ZS5saXN0ZW5lcj09PXQpO3JldHVybiBuPj0wJiZyLnNwbGljZShuLDEpLHRoaXN9b25jZShlLHQpe3JldHVybihzKHRoaXMsV2UsImYiKVtlXXx8KHModGhpcyxXZSwiZiIpW2VdPVtdKSkucHVzaCh7bGlzdGVuZXI6dCxvbmNlOiEwfSksdGhpc31lbWl0dGVkKGUpe3JldHVybiBuZXcgUHJvbWlzZSgocyxyKT0+e3QodGhpcyxIZSwhMCwiZiIpLCJlcnJvciIhPT1lJiZ0aGlzLm9uY2UoImVycm9yIixyKSx0aGlzLm9uY2UoZSxzKX0pfWFzeW5jIGRvbmUoKXt0KHRoaXMsSGUsITAsImYiKSxhd2FpdCBzKHRoaXMscWUsImYiKX1nZXQgY3VycmVudE1lc3NhZ2UoKXtyZXR1cm4gcyh0aGlzLCRlLCJmIil9YXN5bmMgZmluYWxNZXNzYWdlKCl7cmV0dXJuIGF3YWl0IHRoaXMuZG9uZSgpLHModGhpcyxPZSwibSIsWGUpLmNhbGwodGhpcyl9YXN5bmMgZmluYWxUZXh0KCl7cmV0dXJuIGF3YWl0IHRoaXMuZG9uZSgpLHModGhpcyxPZSwibSIsR2UpLmNhbGwodGhpcyl9X2VtaXQoZSwuLi5yKXtpZihzKHRoaXMsQmUsImYiKSlyZXR1cm47ImVuZCI9PT1lJiYodCh0aGlzLEJlLCEwLCJmIikscyh0aGlzLGplLCJmIikuY2FsbCh0aGlzKSk7Y29uc3Qgbj1zKHRoaXMsV2UsImYiKVtlXTtpZihuJiYocyh0aGlzLFdlLCJmIilbZV09bi5maWx0ZXIoZT0+IWUub25jZSksbi5mb3JFYWNoKCh7bGlzdGVuZXI6ZX0pPT5lKC4uLnIpKSksImFib3J0Ij09PWUpe2NvbnN0IGU9clswXTtyZXR1cm4gcyh0aGlzLEhlLCJmIil8fG4/Lmxlbmd0aHx8UHJvbWlzZS5yZWplY3QoZSkscyh0aGlzLFVlLCJmIikuY2FsbCh0aGlzLGUpLHModGhpcyxGZSwiZiIpLmNhbGwodGhpcyxlKSx2b2lkIHRoaXMuX2VtaXQoImVuZCIpfWlmKCJlcnJvciI9PT1lKXtjb25zdCBlPXJbMF07cyh0aGlzLEhlLCJmIil8fG4/Lmxlbmd0aHx8UHJvbWlzZS5yZWplY3QoZSkscyh0aGlzLFVlLCJmIikuY2FsbCh0aGlzLGUpLHModGhpcyxGZSwiZiIpLmNhbGwodGhpcyxlKSx0aGlzLl9lbWl0KCJlbmQiKX19X2VtaXRGaW5hbCgpe3RoaXMucmVjZWl2ZWRNZXNzYWdlcy5hdCgtMSkmJnRoaXMuX2VtaXQoImZpbmFsTWVzc2FnZSIscyh0aGlzLE9lLCJtIixYZSkuY2FsbCh0aGlzKSl9YXN5bmMgX2Zyb21SZWFkYWJsZVN0cmVhbShlLHQpe2NvbnN0IHI9dD8uc2lnbmFsO2xldCBuO3ImJihyLmFib3J0ZWQmJnRoaXMuY29udHJvbGxlci5hYm9ydCgpLG49dGhpcy5jb250cm9sbGVyLmFib3J0LmJpbmQodGhpcy5jb250cm9sbGVyKSxyLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IixuKSk7dHJ5e3ModGhpcyxPZSwibSIsUWUpLmNhbGwodGhpcyksdGhpcy5fY29ubmVjdGVkKG51bGwpO2NvbnN0IHQ9Wi5mcm9tUmVhZGFibGVTdHJlYW0oZSx0aGlzLmNvbnRyb2xsZXIpO2ZvciBhd2FpdChjb25zdCBlIG9mIHQpcyh0aGlzLE9lLCJtIixaZSkuY2FsbCh0aGlzLGUpO2lmKHQuY29udHJvbGxlci5zaWduYWw/LmFib3J0ZWQpdGhyb3cgbmV3IGM7cyh0aGlzLE9lLCJtIixldCkuY2FsbCh0aGlzKX1maW5hbGx5e3ImJm4mJnIucmVtb3ZlRXZlbnRMaXN0ZW5lcigiYWJvcnQiLG4pfX1bKCRlPW5ldyBXZWFrTWFwLExlPW5ldyBXZWFrTWFwLE5lPW5ldyBXZWFrTWFwLERlPW5ldyBXZWFrTWFwLFVlPW5ldyBXZWFrTWFwLHFlPW5ldyBXZWFrTWFwLGplPW5ldyBXZWFrTWFwLEZlPW5ldyBXZWFrTWFwLFdlPW5ldyBXZWFrTWFwLEJlPW5ldyBXZWFrTWFwLEplPW5ldyBXZWFrTWFwLHplPW5ldyBXZWFrTWFwLEhlPW5ldyBXZWFrTWFwLEtlPW5ldyBXZWFrTWFwLFZlPW5ldyBXZWFrTWFwLFllPW5ldyBXZWFrTWFwLE9lPW5ldyBXZWFrU2V0LFhlPWZ1bmN0aW9uKCl7aWYoMD09PXRoaXMucmVjZWl2ZWRNZXNzYWdlcy5sZW5ndGgpdGhyb3cgbmV3IG8oInN0cmVhbSBlbmRlZCB3aXRob3V0IHByb2R1Y2luZyBhIE1lc3NhZ2Ugd2l0aCByb2xlPWFzc2lzdGFudCIpO3JldHVybiB0aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpfSxHZT1mdW5jdGlvbigpe2lmKDA9PT10aGlzLnJlY2VpdmVkTWVzc2FnZXMubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBNZXNzYWdlIHdpdGggcm9sZT1hc3Npc3RhbnQiKTtjb25zdCBlPXRoaXMucmVjZWl2ZWRNZXNzYWdlcy5hdCgtMSkuY29udGVudC5maWx0ZXIoZT0+InRleHQiPT09ZS50eXBlKS5tYXAoZT0+ZS50ZXh0KTtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IG8oInN0cmVhbSBlbmRlZCB3aXRob3V0IHByb2R1Y2luZyBhIGNvbnRlbnQgYmxvY2sgd2l0aCB0eXBlPXRleHQiKTtyZXR1cm4gZS5qb2luKCIgIil9LFFlPWZ1bmN0aW9uKCl7dGhpcy5lbmRlZHx8dCh0aGlzLCRlLHZvaWQgMCwiZiIpfSxaZT1mdW5jdGlvbihlKXtpZih0aGlzLmVuZGVkKXJldHVybjtjb25zdCByPXModGhpcyxPZSwibSIsdHQpLmNhbGwodGhpcyxlKTtzd2l0Y2godGhpcy5fZW1pdCgic3RyZWFtRXZlbnQiLGUsciksZS50eXBlKXtjYXNlImNvbnRlbnRfYmxvY2tfZGVsdGEiOntjb25zdCB0PXIuY29udGVudC5hdCgtMSk7c3dpdGNoKGUuZGVsdGEudHlwZSl7Y2FzZSJ0ZXh0X2RlbHRhIjoidGV4dCI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInRleHQiLGUuZGVsdGEudGV4dCx0LnRleHR8fCIiKTticmVhaztjYXNlImNpdGF0aW9uc19kZWx0YSI6InRleHQiPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJjaXRhdGlvbiIsZS5kZWx0YS5jaXRhdGlvbix0LmNpdGF0aW9ucz8/W10pO2JyZWFrO2Nhc2UiaW5wdXRfanNvbl9kZWx0YSI6cnQodCkmJnQuaW5wdXQmJnRoaXMuX2VtaXQoImlucHV0SnNvbiIsZS5kZWx0YS5wYXJ0aWFsX2pzb24sdC5pbnB1dCk7YnJlYWs7Y2FzZSJ0aGlua2luZ19kZWx0YSI6InRoaW5raW5nIj09PXQudHlwZSYmdGhpcy5fZW1pdCgidGhpbmtpbmciLGUuZGVsdGEudGhpbmtpbmcsdC50aGlua2luZyk7YnJlYWs7Y2FzZSJzaWduYXR1cmVfZGVsdGEiOiJ0aGlua2luZyI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInNpZ25hdHVyZSIsdC5zaWduYXR1cmUpO2JyZWFrO2RlZmF1bHQ6ZS5kZWx0YX1icmVha31jYXNlIm1lc3NhZ2Vfc3RvcCI6dGhpcy5fYWRkTWVzc2FnZVBhcmFtKHIpLHRoaXMuX2FkZE1lc3NhZ2UoVGUocixzKHRoaXMsTGUsImYiKSksITApO2JyZWFrO2Nhc2UiY29udGVudF9ibG9ja19zdG9wIjp0aGlzLl9lbWl0KCJjb250ZW50QmxvY2siLHIuY29udGVudC5hdCgtMSkpO2JyZWFrO2Nhc2UibWVzc2FnZV9zdGFydCI6dCh0aGlzLCRlLHIsImYiKX19LGV0PWZ1bmN0aW9uKCl7aWYodGhpcy5lbmRlZCl0aHJvdyBuZXcgbygic3RyZWFtIGhhcyBlbmRlZCwgdGhpcyBzaG91bGRuJ3QgaGFwcGVuIik7Y29uc3QgZT1zKHRoaXMsJGUsImYiKTtpZighZSl0aHJvdyBuZXcgbygicmVxdWVzdCBlbmRlZCB3aXRob3V0IHNlbmRpbmcgYW55IGNodW5rcyIpO3JldHVybiB0KHRoaXMsJGUsdm9pZCAwLCJmIiksVGUoZSxzKHRoaXMsTGUsImYiKSl9LHR0PWZ1bmN0aW9uKGUpe2xldCB0PXModGhpcywkZSwiZiIpO2lmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSl7aWYodCl0aHJvdyBuZXcgbyhgVW5leHBlY3RlZCBldmVudCBvcmRlciwgZ290ICR7ZS50eXBlfSBiZWZvcmUgcmVjZWl2aW5nICJtZXNzYWdlX3N0b3AiYCk7cmV0dXJuIGUubWVzc2FnZX1pZighdCl0aHJvdyBuZXcgbyhgVW5leHBlY3RlZCBldmVudCBvcmRlciwgZ290ICR7ZS50eXBlfSBiZWZvcmUgIm1lc3NhZ2Vfc3RhcnQiYCk7c3dpdGNoKGUudHlwZSl7Y2FzZSJtZXNzYWdlX3N0b3AiOmNhc2UiY29udGVudF9ibG9ja19zdG9wIjpyZXR1cm4gdDtjYXNlIm1lc3NhZ2VfZGVsdGEiOnJldHVybiB0LmNvbnRhaW5lcj1lLmRlbHRhLmNvbnRhaW5lcix0LnN0b3BfcmVhc29uPWUuZGVsdGEuc3RvcF9yZWFzb24sdC5zdG9wX3NlcXVlbmNlPWUuZGVsdGEuc3RvcF9zZXF1ZW5jZSx0LnVzYWdlLm91dHB1dF90b2tlbnM9ZS51c2FnZS5vdXRwdXRfdG9rZW5zLHQuY29udGV4dF9tYW5hZ2VtZW50PWUuY29udGV4dF9tYW5hZ2VtZW50LG51bGwhPWUudXNhZ2UuaW5wdXRfdG9rZW5zJiYodC51c2FnZS5pbnB1dF90b2tlbnM9ZS51c2FnZS5pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2UuY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zJiYodC51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnM9ZS51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMmJih0LnVzYWdlLmNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zPWUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2Uuc2VydmVyX3Rvb2xfdXNlJiYodC51c2FnZS5zZXJ2ZXJfdG9vbF91c2U9ZS51c2FnZS5zZXJ2ZXJfdG9vbF91c2UpLHQ7Y2FzZSJjb250ZW50X2Jsb2NrX3N0YXJ0IjpyZXR1cm4gdC5jb250ZW50LnB1c2goZS5jb250ZW50X2Jsb2NrKSx0O2Nhc2UiY29udGVudF9ibG9ja19kZWx0YSI6e2NvbnN0IHI9dC5jb250ZW50LmF0KGUuaW5kZXgpO3N3aXRjaChlLmRlbHRhLnR5cGUpe2Nhc2UidGV4dF9kZWx0YSI6InRleHQiPT09cj8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucix0ZXh0OihyLnRleHR8fCIiKStlLmRlbHRhLnRleHR9KTticmVhaztjYXNlImNpdGF0aW9uc19kZWx0YSI6InRleHQiPT09cj8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucixjaXRhdGlvbnM6Wy4uLnIuY2l0YXRpb25zPz9bXSxlLmRlbHRhLmNpdGF0aW9uXX0pO2JyZWFrO2Nhc2UiaW5wdXRfanNvbl9kZWx0YSI6aWYociYmcnQocikpe2xldCBuPXJbc3RdfHwiIjtuKz1lLmRlbHRhLnBhcnRpYWxfanNvbjtjb25zdCBhPXsuLi5yfTtpZihPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxzdCx7dmFsdWU6bixlbnVtZXJhYmxlOiExLHdyaXRhYmxlOiEwfSksbil0cnl7YS5pbnB1dD1JZShuKX1jYXRjaChlKXtjb25zdCB0PW5ldyBvKGBVbmFibGUgdG8gcGFyc2UgdG9vbCBwYXJhbWV0ZXIgSlNPTiBmcm9tIG1vZGVsLiBQbGVhc2UgcmV0cnkgeW91ciByZXF1ZXN0IG9yIGFkanVzdCB5b3VyIHByb21wdC4gRXJyb3I6ICR7ZX0uIEpTT046ICR7bn1gKTtzKHRoaXMsWWUsImYiKS5jYWxsKHRoaXMsdCl9dC5jb250ZW50W2UuaW5kZXhdPWF9YnJlYWs7Y2FzZSJ0aGlua2luZ19kZWx0YSI6InRoaW5raW5nIj09PXI/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnIsdGhpbmtpbmc6ci50aGlua2luZytlLmRlbHRhLnRoaW5raW5nfSk7YnJlYWs7Y2FzZSJzaWduYXR1cmVfZGVsdGEiOiJ0aGlua2luZyI9PT1yPy50eXBlJiYodC5jb250ZW50W2UuaW5kZXhdPXsuLi5yLHNpZ25hdHVyZTplLmRlbHRhLnNpZ25hdHVyZX0pO2JyZWFrO2RlZmF1bHQ6ZS5kZWx0YX1yZXR1cm4gdH19fSxTeW1ib2wuYXN5bmNJdGVyYXRvcildKCl7Y29uc3QgZT1bXSx0PVtdO2xldCBzPSExO3JldHVybiB0aGlzLm9uKCJzdHJlYW1FdmVudCIscz0+e2NvbnN0IHI9dC5zaGlmdCgpO3I/ci5yZXNvbHZlKHMpOmUucHVzaChzKX0pLHRoaXMub24oImVuZCIsKCk9PntzPSEwO2Zvcihjb25zdCBlIG9mIHQpZS5yZXNvbHZlKHZvaWQgMCk7dC5sZW5ndGg9MH0pLHRoaXMub24oImFib3J0IixlPT57cz0hMDtmb3IoY29uc3QgcyBvZiB0KXMucmVqZWN0KGUpO3QubGVuZ3RoPTB9KSx0aGlzLm9uKCJlcnJvciIsZT0+e3M9ITA7Zm9yKGNvbnN0IHMgb2YgdClzLnJlamVjdChlKTt0Lmxlbmd0aD0wfSkse25leHQ6YXN5bmMoKT0+ZS5sZW5ndGg/e3ZhbHVlOmUuc2hpZnQoKSxkb25lOiExfTpzP3t2YWx1ZTp2b2lkIDAsZG9uZTohMH06bmV3IFByb21pc2UoKGUscyk9PnQucHVzaCh7cmVzb2x2ZTplLHJlamVjdDpzfSkpLnRoZW4oZT0+ZT97dmFsdWU6ZSxkb25lOiExfTp7dmFsdWU6dm9pZCAwLGRvbmU6ITB9KSxyZXR1cm46YXN5bmMoKT0+KHRoaXMuYWJvcnQoKSx7dmFsdWU6dm9pZCAwLGRvbmU6ITB9KX19dG9SZWFkYWJsZVN0cmVhbSgpe3JldHVybiBuZXcgWih0aGlzW1N5bWJvbC5hc3luY0l0ZXJhdG9yXS5iaW5kKHRoaXMpLHRoaXMuY29udHJvbGxlcikudG9SZWFkYWJsZVN0cmVhbSgpfX12YXIgYXQsb3QsaXQsY3QsbHQsZHQsaHQsdXQscHQsZnQsbXQ7ZnVuY3Rpb24gZ3QoKXtsZXQgZSx0O3JldHVybntwcm9taXNlOm5ldyBQcm9taXNlKChzLHIpPT57ZT1zLHQ9cn0pLHJlc29sdmU6ZSxyZWplY3Q6dH19Y2xhc3Mgd3R7Y29uc3RydWN0b3IoZSxzLHIpe2F0LmFkZCh0aGlzKSx0aGlzLmNsaWVudD1lLG90LnNldCh0aGlzLCExKSxpdC5zZXQodGhpcywhMSksY3Quc2V0KHRoaXMsdm9pZCAwKSxsdC5zZXQodGhpcyx2b2lkIDApLGR0LnNldCh0aGlzLHZvaWQgMCksaHQuc2V0KHRoaXMsdm9pZCAwKSx1dC5zZXQodGhpcyx2b2lkIDApLHB0LnNldCh0aGlzLDApLHQodGhpcyxjdCx7cGFyYW1zOnsuLi5zLG1lc3NhZ2VzOnN0cnVjdHVyZWRDbG9uZShzLm1lc3NhZ2VzKX19LCJmIiksdCh0aGlzLGx0LHsuLi5yLGhlYWRlcnM6X2UoW3sieC1zdGFpbmxlc3MtaGVscGVyIjoiQmV0YVRvb2xSdW5uZXIifSxyPy5oZWFkZXJzXSl9LCJmIiksdCh0aGlzLHV0LGd0KCksImYiKX1hc3luYypbKG90PW5ldyBXZWFrTWFwLGl0PW5ldyBXZWFrTWFwLGN0PW5ldyBXZWFrTWFwLGx0PW5ldyBXZWFrTWFwLGR0PW5ldyBXZWFrTWFwLGh0PW5ldyBXZWFrTWFwLHV0PW5ldyBXZWFrTWFwLHB0PW5ldyBXZWFrTWFwLGF0PW5ldyBXZWFrU2V0LGZ0PWFzeW5jIGZ1bmN0aW9uKCl7Y29uc3QgZT1zKHRoaXMsY3QsImYiKS5wYXJhbXMuY29tcGFjdGlvbkNvbnRyb2w7aWYoIWV8fCFlLmVuYWJsZWQpcmV0dXJuITE7bGV0IHQ9MDtpZih2b2lkIDAhPT1zKHRoaXMsZHQsImYiKSl0cnl7Y29uc3QgZT1hd2FpdCBzKHRoaXMsZHQsImYiKTt0PWUudXNhZ2UuaW5wdXRfdG9rZW5zKyhlLnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2Vucz8/MCkrKGUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM/PzApK2UudXNhZ2Uub3V0cHV0X3Rva2Vuc31jYXRjaHtyZXR1cm4hMX1pZih0PChlLmNvbnRleHRUb2tlblRocmVzaG9sZD8/MWU1KSlyZXR1cm4hMTtjb25zdCByPWUubW9kZWw/P3ModGhpcyxjdCwiZiIpLnBhcmFtcy5tb2RlbCxuPWUuc3VtbWFyeVByb21wdD8/IllvdSBoYXZlIGJlZW4gd29ya2luZyBvbiB0aGUgdGFzayBkZXNjcmliZWQgYWJvdmUgYnV0IGhhdmUgbm90IHlldCBjb21wbGV0ZWQgaXQuIFdyaXRlIGEgY29udGludWF0aW9uIHN1bW1hcnkgdGhhdCB3aWxsIGFsbG93IHlvdSAob3IgYW5vdGhlciBpbnN0YW5jZSBvZiB5b3Vyc2VsZikgdG8gcmVzdW1lIHdvcmsgZWZmaWNpZW50bHkgaW4gYSBmdXR1cmUgY29udGV4dCB3aW5kb3cgd2hlcmUgdGhlIGNvbnZlcnNhdGlvbiBoaXN0b3J5IHdpbGwgYmUgcmVwbGFjZWQgd2l0aCB0aGlzIHN1bW1hcnkuIFlvdXIgc3VtbWFyeSBzaG91bGQgYmUgc3RydWN0dXJlZCwgY29uY2lzZSwgYW5kIGFjdGlvbmFibGUuIEluY2x1ZGU6XG4xLiBUYXNrIE92ZXJ2aWV3XG5UaGUgdXNlcidzIGNvcmUgcmVxdWVzdCBhbmQgc3VjY2VzcyBjcml0ZXJpYVxuQW55IGNsYXJpZmljYXRpb25zIG9yIGNvbnN0cmFpbnRzIHRoZXkgc3BlY2lmaWVkXG4yLiBDdXJyZW50IFN0YXRlXG5XaGF0IGhhcyBiZWVuIGNvbXBsZXRlZCBzbyBmYXJcbkZpbGVzIGNyZWF0ZWQsIG1vZGlmaWVkLCBvciBhbmFseXplZCAod2l0aCBwYXRocyBpZiByZWxldmFudClcbktleSBvdXRwdXRzIG9yIGFydGlmYWN0cyBwcm9kdWNlZFxuMy4gSW1wb3J0YW50IERpc2NvdmVyaWVzXG5UZWNobmljYWwgY29uc3RyYWludHMgb3IgcmVxdWlyZW1lbnRzIHVuY292ZXJlZFxuRGVjaXNpb25zIG1hZGUgYW5kIHRoZWlyIHJhdGlvbmFsZVxuRXJyb3JzIGVuY291bnRlcmVkIGFuZCBob3cgdGhleSB3ZXJlIHJlc29sdmVkXG5XaGF0IGFwcHJvYWNoZXMgd2VyZSB0cmllZCB0aGF0IGRpZG4ndCB3b3JrIChhbmQgd2h5KVxuNC4gTmV4dCBTdGVwc1xuU3BlY2lmaWMgYWN0aW9ucyBuZWVkZWQgdG8gY29tcGxldGUgdGhlIHRhc2tcbkFueSBibG9ja2VycyBvciBvcGVuIHF1ZXN0aW9ucyB0byByZXNvbHZlXG5Qcmlvcml0eSBvcmRlciBpZiBtdWx0aXBsZSBzdGVwcyByZW1haW5cbjUuIENvbnRleHQgdG8gUHJlc2VydmVcblVzZXIgcHJlZmVyZW5jZXMgb3Igc3R5bGUgcmVxdWlyZW1lbnRzXG5Eb21haW4tc3BlY2lmaWMgZGV0YWlscyB0aGF0IGFyZW4ndCBvYnZpb3VzXG5BbnkgcHJvbWlzZXMgbWFkZSB0byB0aGUgdXNlclxuQmUgY29uY2lzZSBidXQgY29tcGxldGXigJRlcnIgb24gdGhlIHNpZGUgb2YgaW5jbHVkaW5nIGluZm9ybWF0aW9uIHRoYXQgd291bGQgcHJldmVudCBkdXBsaWNhdGUgd29yayBvciByZXBlYXRlZCBtaXN0YWtlcy4gV3JpdGUgaW4gYSB3YXkgdGhhdCBlbmFibGVzIGltbWVkaWF0ZSByZXN1bXB0aW9uIG9mIHRoZSB0YXNrLlxuV3JhcCB5b3VyIHN1bW1hcnkgaW4gPHN1bW1hcnk+PC9zdW1tYXJ5PiB0YWdzLiIsYT1zKHRoaXMsY3QsImYiKS5wYXJhbXMubWVzc2FnZXM7aWYoImFzc2lzdGFudCI9PT1hW2EubGVuZ3RoLTFdLnJvbGUpe2NvbnN0IGU9YVthLmxlbmd0aC0xXTtpZihBcnJheS5pc0FycmF5KGUuY29udGVudCkpe2NvbnN0IHQ9ZS5jb250ZW50LmZpbHRlcihlPT4idG9vbF91c2UiIT09ZS50eXBlKTswPT09dC5sZW5ndGg/YS5wb3AoKTplLmNvbnRlbnQ9dH19Y29uc3QgaT1hd2FpdCB0aGlzLmNsaWVudC5iZXRhLm1lc3NhZ2VzLmNyZWF0ZSh7bW9kZWw6cixtZXNzYWdlczpbLi4uYSx7cm9sZToidXNlciIsY29udGVudDpbe3R5cGU6InRleHQiLHRleHQ6bn1dfV0sbWF4X3Rva2VuczpzKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X3Rva2Vuc30se2hlYWRlcnM6eyJ4LXN0YWlubGVzcy1oZWxwZXIiOiJjb21wYWN0aW9uIn19KTtpZigidGV4dCIhPT1pLmNvbnRlbnRbMF0/LnR5cGUpdGhyb3cgbmV3IG8oIkV4cGVjdGVkIHRleHQgcmVzcG9uc2UgZm9yIGNvbXBhY3Rpb24iKTtyZXR1cm4gcyh0aGlzLGN0LCJmIikucGFyYW1zLm1lc3NhZ2VzPVt7cm9sZToidXNlciIsY29udGVudDppLmNvbnRlbnR9XSwhMH0sU3ltYm9sLmFzeW5jSXRlcmF0b3IpXSgpe3ZhciBlO2lmKHModGhpcyxvdCwiZiIpKXRocm93IG5ldyBvKCJDYW5ub3QgaXRlcmF0ZSBvdmVyIGEgY29uc3VtZWQgc3RyZWFtIik7dCh0aGlzLG90LCEwLCJmIiksdCh0aGlzLGl0LCEwLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpO3RyeXtmb3IoOzspe2xldCByO3RyeXtpZihzKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X2l0ZXJhdGlvbnMmJnModGhpcyxwdCwiZiIpPj1zKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X2l0ZXJhdGlvbnMpYnJlYWs7dCh0aGlzLGl0LCExLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpLHQodGhpcyxwdCwoZT1zKHRoaXMscHQsImYiKSwrK2UpLCJmIiksdCh0aGlzLGR0LHZvaWQgMCwiZiIpO2NvbnN0e21heF9pdGVyYXRpb25zOm4sY29tcGFjdGlvbkNvbnRyb2w6YSwuLi5vfT1zKHRoaXMsY3QsImYiKS5wYXJhbXM7aWYoby5zdHJlYW0/KHI9dGhpcy5jbGllbnQuYmV0YS5tZXNzYWdlcy5zdHJlYW0oey4uLm99LHModGhpcyxsdCwiZiIpKSx0KHRoaXMsZHQsci5maW5hbE1lc3NhZ2UoKSwiZiIpLHModGhpcyxkdCwiZiIpLmNhdGNoKCgpPT57fSkseWllbGQgcik6KHQodGhpcyxkdCx0aGlzLmNsaWVudC5iZXRhLm1lc3NhZ2VzLmNyZWF0ZSh7Li4ubyxzdHJlYW06ITF9LHModGhpcyxsdCwiZiIpKSwiZiIpLHlpZWxkIHModGhpcyxkdCwiZiIpKSwhYXdhaXQgcyh0aGlzLGF0LCJtIixmdCkuY2FsbCh0aGlzKSl7aWYoIXModGhpcyxpdCwiZiIpKXtjb25zdHtyb2xlOmUsY29udGVudDp0fT1hd2FpdCBzKHRoaXMsZHQsImYiKTtzKHRoaXMsY3QsImYiKS5wYXJhbXMubWVzc2FnZXMucHVzaCh7cm9sZTplLGNvbnRlbnQ6dH0pfWNvbnN0IGU9YXdhaXQgcyh0aGlzLGF0LCJtIixtdCkuY2FsbCh0aGlzLHModGhpcyxjdCwiZiIpLnBhcmFtcy5tZXNzYWdlcy5hdCgtMSkpO2lmKGUpcyh0aGlzLGN0LCJmIikucGFyYW1zLm1lc3NhZ2VzLnB1c2goZSk7ZWxzZSBpZighcyh0aGlzLGl0LCJmIikpYnJlYWt9fWZpbmFsbHl7ciYmci5hYm9ydCgpfX1pZighcyh0aGlzLGR0LCJmIikpdGhyb3cgbmV3IG8oIlRvb2xSdW5uZXIgY29uY2x1ZGVkIHdpdGhvdXQgYSBtZXNzYWdlIGZyb20gdGhlIHNlcnZlciIpO3ModGhpcyx1dCwiZiIpLnJlc29sdmUoYXdhaXQgcyh0aGlzLGR0LCJmIikpfWNhdGNoKGUpe3Rocm93IHQodGhpcyxvdCwhMSwiZiIpLHModGhpcyx1dCwiZiIpLnByb21pc2UuY2F0Y2goKCk9Pnt9KSxzKHRoaXMsdXQsImYiKS5yZWplY3QoZSksdCh0aGlzLHV0LGd0KCksImYiKSxlfX1zZXRNZXNzYWdlc1BhcmFtcyhlKXtzKHRoaXMsY3QsImYiKS5wYXJhbXM9ImZ1bmN0aW9uIj09dHlwZW9mIGU/ZShzKHRoaXMsY3QsImYiKS5wYXJhbXMpOmUsdCh0aGlzLGl0LCEwLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpfWFzeW5jIGdlbmVyYXRlVG9vbFJlc3BvbnNlKCl7Y29uc3QgZT1hd2FpdCBzKHRoaXMsZHQsImYiKT8/dGhpcy5wYXJhbXMubWVzc2FnZXMuYXQoLTEpO3JldHVybiBlP3ModGhpcyxhdCwibSIsbXQpLmNhbGwodGhpcyxlKTpudWxsfWRvbmUoKXtyZXR1cm4gcyh0aGlzLHV0LCJmIikucHJvbWlzZX1hc3luYyBydW5VbnRpbERvbmUoKXtpZighcyh0aGlzLG90LCJmIikpZm9yIGF3YWl0KGNvbnN0IGUgb2YgdGhpcyk7cmV0dXJuIHRoaXMuZG9uZSgpfWdldCBwYXJhbXMoKXtyZXR1cm4gcyh0aGlzLGN0LCJmIikucGFyYW1zfXB1c2hNZXNzYWdlcyguLi5lKXt0aGlzLnNldE1lc3NhZ2VzUGFyYW1zKHQ9Pih7Li4udCxtZXNzYWdlczpbLi4udC5tZXNzYWdlcywuLi5lXX0pKX10aGVuKGUsdCl7cmV0dXJuIHRoaXMucnVuVW50aWxEb25lKCkudGhlbihlLHQpfX1tdD1hc3luYyBmdW5jdGlvbihlKXtyZXR1cm4gdm9pZCAwIT09cyh0aGlzLGh0LCJmIil8fHQodGhpcyxodCxhc3luYyBmdW5jdGlvbihlLHQ9ZS5tZXNzYWdlcy5hdCgtMSkpe2lmKCF0fHwiYXNzaXN0YW50IiE9PXQucm9sZXx8IXQuY29udGVudHx8InN0cmluZyI9PXR5cGVvZiB0LmNvbnRlbnQpcmV0dXJuIG51bGw7Y29uc3Qgcz10LmNvbnRlbnQuZmlsdGVyKGU9PiJ0b29sX3VzZSI9PT1lLnR5cGUpO3JldHVybiAwPT09cy5sZW5ndGg/bnVsbDp7cm9sZToidXNlciIsY29udGVudDphd2FpdCBQcm9taXNlLmFsbChzLm1hcChhc3luYyB0PT57Y29uc3Qgcz1lLnRvb2xzLmZpbmQoZT0+KCJuYW1lImluIGU/ZS5uYW1lOmUubWNwX3NlcnZlcl9uYW1lKT09PXQubmFtZSk7aWYoIXN8fCEoInJ1biJpbiBzKSlyZXR1cm57dHlwZToidG9vbF9yZXN1bHQiLHRvb2xfdXNlX2lkOnQuaWQsY29udGVudDpgRXJyb3I6IFRvb2wgJyR7dC5uYW1lfScgbm90IGZvdW5kYCxpc19lcnJvcjohMH07dHJ5e2xldCBlPXQuaW5wdXQ7InBhcnNlImluIHMmJnMucGFyc2UmJihlPXMucGFyc2UoZSkpO2NvbnN0IHI9YXdhaXQgcy5ydW4oZSk7cmV0dXJue3R5cGU6InRvb2xfcmVzdWx0Iix0b29sX3VzZV9pZDp0LmlkLGNvbnRlbnQ6cn19Y2F0Y2goZSl7cmV0dXJue3R5cGU6InRvb2xfcmVzdWx0Iix0b29sX3VzZV9pZDp0LmlkLGNvbnRlbnQ6YEVycm9yOiAke2UgaW5zdGFuY2VvZiBFcnJvcj9lLm1lc3NhZ2U6U3RyaW5nKGUpfWAsaXNfZXJyb3I6ITB9fX0pKX19KHModGhpcyxjdCwiZiIpLnBhcmFtcyxlKSwiZiIpLHModGhpcyxodCwiZiIpfTtjbGFzcyB5dHtjb25zdHJ1Y3RvcihlLHQpe3RoaXMuaXRlcmF0b3I9ZSx0aGlzLmNvbnRyb2xsZXI9dH1hc3luYypkZWNvZGVyKCl7Y29uc3QgZT1uZXcgcTtmb3IgYXdhaXQoY29uc3QgdCBvZiB0aGlzLml0ZXJhdG9yKWZvcihjb25zdCBzIG9mIGUuZGVjb2RlKHQpKXlpZWxkIEpTT04ucGFyc2Uocyk7Zm9yKGNvbnN0IHQgb2YgZS5mbHVzaCgpKXlpZWxkIEpTT04ucGFyc2UodCl9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzLmRlY29kZXIoKX1zdGF0aWMgZnJvbVJlc3BvbnNlKGUsdCl7aWYoIWUuYm9keSl7aWYodC5hYm9ydCgpLHZvaWQgMCE9PWdsb2JhbFRoaXMubmF2aWdhdG9yJiYiUmVhY3ROYXRpdmUiPT09Z2xvYmFsVGhpcy5uYXZpZ2F0b3IucHJvZHVjdCl0aHJvdyBuZXcgbygiVGhlIGRlZmF1bHQgcmVhY3QtbmF0aXZlIGZldGNoIGltcGxlbWVudGF0aW9uIGRvZXMgbm90IHN1cHBvcnQgc3RyZWFtaW5nLiBQbGVhc2UgdXNlIGV4cG8vZmV0Y2g6IGh0dHBzOi8vZG9jcy5leHBvLmRldi92ZXJzaW9ucy9sYXRlc3Qvc2RrL2V4cG8vI2V4cG9mZXRjaC1hcGkiKTt0aHJvdyBuZXcgbygiQXR0ZW1wdGVkIHRvIGl0ZXJhdGUgb3ZlciBhIHJlc3BvbnNlIHdpdGggbm8gYm9keSIpfXJldHVybiBuZXcgeXQoQyhlLmJvZHkpLHQpfX1jbGFzcyBidCBleHRlbmRzIHlle2NyZWF0ZShlLHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9tZXNzYWdlcy9iYXRjaGVzP2JldGE9dHJ1ZSIse2JvZHk6ciwuLi50LGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5zPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX1yZXRyaWV2ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL21lc3NhZ2VzL2JhdGNoZXMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9tZXNzYWdlcy9iYXRjaGVzP2JldGE9dHJ1ZSIsb2Use3F1ZXJ5OnIsLi4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucz8/W10sIm1lc3NhZ2UtYmF0Y2hlcy0yMDI0LTA5LTI0Il0udG9TdHJpbmcoKX0sdD8uaGVhZGVyc10pfSl9ZGVsZXRlKGUsdD17fSxzKXtjb25zdHtiZXRhczpyfT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmRlbGV0ZShQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9P2JldGE9dHJ1ZWAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJtZXNzYWdlLWJhdGNoZXMtMjAyNC0wOS0yNCJdLnRvU3RyaW5nKCl9LHM/LmhlYWRlcnNdKX0pfWNhbmNlbChlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KFBlYC92MS9tZXNzYWdlcy9iYXRjaGVzLyR7ZX0vY2FuY2VsP2JldGE9dHJ1ZWAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJtZXNzYWdlLWJhdGNoZXMtMjAyNC0wOS0yNCJdLnRvU3RyaW5nKCl9LHM/LmhlYWRlcnNdKX0pfWFzeW5jIHJlc3VsdHMoZSx0PXt9LHMpe2NvbnN0IHI9YXdhaXQgdGhpcy5yZXRyaWV2ZShlKTtpZighci5yZXN1bHRzX3VybCl0aHJvdyBuZXcgbyhgTm8gYmF0Y2ggXGByZXN1bHRzX3VybFxgOyBIYXMgaXQgZmluaXNoZWQgcHJvY2Vzc2luZz8gJHtyLnByb2Nlc3Npbmdfc3RhdHVzfSAtICR7ci5pZH1gKTtjb25zdHtiZXRhczpufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChyLnJlc3VsdHNfdXJsLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5uPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpLEFjY2VwdDoiYXBwbGljYXRpb24vYmluYXJ5In0scz8uaGVhZGVyc10pLHN0cmVhbTohMCxfX2JpbmFyeVJlc3BvbnNlOiEwfSkuX3RoZW5VbndyYXAoKGUsdCk9Pnl0LmZyb21SZXNwb25zZSh0LnJlc3BvbnNlLHQuY29udHJvbGxlcikpfX1jb25zdCB2dD17ImNsYXVkZS0xLjMiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtMS4zLTEwMGsiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjEiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjEtMTAwayI6Ik5vdmVtYmVyIDZ0aCwgMjAyNCIsImNsYXVkZS1pbnN0YW50LTEuMiI6Ik5vdmVtYmVyIDZ0aCwgMjAyNCIsImNsYXVkZS0zLXNvbm5ldC0yMDI0MDIyOSI6Ikp1bHkgMjFzdCwgMjAyNSIsImNsYXVkZS0zLW9wdXMtMjAyNDAyMjkiOiJKYW51YXJ5IDV0aCwgMjAyNiIsImNsYXVkZS0yLjEiOiJKdWx5IDIxc3QsIDIwMjUiLCJjbGF1ZGUtMi4wIjoiSnVseSAyMXN0LCAyMDI1IiwiY2xhdWRlLTMtNy1zb25uZXQtbGF0ZXN0IjoiRmVicnVhcnkgMTl0aCwgMjAyNiIsImNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5IjoiRmVicnVhcnkgMTl0aCwgMjAyNiJ9O2NsYXNzIF90IGV4dGVuZHMgeWV7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMuYmF0Y2hlcz1uZXcgYnQodGhpcy5fY2xpZW50KX1jcmVhdGUoZSx0KXtjb25zdHtiZXRhczpzLC4uLnJ9PWU7ci5tb2RlbCBpbiB2dCYmY29uc29sZS53YXJuKGBUaGUgbW9kZWwgJyR7ci5tb2RlbH0nIGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgcmVhY2ggZW5kLW9mLWxpZmUgb24gJHt2dFtyLm1vZGVsXX1cblBsZWFzZSBtaWdyYXRlIHRvIGEgbmV3ZXIgbW9kZWwuIFZpc2l0IGh0dHBzOi8vZG9jcy5hbnRocm9waWMuY29tL2VuL2RvY3MvcmVzb3VyY2VzL21vZGVsLWRlcHJlY2F0aW9ucyBmb3IgbW9yZSBpbmZvcm1hdGlvbi5gKTtsZXQgbj10aGlzLl9jbGllbnQuX29wdGlvbnMudGltZW91dDtpZighci5zdHJlYW0mJm51bGw9PW4pe2NvbnN0IGU9eGVbci5tb2RlbF0/P3ZvaWQgMDtuPXRoaXMuX2NsaWVudC5jYWxjdWxhdGVOb25zdHJlYW1pbmdUaW1lb3V0KHIubWF4X3Rva2VucyxlKX1yZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9tZXNzYWdlcz9iZXRhPXRydWUiLHtib2R5OnIsdGltZW91dDpuPz82ZTUsLi4udCxoZWFkZXJzOl9lKFt7Li4ubnVsbCE9cz8udG9TdHJpbmcoKT97ImFudGhyb3BpYy1iZXRhIjpzPy50b1N0cmluZygpfTp2b2lkIDB9LHQ/LmhlYWRlcnNdKSxzdHJlYW06ZS5zdHJlYW0/PyExfSl9cGFyc2UoZSx0KXtyZXR1cm4gdD17Li4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4uZS5iZXRhcz8/W10sInN0cnVjdHVyZWQtb3V0cHV0cy0yMDI1LTExLTEzIl0udG9TdHJpbmcoKX0sdD8uaGVhZGVyc10pfSx0aGlzLmNyZWF0ZShlLHQpLnRoZW4odD0+QWUodCxlKSl9c3RyZWFtKGUsdCl7cmV0dXJuIG50LmNyZWF0ZU1lc3NhZ2UodGhpcyxlLHQpfWNvdW50VG9rZW5zKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL21lc3NhZ2VzL2NvdW50X3Rva2Vucz9iZXRhPXRydWUiLHtib2R5OnIsLi4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucz8/W10sInRva2VuLWNvdW50aW5nLTIwMjQtMTEtMDEiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX10b29sUnVubmVyKGUsdCl7cmV0dXJuIG5ldyB3dCh0aGlzLl9jbGllbnQsZSx0KX19X3QuQmF0Y2hlcz1idCxfdC5CZXRhVG9vbFJ1bm5lcj13dDtjbGFzcyBrdCBleHRlbmRzIHlle2NyZWF0ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6ciwuLi5ufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoUGVgL3YxL3NraWxscy8ke2V9L3ZlcnNpb25zP2JldGE9dHJ1ZWAsdWUoe2JvZHk6biwuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9LHRoaXMuX2NsaWVudCkpfXJldHJpZXZlKGUsdCxzKXtjb25zdHtza2lsbF9pZDpyLGJldGFzOm59PXQ7cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL3NraWxscy8ke3J9L3ZlcnNpb25zLyR7ZX0/YmV0YT10cnVlYCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ubj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9bGlzdChlLHQ9e30scyl7Y29uc3R7YmV0YXM6ciwuLi5ufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoUGVgL3YxL3NraWxscy8ke2V9L3ZlcnNpb25zP2JldGE9dHJ1ZWAsaWUse3F1ZXJ5Om4sLi4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9ZGVsZXRlKGUsdCxzKXtjb25zdHtza2lsbF9pZDpyLGJldGFzOm59PXQ7cmV0dXJuIHRoaXMuX2NsaWVudC5kZWxldGUoUGVgL3YxL3NraWxscy8ke3J9L3ZlcnNpb25zLyR7ZX0/YmV0YT10cnVlYCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ubj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9fWNsYXNzIFN0IGV4dGVuZHMgeWV7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMudmVyc2lvbnM9bmV3IGt0KHRoaXMuX2NsaWVudCl9Y3JlYXRlKGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9za2lsbHM/YmV0YT10cnVlIix1ZSh7Ym9keTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJza2lsbHMtMjAyNS0xMC0wMiJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0sdGhpcy5fY2xpZW50KSl9cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9za2lsbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9za2lsbHM/YmV0YT10cnVlIixpZSx7cXVlcnk6ciwuLi50LGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5zPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX1kZWxldGUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZGVsZXRlKFBlYC92MS9za2lsbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX19U3QuVmVyc2lvbnM9a3Q7Y2xhc3MgTXQgZXh0ZW5kcyB5ZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5tb2RlbHM9bmV3IFJlKHRoaXMuX2NsaWVudCksdGhpcy5tZXNzYWdlcz1uZXcgX3QodGhpcy5fY2xpZW50KSx0aGlzLmZpbGVzPW5ldyBFZSh0aGlzLl9jbGllbnQpLHRoaXMuc2tpbGxzPW5ldyBTdCh0aGlzLl9jbGllbnQpfX1NdC5Nb2RlbHM9UmUsTXQuTWVzc2FnZXM9X3QsTXQuRmlsZXM9RWUsTXQuU2tpbGxzPVN0O2NsYXNzIFB0IGV4dGVuZHMgeWV7Y3JlYXRlKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL2NvbXBsZXRlIix7Ym9keTpyLHRpbWVvdXQ6dGhpcy5fY2xpZW50Ll9vcHRpb25zLnRpbWVvdXQ/PzZlNSwuLi50LGhlYWRlcnM6X2UoW3suLi5udWxsIT1zPy50b1N0cmluZygpP3siYW50aHJvcGljLWJldGEiOnM/LnRvU3RyaW5nKCl9OnZvaWQgMH0sdD8uaGVhZGVyc10pLHN0cmVhbTplLnN0cmVhbT8/ITF9KX19dmFyIEV0LFJ0LHh0LFR0LEF0LEN0LEl0LE90LCR0LEx0LE50LER0LFV0LHF0LGp0LEZ0LFd0LEJ0LEp0LHp0LEh0LEt0O2NvbnN0IFZ0PSJfX2pzb25fYnVmIjtmdW5jdGlvbiBYdChlKXtyZXR1cm4idG9vbF91c2UiPT09ZS50eXBlfHwic2VydmVyX3Rvb2xfdXNlIj09PWUudHlwZX1jbGFzcyBHdHtjb25zdHJ1Y3Rvcigpe0V0LmFkZCh0aGlzKSx0aGlzLm1lc3NhZ2VzPVtdLHRoaXMucmVjZWl2ZWRNZXNzYWdlcz1bXSxSdC5zZXQodGhpcyx2b2lkIDApLHRoaXMuY29udHJvbGxlcj1uZXcgQWJvcnRDb250cm9sbGVyLHh0LnNldCh0aGlzLHZvaWQgMCksVHQuc2V0KHRoaXMsKCk9Pnt9KSxBdC5zZXQodGhpcywoKT0+e30pLEN0LnNldCh0aGlzLHZvaWQgMCksSXQuc2V0KHRoaXMsKCk9Pnt9KSxPdC5zZXQodGhpcywoKT0+e30pLCR0LnNldCh0aGlzLHt9KSxMdC5zZXQodGhpcywhMSksTnQuc2V0KHRoaXMsITEpLER0LnNldCh0aGlzLCExKSxVdC5zZXQodGhpcywhMSkscXQuc2V0KHRoaXMsdm9pZCAwKSxqdC5zZXQodGhpcyx2b2lkIDApLEJ0LnNldCh0aGlzLGU9PntpZih0KHRoaXMsTnQsITAsImYiKSxuKGUpJiYoZT1uZXcgYyksZSBpbnN0YW5jZW9mIGMpcmV0dXJuIHQodGhpcyxEdCwhMCwiZiIpLHRoaXMuX2VtaXQoImFib3J0IixlKTtpZihlIGluc3RhbmNlb2YgbylyZXR1cm4gdGhpcy5fZW1pdCgiZXJyb3IiLGUpO2lmKGUgaW5zdGFuY2VvZiBFcnJvcil7Y29uc3QgdD1uZXcgbyhlLm1lc3NhZ2UpO3JldHVybiB0LmNhdXNlPWUsdGhpcy5fZW1pdCgiZXJyb3IiLHQpfXJldHVybiB0aGlzLl9lbWl0KCJlcnJvciIsbmV3IG8oU3RyaW5nKGUpKSl9KSx0KHRoaXMseHQsbmV3IFByb21pc2UoKGUscyk9Pnt0KHRoaXMsVHQsZSwiZiIpLHQodGhpcyxBdCxzLCJmIil9KSwiZiIpLHQodGhpcyxDdCxuZXcgUHJvbWlzZSgoZSxzKT0+e3QodGhpcyxJdCxlLCJmIiksdCh0aGlzLE90LHMsImYiKX0pLCJmIikscyh0aGlzLHh0LCJmIikuY2F0Y2goKCk9Pnt9KSxzKHRoaXMsQ3QsImYiKS5jYXRjaCgoKT0+e30pfWdldCByZXNwb25zZSgpe3JldHVybiBzKHRoaXMscXQsImYiKX1nZXQgcmVxdWVzdF9pZCgpe3JldHVybiBzKHRoaXMsanQsImYiKX1hc3luYyB3aXRoUmVzcG9uc2UoKXtjb25zdCBlPWF3YWl0IHModGhpcyx4dCwiZiIpO2lmKCFlKXRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IHJlc29sdmUgYSBgUmVzcG9uc2VgIG9iamVjdCIpO3JldHVybntkYXRhOnRoaXMscmVzcG9uc2U6ZSxyZXF1ZXN0X2lkOmUuaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKX19c3RhdGljIGZyb21SZWFkYWJsZVN0cmVhbShlKXtjb25zdCB0PW5ldyBHdDtyZXR1cm4gdC5fcnVuKCgpPT50Ll9mcm9tUmVhZGFibGVTdHJlYW0oZSkpLHR9c3RhdGljIGNyZWF0ZU1lc3NhZ2UoZSx0LHMpe2NvbnN0IHI9bmV3IEd0O2Zvcihjb25zdCBlIG9mIHQubWVzc2FnZXMpci5fYWRkTWVzc2FnZVBhcmFtKGUpO3JldHVybiByLl9ydW4oKCk9PnIuX2NyZWF0ZU1lc3NhZ2UoZSx7Li4udCxzdHJlYW06ITB9LHsuLi5zLGhlYWRlcnM6ey4uLnM/LmhlYWRlcnMsIlgtU3RhaW5sZXNzLUhlbHBlci1NZXRob2QiOiJzdHJlYW0ifX0pKSxyfV9ydW4oZSl7ZSgpLnRoZW4oKCk9Pnt0aGlzLl9lbWl0RmluYWwoKSx0aGlzLl9lbWl0KCJlbmQiKX0scyh0aGlzLEJ0LCJmIikpfV9hZGRNZXNzYWdlUGFyYW0oZSl7dGhpcy5tZXNzYWdlcy5wdXNoKGUpfV9hZGRNZXNzYWdlKGUsdD0hMCl7dGhpcy5yZWNlaXZlZE1lc3NhZ2VzLnB1c2goZSksdCYmdGhpcy5fZW1pdCgibWVzc2FnZSIsZSl9YXN5bmMgX2NyZWF0ZU1lc3NhZ2UoZSx0LHIpe2NvbnN0IG49cj8uc2lnbmFsO2xldCBhO24mJihuLmFib3J0ZWQmJnRoaXMuY29udHJvbGxlci5hYm9ydCgpLGE9dGhpcy5jb250cm9sbGVyLmFib3J0LmJpbmQodGhpcy5jb250cm9sbGVyKSxuLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IixhKSk7dHJ5e3ModGhpcyxFdCwibSIsSnQpLmNhbGwodGhpcyk7Y29uc3R7cmVzcG9uc2U6bixkYXRhOmF9PWF3YWl0IGUuY3JlYXRlKHsuLi50LHN0cmVhbTohMH0sey4uLnIsc2lnbmFsOnRoaXMuY29udHJvbGxlci5zaWduYWx9KS53aXRoUmVzcG9uc2UoKTt0aGlzLl9jb25uZWN0ZWQobik7Zm9yIGF3YWl0KGNvbnN0IGUgb2YgYSlzKHRoaXMsRXQsIm0iLHp0KS5jYWxsKHRoaXMsZSk7aWYoYS5jb250cm9sbGVyLnNpZ25hbD8uYWJvcnRlZCl0aHJvdyBuZXcgYztzKHRoaXMsRXQsIm0iLEh0KS5jYWxsKHRoaXMpfWZpbmFsbHl7biYmYSYmbi5yZW1vdmVFdmVudExpc3RlbmVyKCJhYm9ydCIsYSl9fV9jb25uZWN0ZWQoZSl7dGhpcy5lbmRlZHx8KHQodGhpcyxxdCxlLCJmIiksdCh0aGlzLGp0LGU/LmhlYWRlcnMuZ2V0KCJyZXF1ZXN0LWlkIiksImYiKSxzKHRoaXMsVHQsImYiKS5jYWxsKHRoaXMsZSksdGhpcy5fZW1pdCgiY29ubmVjdCIpKX1nZXQgZW5kZWQoKXtyZXR1cm4gcyh0aGlzLEx0LCJmIil9Z2V0IGVycm9yZWQoKXtyZXR1cm4gcyh0aGlzLE50LCJmIil9Z2V0IGFib3J0ZWQoKXtyZXR1cm4gcyh0aGlzLER0LCJmIil9YWJvcnQoKXt0aGlzLmNvbnRyb2xsZXIuYWJvcnQoKX1vbihlLHQpe3JldHVybihzKHRoaXMsJHQsImYiKVtlXXx8KHModGhpcywkdCwiZiIpW2VdPVtdKSkucHVzaCh7bGlzdGVuZXI6dH0pLHRoaXN9b2ZmKGUsdCl7Y29uc3Qgcj1zKHRoaXMsJHQsImYiKVtlXTtpZighcilyZXR1cm4gdGhpcztjb25zdCBuPXIuZmluZEluZGV4KGU9PmUubGlzdGVuZXI9PT10KTtyZXR1cm4gbj49MCYmci5zcGxpY2UobiwxKSx0aGlzfW9uY2UoZSx0KXtyZXR1cm4ocyh0aGlzLCR0LCJmIilbZV18fChzKHRoaXMsJHQsImYiKVtlXT1bXSkpLnB1c2goe2xpc3RlbmVyOnQsb25jZTohMH0pLHRoaXN9ZW1pdHRlZChlKXtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pnt0KHRoaXMsVXQsITAsImYiKSwiZXJyb3IiIT09ZSYmdGhpcy5vbmNlKCJlcnJvciIsciksdGhpcy5vbmNlKGUscyl9KX1hc3luYyBkb25lKCl7dCh0aGlzLFV0LCEwLCJmIiksYXdhaXQgcyh0aGlzLEN0LCJmIil9Z2V0IGN1cnJlbnRNZXNzYWdlKCl7cmV0dXJuIHModGhpcyxSdCwiZiIpfWFzeW5jIGZpbmFsTWVzc2FnZSgpe3JldHVybiBhd2FpdCB0aGlzLmRvbmUoKSxzKHRoaXMsRXQsIm0iLEZ0KS5jYWxsKHRoaXMpfWFzeW5jIGZpbmFsVGV4dCgpe3JldHVybiBhd2FpdCB0aGlzLmRvbmUoKSxzKHRoaXMsRXQsIm0iLFd0KS5jYWxsKHRoaXMpfV9lbWl0KGUsLi4ucil7aWYocyh0aGlzLEx0LCJmIikpcmV0dXJuOyJlbmQiPT09ZSYmKHQodGhpcyxMdCwhMCwiZiIpLHModGhpcyxJdCwiZiIpLmNhbGwodGhpcykpO2NvbnN0IG49cyh0aGlzLCR0LCJmIilbZV07aWYobiYmKHModGhpcywkdCwiZiIpW2VdPW4uZmlsdGVyKGU9PiFlLm9uY2UpLG4uZm9yRWFjaCgoe2xpc3RlbmVyOmV9KT0+ZSguLi5yKSkpLCJhYm9ydCI9PT1lKXtjb25zdCBlPXJbMF07cmV0dXJuIHModGhpcyxVdCwiZiIpfHxuPy5sZW5ndGh8fFByb21pc2UucmVqZWN0KGUpLHModGhpcyxBdCwiZiIpLmNhbGwodGhpcyxlKSxzKHRoaXMsT3QsImYiKS5jYWxsKHRoaXMsZSksdm9pZCB0aGlzLl9lbWl0KCJlbmQiKX1pZigiZXJyb3IiPT09ZSl7Y29uc3QgZT1yWzBdO3ModGhpcyxVdCwiZiIpfHxuPy5sZW5ndGh8fFByb21pc2UucmVqZWN0KGUpLHModGhpcyxBdCwiZiIpLmNhbGwodGhpcyxlKSxzKHRoaXMsT3QsImYiKS5jYWxsKHRoaXMsZSksdGhpcy5fZW1pdCgiZW5kIil9fV9lbWl0RmluYWwoKXt0aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpJiZ0aGlzLl9lbWl0KCJmaW5hbE1lc3NhZ2UiLHModGhpcyxFdCwibSIsRnQpLmNhbGwodGhpcykpfWFzeW5jIF9mcm9tUmVhZGFibGVTdHJlYW0oZSx0KXtjb25zdCByPXQ/LnNpZ25hbDtsZXQgbjtyJiYoci5hYm9ydGVkJiZ0aGlzLmNvbnRyb2xsZXIuYWJvcnQoKSxuPXRoaXMuY29udHJvbGxlci5hYm9ydC5iaW5kKHRoaXMuY29udHJvbGxlciksci5hZGRFdmVudExpc3RlbmVyKCJhYm9ydCIsbikpO3RyeXtzKHRoaXMsRXQsIm0iLEp0KS5jYWxsKHRoaXMpLHRoaXMuX2Nvbm5lY3RlZChudWxsKTtjb25zdCB0PVouZnJvbVJlYWRhYmxlU3RyZWFtKGUsdGhpcy5jb250cm9sbGVyKTtmb3IgYXdhaXQoY29uc3QgZSBvZiB0KXModGhpcyxFdCwibSIsenQpLmNhbGwodGhpcyxlKTtpZih0LmNvbnRyb2xsZXIuc2lnbmFsPy5hYm9ydGVkKXRocm93IG5ldyBjO3ModGhpcyxFdCwibSIsSHQpLmNhbGwodGhpcyl9ZmluYWxseXtyJiZuJiZyLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0IixuKX19WyhSdD1uZXcgV2Vha01hcCx4dD1uZXcgV2Vha01hcCxUdD1uZXcgV2Vha01hcCxBdD1uZXcgV2Vha01hcCxDdD1uZXcgV2Vha01hcCxJdD1uZXcgV2Vha01hcCxPdD1uZXcgV2Vha01hcCwkdD1uZXcgV2Vha01hcCxMdD1uZXcgV2Vha01hcCxOdD1uZXcgV2Vha01hcCxEdD1uZXcgV2Vha01hcCxVdD1uZXcgV2Vha01hcCxxdD1uZXcgV2Vha01hcCxqdD1uZXcgV2Vha01hcCxCdD1uZXcgV2Vha01hcCxFdD1uZXcgV2Vha1NldCxGdD1mdW5jdGlvbigpe2lmKDA9PT10aGlzLnJlY2VpdmVkTWVzc2FnZXMubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBNZXNzYWdlIHdpdGggcm9sZT1hc3Npc3RhbnQiKTtyZXR1cm4gdGhpcy5yZWNlaXZlZE1lc3NhZ2VzLmF0KC0xKX0sV3Q9ZnVuY3Rpb24oKXtpZigwPT09dGhpcy5yZWNlaXZlZE1lc3NhZ2VzLmxlbmd0aCl0aHJvdyBuZXcgbygic3RyZWFtIGVuZGVkIHdpdGhvdXQgcHJvZHVjaW5nIGEgTWVzc2FnZSB3aXRoIHJvbGU9YXNzaXN0YW50Iik7Y29uc3QgZT10aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpLmNvbnRlbnQuZmlsdGVyKGU9PiJ0ZXh0Ij09PWUudHlwZSkubWFwKGU9PmUudGV4dCk7aWYoMD09PWUubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBjb250ZW50IGJsb2NrIHdpdGggdHlwZT10ZXh0Iik7cmV0dXJuIGUuam9pbigiICIpfSxKdD1mdW5jdGlvbigpe3RoaXMuZW5kZWR8fHQodGhpcyxSdCx2b2lkIDAsImYiKX0senQ9ZnVuY3Rpb24oZSl7aWYodGhpcy5lbmRlZClyZXR1cm47Y29uc3Qgcj1zKHRoaXMsRXQsIm0iLEt0KS5jYWxsKHRoaXMsZSk7c3dpdGNoKHRoaXMuX2VtaXQoInN0cmVhbUV2ZW50IixlLHIpLGUudHlwZSl7Y2FzZSJjb250ZW50X2Jsb2NrX2RlbHRhIjp7Y29uc3QgdD1yLmNvbnRlbnQuYXQoLTEpO3N3aXRjaChlLmRlbHRhLnR5cGUpe2Nhc2UidGV4dF9kZWx0YSI6InRleHQiPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJ0ZXh0IixlLmRlbHRhLnRleHQsdC50ZXh0fHwiIik7YnJlYWs7Y2FzZSJjaXRhdGlvbnNfZGVsdGEiOiJ0ZXh0Ij09PXQudHlwZSYmdGhpcy5fZW1pdCgiY2l0YXRpb24iLGUuZGVsdGEuY2l0YXRpb24sdC5jaXRhdGlvbnM/P1tdKTticmVhaztjYXNlImlucHV0X2pzb25fZGVsdGEiOlh0KHQpJiZ0LmlucHV0JiZ0aGlzLl9lbWl0KCJpbnB1dEpzb24iLGUuZGVsdGEucGFydGlhbF9qc29uLHQuaW5wdXQpO2JyZWFrO2Nhc2UidGhpbmtpbmdfZGVsdGEiOiJ0aGlua2luZyI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInRoaW5raW5nIixlLmRlbHRhLnRoaW5raW5nLHQudGhpbmtpbmcpO2JyZWFrO2Nhc2Uic2lnbmF0dXJlX2RlbHRhIjoidGhpbmtpbmciPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJzaWduYXR1cmUiLHQuc2lnbmF0dXJlKTticmVhaztkZWZhdWx0OmUuZGVsdGF9YnJlYWt9Y2FzZSJtZXNzYWdlX3N0b3AiOnRoaXMuX2FkZE1lc3NhZ2VQYXJhbShyKSx0aGlzLl9hZGRNZXNzYWdlKHIsITApO2JyZWFrO2Nhc2UiY29udGVudF9ibG9ja19zdG9wIjp0aGlzLl9lbWl0KCJjb250ZW50QmxvY2siLHIuY29udGVudC5hdCgtMSkpO2JyZWFrO2Nhc2UibWVzc2FnZV9zdGFydCI6dCh0aGlzLFJ0LHIsImYiKX19LEh0PWZ1bmN0aW9uKCl7aWYodGhpcy5lbmRlZCl0aHJvdyBuZXcgbygic3RyZWFtIGhhcyBlbmRlZCwgdGhpcyBzaG91bGRuJ3QgaGFwcGVuIik7Y29uc3QgZT1zKHRoaXMsUnQsImYiKTtpZighZSl0aHJvdyBuZXcgbygicmVxdWVzdCBlbmRlZCB3aXRob3V0IHNlbmRpbmcgYW55IGNodW5rcyIpO3JldHVybiB0KHRoaXMsUnQsdm9pZCAwLCJmIiksZX0sS3Q9ZnVuY3Rpb24oZSl7bGV0IHQ9cyh0aGlzLFJ0LCJmIik7aWYoIm1lc3NhZ2Vfc3RhcnQiPT09ZS50eXBlKXtpZih0KXRocm93IG5ldyBvKGBVbmV4cGVjdGVkIGV2ZW50IG9yZGVyLCBnb3QgJHtlLnR5cGV9IGJlZm9yZSByZWNlaXZpbmcgIm1lc3NhZ2Vfc3RvcCJgKTtyZXR1cm4gZS5tZXNzYWdlfWlmKCF0KXRocm93IG5ldyBvKGBVbmV4cGVjdGVkIGV2ZW50IG9yZGVyLCBnb3QgJHtlLnR5cGV9IGJlZm9yZSAibWVzc2FnZV9zdGFydCJgKTtzd2l0Y2goZS50eXBlKXtjYXNlIm1lc3NhZ2Vfc3RvcCI6Y2FzZSJjb250ZW50X2Jsb2NrX3N0b3AiOnJldHVybiB0O2Nhc2UibWVzc2FnZV9kZWx0YSI6cmV0dXJuIHQuc3RvcF9yZWFzb249ZS5kZWx0YS5zdG9wX3JlYXNvbix0LnN0b3Bfc2VxdWVuY2U9ZS5kZWx0YS5zdG9wX3NlcXVlbmNlLHQudXNhZ2Uub3V0cHV0X3Rva2Vucz1lLnVzYWdlLm91dHB1dF90b2tlbnMsbnVsbCE9ZS51c2FnZS5pbnB1dF90b2tlbnMmJih0LnVzYWdlLmlucHV0X3Rva2Vucz1lLnVzYWdlLmlucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMmJih0LnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2Vucz1lLnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyYmKHQudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM9ZS51c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5zZXJ2ZXJfdG9vbF91c2UmJih0LnVzYWdlLnNlcnZlcl90b29sX3VzZT1lLnVzYWdlLnNlcnZlcl90b29sX3VzZSksdDtjYXNlImNvbnRlbnRfYmxvY2tfc3RhcnQiOnJldHVybiB0LmNvbnRlbnQucHVzaCh7Li4uZS5jb250ZW50X2Jsb2NrfSksdDtjYXNlImNvbnRlbnRfYmxvY2tfZGVsdGEiOntjb25zdCBzPXQuY29udGVudC5hdChlLmluZGV4KTtzd2l0Y2goZS5kZWx0YS50eXBlKXtjYXNlInRleHRfZGVsdGEiOiJ0ZXh0Ij09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsdGV4dDoocy50ZXh0fHwiIikrZS5kZWx0YS50ZXh0fSk7YnJlYWs7Y2FzZSJjaXRhdGlvbnNfZGVsdGEiOiJ0ZXh0Ij09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsY2l0YXRpb25zOlsuLi5zLmNpdGF0aW9ucz8/W10sZS5kZWx0YS5jaXRhdGlvbl19KTticmVhaztjYXNlImlucHV0X2pzb25fZGVsdGEiOmlmKHMmJlh0KHMpKXtsZXQgcj1zW1Z0XXx8IiI7cis9ZS5kZWx0YS5wYXJ0aWFsX2pzb247Y29uc3Qgbj17Li4uc307T2JqZWN0LmRlZmluZVByb3BlcnR5KG4sVnQse3ZhbHVlOnIsZW51bWVyYWJsZTohMSx3cml0YWJsZTohMH0pLHImJihuLmlucHV0PUllKHIpKSx0LmNvbnRlbnRbZS5pbmRleF09bn1icmVhaztjYXNlInRoaW5raW5nX2RlbHRhIjoidGhpbmtpbmciPT09cz8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucyx0aGlua2luZzpzLnRoaW5raW5nK2UuZGVsdGEudGhpbmtpbmd9KTticmVhaztjYXNlInNpZ25hdHVyZV9kZWx0YSI6InRoaW5raW5nIj09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsc2lnbmF0dXJlOmUuZGVsdGEuc2lnbmF0dXJlfSk7YnJlYWs7ZGVmYXVsdDplLmRlbHRhfXJldHVybiB0fX19LFN5bWJvbC5hc3luY0l0ZXJhdG9yKV0oKXtjb25zdCBlPVtdLHQ9W107bGV0IHM9ITE7cmV0dXJuIHRoaXMub24oInN0cmVhbUV2ZW50IixzPT57Y29uc3Qgcj10LnNoaWZ0KCk7cj9yLnJlc29sdmUocyk6ZS5wdXNoKHMpfSksdGhpcy5vbigiZW5kIiwoKT0+e3M9ITA7Zm9yKGNvbnN0IGUgb2YgdCllLnJlc29sdmUodm9pZCAwKTt0Lmxlbmd0aD0wfSksdGhpcy5vbigiYWJvcnQiLGU9PntzPSEwO2Zvcihjb25zdCBzIG9mIHQpcy5yZWplY3QoZSk7dC5sZW5ndGg9MH0pLHRoaXMub24oImVycm9yIixlPT57cz0hMDtmb3IoY29uc3QgcyBvZiB0KXMucmVqZWN0KGUpO3QubGVuZ3RoPTB9KSx7bmV4dDphc3luYygpPT5lLmxlbmd0aD97dmFsdWU6ZS5zaGlmdCgpLGRvbmU6ITF9OnM/e3ZhbHVlOnZvaWQgMCxkb25lOiEwfTpuZXcgUHJvbWlzZSgoZSxzKT0+dC5wdXNoKHtyZXNvbHZlOmUscmVqZWN0OnN9KSkudGhlbihlPT5lP3t2YWx1ZTplLGRvbmU6ITF9Ont2YWx1ZTp2b2lkIDAsZG9uZTohMH0pLHJldHVybjphc3luYygpPT4odGhpcy5hYm9ydCgpLHt2YWx1ZTp2b2lkIDAsZG9uZTohMH0pfX10b1JlYWRhYmxlU3RyZWFtKCl7cmV0dXJuIG5ldyBaKHRoaXNbU3ltYm9sLmFzeW5jSXRlcmF0b3JdLmJpbmQodGhpcyksdGhpcy5jb250cm9sbGVyKS50b1JlYWRhYmxlU3RyZWFtKCl9fWNsYXNzIFl0IGV4dGVuZHMgeWV7Y3JlYXRlKGUsdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMvYmF0Y2hlcyIse2JvZHk6ZSwuLi50fSl9cmV0cmlldmUoZSx0KXtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9YCx0KX1saXN0KGU9e30sdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvbWVzc2FnZXMvYmF0Y2hlcyIsb2Use3F1ZXJ5OmUsLi4udH0pfWRlbGV0ZShlLHQpe3JldHVybiB0aGlzLl9jbGllbnQuZGVsZXRlKFBlYC92MS9tZXNzYWdlcy9iYXRjaGVzLyR7ZX1gLHQpfWNhbmNlbChlLHQpe3JldHVybiB0aGlzLl9jbGllbnQucG9zdChQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9L2NhbmNlbGAsdCl9YXN5bmMgcmVzdWx0cyhlLHQpe2NvbnN0IHM9YXdhaXQgdGhpcy5yZXRyaWV2ZShlKTtpZighcy5yZXN1bHRzX3VybCl0aHJvdyBuZXcgbyhgTm8gYmF0Y2ggXGByZXN1bHRzX3VybFxgOyBIYXMgaXQgZmluaXNoZWQgcHJvY2Vzc2luZz8gJHtzLnByb2Nlc3Npbmdfc3RhdHVzfSAtICR7cy5pZH1gKTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChzLnJlc3VsdHNfdXJsLHsuLi50LGhlYWRlcnM6X2UoW3tBY2NlcHQ6ImFwcGxpY2F0aW9uL2JpbmFyeSJ9LHQ/LmhlYWRlcnNdKSxzdHJlYW06ITAsX19iaW5hcnlSZXNwb25zZTohMH0pLl90aGVuVW53cmFwKChlLHQpPT55dC5mcm9tUmVzcG9uc2UodC5yZXNwb25zZSx0LmNvbnRyb2xsZXIpKX19Y2xhc3MgUXQgZXh0ZW5kcyB5ZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5iYXRjaGVzPW5ldyBZdCh0aGlzLl9jbGllbnQpfWNyZWF0ZShlLHQpe2UubW9kZWwgaW4gWnQmJmNvbnNvbGUud2FybihgVGhlIG1vZGVsICcke2UubW9kZWx9JyBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIHJlYWNoIGVuZC1vZi1saWZlIG9uICR7WnRbZS5tb2RlbF19XG5QbGVhc2UgbWlncmF0ZSB0byBhIG5ld2VyIG1vZGVsLiBWaXNpdCBodHRwczovL2RvY3MuYW50aHJvcGljLmNvbS9lbi9kb2NzL3Jlc291cmNlcy9tb2RlbC1kZXByZWNhdGlvbnMgZm9yIG1vcmUgaW5mb3JtYXRpb24uYCk7bGV0IHM9dGhpcy5fY2xpZW50Ll9vcHRpb25zLnRpbWVvdXQ7aWYoIWUuc3RyZWFtJiZudWxsPT1zKXtjb25zdCB0PXhlW2UubW9kZWxdPz92b2lkIDA7cz10aGlzLl9jbGllbnQuY2FsY3VsYXRlTm9uc3RyZWFtaW5nVGltZW91dChlLm1heF90b2tlbnMsdCl9cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMiLHtib2R5OmUsdGltZW91dDpzPz82ZTUsLi4udCxzdHJlYW06ZS5zdHJlYW0/PyExfSl9c3RyZWFtKGUsdCl7cmV0dXJuIEd0LmNyZWF0ZU1lc3NhZ2UodGhpcyxlLHQpfWNvdW50VG9rZW5zKGUsdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMvY291bnRfdG9rZW5zIix7Ym9keTplLC4uLnR9KX19Y29uc3QgWnQ9eyJjbGF1ZGUtMS4zIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLTEuMy0xMDBrIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLWluc3RhbnQtMS4xIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLWluc3RhbnQtMS4xLTEwMGsiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjIiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtMy1zb25uZXQtMjAyNDAyMjkiOiJKdWx5IDIxc3QsIDIwMjUiLCJjbGF1ZGUtMy1vcHVzLTIwMjQwMjI5IjoiSmFudWFyeSA1dGgsIDIwMjYiLCJjbGF1ZGUtMi4xIjoiSnVseSAyMXN0LCAyMDI1IiwiY2xhdWRlLTIuMCI6Ikp1bHkgMjFzdCwgMjAyNSIsImNsYXVkZS0zLTctc29ubmV0LWxhdGVzdCI6IkZlYnJ1YXJ5IDE5dGgsIDIwMjYiLCJjbGF1ZGUtMy03LXNvbm5ldC0yMDI1MDIxOSI6IkZlYnJ1YXJ5IDE5dGgsIDIwMjYifTtRdC5CYXRjaGVzPVl0O2NsYXNzIGVzIGV4dGVuZHMgeWV7cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9tb2RlbHMvJHtlfWAsey4uLnMsaGVhZGVyczpfZShbey4uLm51bGwhPXI/LnRvU3RyaW5nKCk/eyJhbnRocm9waWMtYmV0YSI6cj8udG9TdHJpbmcoKX06dm9pZCAwfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9tb2RlbHMiLG9lLHtxdWVyeTpyLC4uLnQsaGVhZGVyczpfZShbey4uLm51bGwhPXM/LnRvU3RyaW5nKCk/eyJhbnRocm9waWMtYmV0YSI6cz8udG9TdHJpbmcoKX06dm9pZCAwfSx0Py5oZWFkZXJzXSl9KX19Y29uc3QgdHM9ZT0+dm9pZCAwIT09Z2xvYmFsVGhpcy5wcm9jZXNzP2dsb2JhbFRoaXMucHJvY2Vzcy5lbnY/LltlXT8udHJpbSgpPz92b2lkIDA6dm9pZCAwIT09Z2xvYmFsVGhpcy5EZW5vP2dsb2JhbFRoaXMuRGVuby5lbnY/LmdldD8uKGUpPy50cmltKCk6dm9pZCAwO3ZhciBzcyxycyxucyxhcyxvcyxpcztjbGFzcyBjc3tjb25zdHJ1Y3Rvcih7YmFzZVVSTDplPXRzKCJBTlRIUk9QSUNfQkFTRV9VUkwiKSxhcGlLZXk6cz10cygiQU5USFJPUElDX0FQSV9LRVkiKT8/bnVsbCxhdXRoVG9rZW46cj10cygiQU5USFJPUElDX0FVVEhfVE9LRU4iKT8/bnVsbCwuLi5ufT17fSl7c3MuYWRkKHRoaXMpLG5zLnNldCh0aGlzLHZvaWQgMCk7Y29uc3QgYT17YXBpS2V5OnMsYXV0aFRva2VuOnIsLi4ubixiYXNlVVJMOmV8fCJodHRwczovL2FwaS5hbnRocm9waWMuY29tIn07aWYoIWEuZGFuZ2Vyb3VzbHlBbGxvd0Jyb3dzZXImJiJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiZ2b2lkIDAhPT13aW5kb3cuZG9jdW1lbnQmJiJ1bmRlZmluZWQiIT10eXBlb2YgbmF2aWdhdG9yKXRocm93IG5ldyBvKCJJdCBsb29rcyBsaWtlIHlvdSdyZSBydW5uaW5nIGluIGEgYnJvd3Nlci1saWtlIGVudmlyb25tZW50LlxuXG5UaGlzIGlzIGRpc2FibGVkIGJ5IGRlZmF1bHQsIGFzIGl0IHJpc2tzIGV4cG9zaW5nIHlvdXIgc2VjcmV0IEFQSSBjcmVkZW50aWFscyB0byBhdHRhY2tlcnMuXG5JZiB5b3UgdW5kZXJzdGFuZCB0aGUgcmlza3MgYW5kIGhhdmUgYXBwcm9wcmlhdGUgbWl0aWdhdGlvbnMgaW4gcGxhY2UsXG55b3UgY2FuIHNldCB0aGUgYGRhbmdlcm91c2x5QWxsb3dCcm93c2VyYCBvcHRpb24gdG8gYHRydWVgLCBlLmcuLFxuXG5uZXcgQW50aHJvcGljKHsgYXBpS2V5LCBkYW5nZXJvdXNseUFsbG93QnJvd3NlcjogdHJ1ZSB9KTtcbiIpO3RoaXMuYmFzZVVSTD1hLmJhc2VVUkwsdGhpcy50aW1lb3V0PWEudGltZW91dD8/cnMuREVGQVVMVF9USU1FT1VULHRoaXMubG9nZ2VyPWEubG9nZ2VyPz9jb25zb2xlO2NvbnN0IGk9Indhcm4iO3RoaXMubG9nTGV2ZWw9aSx0aGlzLmxvZ0xldmVsPUIoYS5sb2dMZXZlbCwiQ2xpZW50T3B0aW9ucy5sb2dMZXZlbCIsdGhpcyk/P0IodHMoIkFOVEhST1BJQ19MT0ciKSwicHJvY2Vzcy5lbnZbJ0FOVEhST1BJQ19MT0cnXSIsdGhpcyk/P2ksdGhpcy5mZXRjaE9wdGlvbnM9YS5mZXRjaE9wdGlvbnMsdGhpcy5tYXhSZXRyaWVzPWEubWF4UmV0cmllcz8/Mix0aGlzLmZldGNoPWEuZmV0Y2g/P2Z1bmN0aW9uKCl7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBmZXRjaClyZXR1cm4gZmV0Y2g7dGhyb3cgbmV3IEVycm9yKCJgZmV0Y2hgIGlzIG5vdCBkZWZpbmVkIGFzIGEgZ2xvYmFsOyBFaXRoZXIgcGFzcyBgZmV0Y2hgIHRvIHRoZSBjbGllbnQsIGBuZXcgQW50aHJvcGljKHsgZmV0Y2ggfSlgIG9yIHBvbHlmaWxsIHRoZSBnbG9iYWwsIGBnbG9iYWxUaGlzLmZldGNoID0gZmV0Y2hgIil9KCksdCh0aGlzLG5zLEksImYiKSx0aGlzLl9vcHRpb25zPWEsdGhpcy5hcGlLZXk9InN0cmluZyI9PXR5cGVvZiBzP3M6bnVsbCx0aGlzLmF1dGhUb2tlbj1yfXdpdGhPcHRpb25zKGUpe3JldHVybiBuZXcgdGhpcy5jb25zdHJ1Y3Rvcih7Li4udGhpcy5fb3B0aW9ucyxiYXNlVVJMOnRoaXMuYmFzZVVSTCxtYXhSZXRyaWVzOnRoaXMubWF4UmV0cmllcyx0aW1lb3V0OnRoaXMudGltZW91dCxsb2dnZXI6dGhpcy5sb2dnZXIsbG9nTGV2ZWw6dGhpcy5sb2dMZXZlbCxmZXRjaDp0aGlzLmZldGNoLGZldGNoT3B0aW9uczp0aGlzLmZldGNoT3B0aW9ucyxhcGlLZXk6dGhpcy5hcGlLZXksYXV0aFRva2VuOnRoaXMuYXV0aFRva2VuLC4uLmV9KX1kZWZhdWx0UXVlcnkoKXtyZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0UXVlcnl9dmFsaWRhdGVIZWFkZXJzKHt2YWx1ZXM6ZSxudWxsczp0fSl7aWYoIWUuZ2V0KCJ4LWFwaS1rZXkiKSYmIWUuZ2V0KCJhdXRob3JpemF0aW9uIikmJiEodGhpcy5hcGlLZXkmJmUuZ2V0KCJ4LWFwaS1rZXkiKXx8dC5oYXMoIngtYXBpLWtleSIpfHx0aGlzLmF1dGhUb2tlbiYmZS5nZXQoImF1dGhvcml6YXRpb24iKXx8dC5oYXMoImF1dGhvcml6YXRpb24iKSkpdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgcmVzb2x2ZSBhdXRoZW50aWNhdGlvbiBtZXRob2QuIEV4cGVjdGVkIGVpdGhlciBhcGlLZXkgb3IgYXV0aFRva2VuIHRvIGJlIHNldC4gT3IgZm9yIG9uZSBvZiB0aGUgIlgtQXBpLUtleSIgb3IgIkF1dGhvcml6YXRpb24iIGhlYWRlcnMgdG8gYmUgZXhwbGljaXRseSBvbWl0dGVkJyl9YXN5bmMgYXV0aEhlYWRlcnMoZSl7cmV0dXJuIF9lKFthd2FpdCB0aGlzLmFwaUtleUF1dGgoZSksYXdhaXQgdGhpcy5iZWFyZXJBdXRoKGUpXSl9YXN5bmMgYXBpS2V5QXV0aChlKXtpZihudWxsIT10aGlzLmFwaUtleSlyZXR1cm4gX2UoW3siWC1BcGktS2V5Ijp0aGlzLmFwaUtleX1dKX1hc3luYyBiZWFyZXJBdXRoKGUpe2lmKG51bGwhPXRoaXMuYXV0aFRva2VuKXJldHVybiBfZShbe0F1dGhvcml6YXRpb246YEJlYXJlciAke3RoaXMuYXV0aFRva2VufWB9XSl9c3RyaW5naWZ5UXVlcnkoZSl7cmV0dXJuIE9iamVjdC5lbnRyaWVzKGUpLmZpbHRlcigoW2UsdF0pPT52b2lkIDAhPT10KS5tYXAoKFtlLHRdKT0+e2lmKCJzdHJpbmciPT10eXBlb2YgdHx8Im51bWJlciI9PXR5cGVvZiB0fHwiYm9vbGVhbiI9PXR5cGVvZiB0KXJldHVybmAke2VuY29kZVVSSUNvbXBvbmVudChlKX09JHtlbmNvZGVVUklDb21wb25lbnQodCl9YDtpZihudWxsPT09dClyZXR1cm5gJHtlbmNvZGVVUklDb21wb25lbnQoZSl9PWA7dGhyb3cgbmV3IG8oYENhbm5vdCBzdHJpbmdpZnkgdHlwZSAke3R5cGVvZiB0fTsgRXhwZWN0ZWQgc3RyaW5nLCBudW1iZXIsIGJvb2xlYW4sIG9yIG51bGwuIElmIHlvdSBuZWVkIHRvIHBhc3MgbmVzdGVkIHF1ZXJ5IHBhcmFtZXRlcnMsIHlvdSBjYW4gbWFudWFsbHkgZW5jb2RlIHRoZW0sIGUuZy4geyBxdWVyeTogeyAnZm9vW2tleTFdJzogdmFsdWUxLCAnZm9vW2tleTJdJzogdmFsdWUyIH0gfSwgYW5kIHBsZWFzZSBvcGVuIGEgR2l0SHViIGlzc3VlIHJlcXVlc3RpbmcgYmV0dGVyIHN1cHBvcnQgZm9yIHlvdXIgdXNlIGNhc2UuYCl9KS5qb2luKCImIil9Z2V0VXNlckFnZW50KCl7cmV0dXJuYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfS9KUyAke019YH1kZWZhdWx0SWRlbXBvdGVuY3lLZXkoKXtyZXR1cm5gc3RhaW5sZXNzLW5vZGUtcmV0cnktJHtyKCl9YH1tYWtlU3RhdHVzRXJyb3IoZSx0LHMscil7cmV0dXJuIGkuZ2VuZXJhdGUoZSx0LHMscil9YnVpbGRVUkwoZSx0LHIpe2NvbnN0IG49IXModGhpcyxzcywibSIsYXMpLmNhbGwodGhpcykmJnJ8fHRoaXMuYmFzZVVSTCxhPShlPT5iLnRlc3QoZSkpKGUpP25ldyBVUkwoZSk6bmV3IFVSTChuKyhuLmVuZHNXaXRoKCIvIikmJmUuc3RhcnRzV2l0aCgiLyIpP2Uuc2xpY2UoMSk6ZSkpLG89dGhpcy5kZWZhdWx0UXVlcnkoKTtyZXR1cm4gZnVuY3Rpb24oZSl7aWYoIWUpcmV0dXJuITA7Zm9yKGNvbnN0IHQgaW4gZSlyZXR1cm4hMTtyZXR1cm4hMH0obyl8fCh0PXsuLi5vLC4uLnR9KSwib2JqZWN0Ij09dHlwZW9mIHQmJnQmJiFBcnJheS5pc0FycmF5KHQpJiYoYS5zZWFyY2g9dGhpcy5zdHJpbmdpZnlRdWVyeSh0KSksYS50b1N0cmluZygpfV9jYWxjdWxhdGVOb25zdHJlYW1pbmdUaW1lb3V0KGUpe2lmKDM2MDAqZS8xMjhlMz42MDApdGhyb3cgbmV3IG8oIlN0cmVhbWluZyBpcyByZXF1aXJlZCBmb3Igb3BlcmF0aW9ucyB0aGF0IG1heSB0YWtlIGxvbmdlciB0aGFuIDEwIG1pbnV0ZXMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYW50aHJvcGljcy9hbnRocm9waWMtc2RrLXR5cGVzY3JpcHQjc3RyZWFtaW5nLXJlc3BvbnNlcyBmb3IgbW9yZSBkZXRhaWxzIik7cmV0dXJuIDZlNX1hc3luYyBwcmVwYXJlT3B0aW9ucyhlKXt9YXN5bmMgcHJlcGFyZVJlcXVlc3QoZSx7dXJsOnQsb3B0aW9uczpzfSl7fWdldChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoImdldCIsZSx0KX1wb3N0KGUsdCl7cmV0dXJuIHRoaXMubWV0aG9kUmVxdWVzdCgicG9zdCIsZSx0KX1wYXRjaChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoInBhdGNoIixlLHQpfXB1dChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoInB1dCIsZSx0KX1kZWxldGUoZSx0KXtyZXR1cm4gdGhpcy5tZXRob2RSZXF1ZXN0KCJkZWxldGUiLGUsdCl9bWV0aG9kUmVxdWVzdChlLHQscyl7cmV0dXJuIHRoaXMucmVxdWVzdChQcm9taXNlLnJlc29sdmUocykudGhlbihzPT4oe21ldGhvZDplLHBhdGg6dCwuLi5zfSkpKX1yZXF1ZXN0KGUsdD1udWxsKXtyZXR1cm4gbmV3IHJlKHRoaXMsdGhpcy5tYWtlUmVxdWVzdChlLHQsdm9pZCAwKSl9YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe2NvbnN0IHI9YXdhaXQgZSxvPXIubWF4UmV0cmllcz8/dGhpcy5tYXhSZXRyaWVzO251bGw9PXQmJih0PW8pLGF3YWl0IHRoaXMucHJlcGFyZU9wdGlvbnMocik7Y29uc3R7cmVxOmksdXJsOmgsdGltZW91dDp1fT1hd2FpdCB0aGlzLmJ1aWxkUmVxdWVzdChyLHtyZXRyeUNvdW50Om8tdH0pO2F3YWl0IHRoaXMucHJlcGFyZVJlcXVlc3QoaSx7dXJsOmgsb3B0aW9uczpyfSk7Y29uc3QgcD0ibG9nXyIrKE1hdGgucmFuZG9tKCkqKDE8PDI0KXwwKS50b1N0cmluZygxNikucGFkU3RhcnQoNiwiMCIpLGY9dm9pZCAwPT09cz8iIjpgLCByZXRyeU9mOiAke3N9YCxtPURhdGUubm93KCk7aWYoVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIHNlbmRpbmcgcmVxdWVzdGAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpzLG1ldGhvZDpyLm1ldGhvZCx1cmw6aCxvcHRpb25zOnIsaGVhZGVyczppLmhlYWRlcnN9KSksci5zaWduYWw/LmFib3J0ZWQpdGhyb3cgbmV3IGM7Y29uc3QgZz1uZXcgQWJvcnRDb250cm9sbGVyLHc9YXdhaXQgdGhpcy5mZXRjaFdpdGhUaW1lb3V0KGgsaSx1LGcpLmNhdGNoKGEpLHk9RGF0ZS5ub3coKTtpZih3IGluc3RhbmNlb2YgZ2xvYmFsVGhpcy5FcnJvcil7Y29uc3QgZT1gcmV0cnlpbmcsICR7dH0gYXR0ZW1wdHMgcmVtYWluaW5nYDtpZihyLnNpZ25hbD8uYWJvcnRlZCl0aHJvdyBuZXcgYztjb25zdCBhPW4odyl8fC90aW1lZD8gP291dC9pLnRlc3QoU3RyaW5nKHcpKygiY2F1c2UiaW4gdz9TdHJpbmcody5jYXVzZSk6IiIpKTtpZih0KXJldHVybiBWKHRoaXMpLmluZm8oYFske3B9XSBjb25uZWN0aW9uICR7YT8idGltZWQgb3V0IjoiZmFpbGVkIn0gLSAke2V9YCksVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIGNvbm5lY3Rpb24gJHthPyJ0aW1lZCBvdXQiOiJmYWlsZWQifSAoJHtlfSlgLFgoe3JldHJ5T2ZSZXF1ZXN0TG9nSUQ6cyx1cmw6aCxkdXJhdGlvbk1zOnktbSxtZXNzYWdlOncubWVzc2FnZX0pKSx0aGlzLnJldHJ5UmVxdWVzdChyLHQscz8/cCk7aWYoVih0aGlzKS5pbmZvKGBbJHtwfV0gY29ubmVjdGlvbiAke2E/InRpbWVkIG91dCI6ImZhaWxlZCJ9IC0gZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0YCksVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIGNvbm5lY3Rpb24gJHthPyJ0aW1lZCBvdXQiOiJmYWlsZWQifSAoZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0KWAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpzLHVybDpoLGR1cmF0aW9uTXM6eS1tLG1lc3NhZ2U6dy5tZXNzYWdlfSkpLGEpdGhyb3cgbmV3IGQ7dGhyb3cgbmV3IGwoe2NhdXNlOnd9KX1jb25zdCBiPWBbJHtwfSR7Zn0ke1suLi53LmhlYWRlcnMuZW50cmllcygpXS5maWx0ZXIoKFtlXSk9PiJyZXF1ZXN0LWlkIj09PWUpLm1hcCgoW2UsdF0pPT4iLCAiK2UrIjogIitKU09OLnN0cmluZ2lmeSh0KSkuam9pbigiIil9XSAke2kubWV0aG9kfSAke2h9ICR7dy5vaz8ic3VjY2VlZGVkIjoiZmFpbGVkIn0gd2l0aCBzdGF0dXMgJHt3LnN0YXR1c30gaW4gJHt5LW19bXNgO2lmKCF3Lm9rKXtjb25zdCBlPWF3YWl0IHRoaXMuc2hvdWxkUmV0cnkodyk7aWYodCYmZSl7Y29uc3QgZT1gcmV0cnlpbmcsICR7dH0gYXR0ZW1wdHMgcmVtYWluaW5nYDtyZXR1cm4gYXdhaXQgYXN5bmMgZnVuY3Rpb24oZSl7aWYobnVsbD09PWV8fCJvYmplY3QiIT10eXBlb2YgZSlyZXR1cm47aWYoZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0pcmV0dXJuIHZvaWQgYXdhaXQoZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKS5yZXR1cm4/LigpKTtjb25zdCB0PWUuZ2V0UmVhZGVyKCkscz10LmNhbmNlbCgpO3QucmVsZWFzZUxvY2soKSxhd2FpdCBzfSh3LmJvZHkpLFYodGhpcykuaW5mbyhgJHtifSAtICR7ZX1gKSxWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2UgZXJyb3IgKCR7ZX0pYCxYKHtyZXRyeU9mUmVxdWVzdExvZ0lEOnMsdXJsOncudXJsLHN0YXR1czp3LnN0YXR1cyxoZWFkZXJzOncuaGVhZGVycyxkdXJhdGlvbk1zOnktbX0pKSx0aGlzLnJldHJ5UmVxdWVzdChyLHQscz8/cCx3LmhlYWRlcnMpfWNvbnN0IG49ZT8iZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0IjoiZXJyb3I7IG5vdCByZXRyeWFibGUiO1YodGhpcykuaW5mbyhgJHtifSAtICR7bn1gKTtjb25zdCBvPWF3YWl0IHcudGV4dCgpLmNhdGNoKGU9PmEoZSkubWVzc2FnZSksaT1TKG8pLGM9aT92b2lkIDA6bzt0aHJvdyBWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2UgZXJyb3IgKCR7bn0pYCxYKHtyZXRyeU9mUmVxdWVzdExvZ0lEOnMsdXJsOncudXJsLHN0YXR1czp3LnN0YXR1cyxoZWFkZXJzOncuaGVhZGVycyxtZXNzYWdlOmMsZHVyYXRpb25NczpEYXRlLm5vdygpLW19KSksdGhpcy5tYWtlU3RhdHVzRXJyb3Iody5zdGF0dXMsaSxjLHcuaGVhZGVycyl9cmV0dXJuIFYodGhpcykuaW5mbyhiKSxWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2Ugc3RhcnRgLFgoe3JldHJ5T2ZSZXF1ZXN0TG9nSUQ6cyx1cmw6dy51cmwsc3RhdHVzOncuc3RhdHVzLGhlYWRlcnM6dy5oZWFkZXJzLGR1cmF0aW9uTXM6eS1tfSkpLHtyZXNwb25zZTp3LG9wdGlvbnM6cixjb250cm9sbGVyOmcscmVxdWVzdExvZ0lEOnAscmV0cnlPZlJlcXVlc3RMb2dJRDpzLHN0YXJ0VGltZTptfX1nZXRBUElMaXN0KGUsdCxzKXtyZXR1cm4gdGhpcy5yZXF1ZXN0QVBJTGlzdCh0LHttZXRob2Q6ImdldCIscGF0aDplLC4uLnN9KX1yZXF1ZXN0QVBJTGlzdChlLHQpe2NvbnN0IHM9dGhpcy5tYWtlUmVxdWVzdCh0LG51bGwsdm9pZCAwKTtyZXR1cm4gbmV3IGFlKHRoaXMscyxlKX1hc3luYyBmZXRjaFdpdGhUaW1lb3V0KGUsdCxzLHIpe2NvbnN0e3NpZ25hbDpuLG1ldGhvZDphLC4uLm99PXR8fHt9O24mJm4uYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLCgpPT5yLmFib3J0KCkpO2NvbnN0IGk9c2V0VGltZW91dCgoKT0+ci5hYm9ydCgpLHMpLGM9Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbSYmby5ib2R5IGluc3RhbmNlb2YgZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbXx8Im9iamVjdCI9PXR5cGVvZiBvLmJvZHkmJm51bGwhPT1vLmJvZHkmJlN5bWJvbC5hc3luY0l0ZXJhdG9yIGluIG8uYm9keSxsPXtzaWduYWw6ci5zaWduYWwsLi4uYz97ZHVwbGV4OiJoYWxmIn06e30sbWV0aG9kOiJHRVQiLC4uLm99O2EmJihsLm1ldGhvZD1hLnRvVXBwZXJDYXNlKCkpO3RyeXtyZXR1cm4gYXdhaXQgdGhpcy5mZXRjaC5jYWxsKHZvaWQgMCxlLGwpfWZpbmFsbHl7Y2xlYXJUaW1lb3V0KGkpfX1hc3luYyBzaG91bGRSZXRyeShlKXtjb25zdCB0PWUuaGVhZGVycy5nZXQoIngtc2hvdWxkLXJldHJ5Iik7cmV0dXJuInRydWUiPT09dHx8ImZhbHNlIiE9PXQmJig0MDg9PT1lLnN0YXR1c3x8NDA5PT09ZS5zdGF0dXN8fDQyOT09PWUuc3RhdHVzfHxlLnN0YXR1cz49NTAwKX1hc3luYyByZXRyeVJlcXVlc3QoZSx0LHMscil7bGV0IG47Y29uc3QgYT1yPy5nZXQoInJldHJ5LWFmdGVyLW1zIik7aWYoYSl7Y29uc3QgZT1wYXJzZUZsb2F0KGEpO051bWJlci5pc05hTihlKXx8KG49ZSl9Y29uc3Qgbz1yPy5nZXQoInJldHJ5LWFmdGVyIik7aWYobyYmIW4pe2NvbnN0IGU9cGFyc2VGbG9hdChvKTtuPU51bWJlci5pc05hTihlKT9EYXRlLnBhcnNlKG8pLURhdGUubm93KCk6MWUzKmV9aWYoIShuJiYwPD1uJiZuPDZlNCkpe2NvbnN0IHM9ZS5tYXhSZXRyaWVzPz90aGlzLm1heFJldHJpZXM7bj10aGlzLmNhbGN1bGF0ZURlZmF1bHRSZXRyeVRpbWVvdXRNaWxsaXModCxzKX12YXIgaTtyZXR1cm4gYXdhaXQoaT1uLG5ldyBQcm9taXNlKGU9PnNldFRpbWVvdXQoZSxpKSkpLHRoaXMubWFrZVJlcXVlc3QoZSx0LTEscyl9Y2FsY3VsYXRlRGVmYXVsdFJldHJ5VGltZW91dE1pbGxpcyhlLHQpe2NvbnN0IHM9dC1lO3JldHVybiBNYXRoLm1pbiguNSpNYXRoLnBvdygyLHMpLDgpKigxLS4yNSpNYXRoLnJhbmRvbSgpKSoxZTN9Y2FsY3VsYXRlTm9uc3RyZWFtaW5nVGltZW91dChlLHQpe2NvbnN0IHM9NmU1O2lmKDM2ZTUqZS8xMjhlMz5zfHxudWxsIT10JiZlPnQpdGhyb3cgbmV3IG8oIlN0cmVhbWluZyBpcyByZXF1aXJlZCBmb3Igb3BlcmF0aW9ucyB0aGF0IG1heSB0YWtlIGxvbmdlciB0aGFuIDEwIG1pbnV0ZXMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYW50aHJvcGljcy9hbnRocm9waWMtc2RrLXR5cGVzY3JpcHQjbG9uZy1yZXF1ZXN0cyBmb3IgbW9yZSBkZXRhaWxzIik7cmV0dXJuIHN9YXN5bmMgYnVpbGRSZXF1ZXN0KGUse3JldHJ5Q291bnQ6dD0wfT17fSl7Y29uc3Qgcz17Li4uZX0se21ldGhvZDpyLHBhdGg6bixxdWVyeTphLGRlZmF1bHRCYXNlVVJMOml9PXMsYz10aGlzLmJ1aWxkVVJMKG4sYSxpKTsidGltZW91dCJpbiBzJiYoKGUsdCk9PntpZigibnVtYmVyIiE9dHlwZW9mIHR8fCFOdW1iZXIuaXNJbnRlZ2VyKHQpKXRocm93IG5ldyBvKGAke2V9IG11c3QgYmUgYW4gaW50ZWdlcmApO2lmKHQ8MCl0aHJvdyBuZXcgbyhgJHtlfSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlcmApfSkoInRpbWVvdXQiLHMudGltZW91dCkscy50aW1lb3V0PXMudGltZW91dD8/dGhpcy50aW1lb3V0O2NvbnN0e2JvZHlIZWFkZXJzOmwsYm9keTpkfT10aGlzLmJ1aWxkQm9keSh7b3B0aW9uczpzfSk7cmV0dXJue3JlcTp7bWV0aG9kOnIsaGVhZGVyczphd2FpdCB0aGlzLmJ1aWxkSGVhZGVycyh7b3B0aW9uczplLG1ldGhvZDpyLGJvZHlIZWFkZXJzOmwscmV0cnlDb3VudDp0fSksLi4ucy5zaWduYWwmJntzaWduYWw6cy5zaWduYWx9LC4uLmdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0mJmQgaW5zdGFuY2VvZiBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtJiZ7ZHVwbGV4OiJoYWxmIn0sLi4uZCYme2JvZHk6ZH0sLi4udGhpcy5mZXRjaE9wdGlvbnM/P3t9LC4uLnMuZmV0Y2hPcHRpb25zPz97fX0sdXJsOmMsdGltZW91dDpzLnRpbWVvdXR9fWFzeW5jIGJ1aWxkSGVhZGVycyh7b3B0aW9uczplLG1ldGhvZDp0LGJvZHlIZWFkZXJzOnMscmV0cnlDb3VudDpyfSl7bGV0IG49e307dGhpcy5pZGVtcG90ZW5jeUhlYWRlciYmImdldCIhPT10JiYoZS5pZGVtcG90ZW5jeUtleXx8KGUuaWRlbXBvdGVuY3lLZXk9dGhpcy5kZWZhdWx0SWRlbXBvdGVuY3lLZXkoKSksblt0aGlzLmlkZW1wb3RlbmN5SGVhZGVyXT1lLmlkZW1wb3RlbmN5S2V5KTtjb25zdCBhPV9lKFtuLHtBY2NlcHQ6ImFwcGxpY2F0aW9uL2pzb24iLCJVc2VyLUFnZW50Ijp0aGlzLmdldFVzZXJBZ2VudCgpLCJYLVN0YWlubGVzcy1SZXRyeS1Db3VudCI6U3RyaW5nKHIpLC4uLmUudGltZW91dD97IlgtU3RhaW5sZXNzLVRpbWVvdXQiOlN0cmluZyhNYXRoLnRydW5jKGUudGltZW91dC8xZTMpKX06e30sLi4ueD8/KHg9UCgpKSwuLi50aGlzLl9vcHRpb25zLmRhbmdlcm91c2x5QWxsb3dCcm93c2VyP3siYW50aHJvcGljLWRhbmdlcm91cy1kaXJlY3QtYnJvd3Nlci1hY2Nlc3MiOiJ0cnVlIn06dm9pZCAwLCJhbnRocm9waWMtdmVyc2lvbiI6IjIwMjMtMDYtMDEifSxhd2FpdCB0aGlzLmF1dGhIZWFkZXJzKGUpLHRoaXMuX29wdGlvbnMuZGVmYXVsdEhlYWRlcnMscyxlLmhlYWRlcnNdKTtyZXR1cm4gdGhpcy52YWxpZGF0ZUhlYWRlcnMoYSksYS52YWx1ZXN9YnVpbGRCb2R5KHtvcHRpb25zOntib2R5OmUsaGVhZGVyczp0fX0pe2lmKCFlKXJldHVybntib2R5SGVhZGVyczp2b2lkIDAsYm9keTp2b2lkIDB9O2NvbnN0IHI9X2UoW3RdKTtyZXR1cm4gQXJyYXlCdWZmZXIuaXNWaWV3KGUpfHxlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXJ8fGUgaW5zdGFuY2VvZiBEYXRhVmlld3x8InN0cmluZyI9PXR5cGVvZiBlJiZyLnZhbHVlcy5oYXMoImNvbnRlbnQtdHlwZSIpfHxnbG9iYWxUaGlzLkJsb2ImJmUgaW5zdGFuY2VvZiBnbG9iYWxUaGlzLkJsb2J8fGUgaW5zdGFuY2VvZiBGb3JtRGF0YXx8ZSBpbnN0YW5jZW9mIFVSTFNlYXJjaFBhcmFtc3x8Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbSYmZSBpbnN0YW5jZW9mIGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0/e2JvZHlIZWFkZXJzOnZvaWQgMCxib2R5OmV9OiJvYmplY3QiPT10eXBlb2YgZSYmKFN5bWJvbC5hc3luY0l0ZXJhdG9yIGluIGV8fFN5bWJvbC5pdGVyYXRvciBpbiBlJiYibmV4dCJpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZS5uZXh0KT97Ym9keUhlYWRlcnM6dm9pZCAwLGJvZHk6QShlKX06cyh0aGlzLG5zLCJmIikuY2FsbCh0aGlzLHtib2R5OmUsaGVhZGVyczpyfSl9fXJzPWNzLG5zPW5ldyBXZWFrTWFwLHNzPW5ldyBXZWFrU2V0LGFzPWZ1bmN0aW9uKCl7cmV0dXJuImh0dHBzOi8vYXBpLmFudGhyb3BpYy5jb20iIT09dGhpcy5iYXNlVVJMfSxjcy5BbnRocm9waWM9cnMsY3MuSFVNQU5fUFJPTVBUPSJcXG5cXG5IdW1hbjoiLGNzLkFJX1BST01QVD0iXFxuXFxuQXNzaXN0YW50OiIsY3MuREVGQVVMVF9USU1FT1VUPTZlNSxjcy5BbnRocm9waWNFcnJvcj1vLGNzLkFQSUVycm9yPWksY3MuQVBJQ29ubmVjdGlvbkVycm9yPWwsY3MuQVBJQ29ubmVjdGlvblRpbWVvdXRFcnJvcj1kLGNzLkFQSVVzZXJBYm9ydEVycm9yPWMsY3MuTm90Rm91bmRFcnJvcj1mLGNzLkNvbmZsaWN0RXJyb3I9bSxjcy5SYXRlTGltaXRFcnJvcj13LGNzLkJhZFJlcXVlc3RFcnJvcj1oLGNzLkF1dGhlbnRpY2F0aW9uRXJyb3I9dSxjcy5JbnRlcm5hbFNlcnZlckVycm9yPXksY3MuUGVybWlzc2lvbkRlbmllZEVycm9yPXAsY3MuVW5wcm9jZXNzYWJsZUVudGl0eUVycm9yPWcsY3MudG9GaWxlPWFzeW5jIGZ1bmN0aW9uKGUsdCxzKXtpZihjZSgpLGU9YXdhaXQgZSx0fHwodD1kZShlKSksKGU9Pm51bGwhPWUmJiJvYmplY3QiPT10eXBlb2YgZSYmInN0cmluZyI9PXR5cGVvZiBlLm5hbWUmJiJudW1iZXIiPT10eXBlb2YgZS5sYXN0TW9kaWZpZWQmJmdlKGUpKShlKSlyZXR1cm4gZSBpbnN0YW5jZW9mIEZpbGUmJm51bGw9PXQmJm51bGw9PXM/ZTpsZShbYXdhaXQgZS5hcnJheUJ1ZmZlcigpXSx0Pz9lLm5hbWUse3R5cGU6ZS50eXBlLGxhc3RNb2RpZmllZDplLmxhc3RNb2RpZmllZCwuLi5zfSk7aWYoKGU9Pm51bGwhPWUmJiJvYmplY3QiPT10eXBlb2YgZSYmInN0cmluZyI9PXR5cGVvZiBlLnVybCYmImZ1bmN0aW9uIj09dHlwZW9mIGUuYmxvYikoZSkpe2NvbnN0IHI9YXdhaXQgZS5ibG9iKCk7cmV0dXJuIHR8fCh0PW5ldyBVUkwoZS51cmwpLnBhdGhuYW1lLnNwbGl0KC9bXFwvXS8pLnBvcCgpKSxsZShhd2FpdCB3ZShyKSx0LHMpfWNvbnN0IHI9YXdhaXQgd2UoZSk7aWYoIXM/LnR5cGUpe2NvbnN0IGU9ci5maW5kKGU9PiJvYmplY3QiPT10eXBlb2YgZSYmInR5cGUiaW4gZSYmZS50eXBlKTsic3RyaW5nIj09dHlwZW9mIGUmJihzPXsuLi5zLHR5cGU6ZX0pfXJldHVybiBsZShyLHQscyl9O2NsYXNzIGxzIGV4dGVuZHMgY3N7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMuY29tcGxldGlvbnM9bmV3IFB0KHRoaXMpLHRoaXMubWVzc2FnZXM9bmV3IFF0KHRoaXMpLHRoaXMubW9kZWxzPW5ldyBlcyh0aGlzKSx0aGlzLmJldGE9bmV3IE10KHRoaXMpfX1scy5Db21wbGV0aW9ucz1QdCxscy5NZXNzYWdlcz1RdCxscy5Nb2RlbHM9ZXMsbHMuQmV0YT1NdDtjbGFzcyBkc3t2YWxpZGF0ZU1vZGVsKGUpe2lmKG51bGw9PT10aGlzLmF2YWlsYWJsZU1vZGVsc3x8MD09PXRoaXMuYXZhaWxhYmxlTW9kZWxzLmxlbmd0aClyZXR1cm4hMDtpZighdGhpcy5hdmFpbGFibGVNb2RlbHMuaW5jbHVkZXMoZSkpdGhyb3cgbmV3IEVycm9yKGBNb2RlbCAnJHtlfScgaXMgbm90IGF2YWlsYWJsZSBmb3IgcHJvdmlkZXIgJyR7dGhpcy5uYW1lfScuIEF2YWlsYWJsZSBtb2RlbHM6ICR7dGhpcy5hdmFpbGFibGVNb2RlbHMuam9pbigiLCAiKX1gKTtyZXR1cm4hMH12YWxpZGF0ZVJlcXVlc3QoZSl7aWYoIWUubW9kZWx8fDA9PT1lLm1vZGVsLnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJNb2RlbCBpcyByZXF1aXJlZCIpO2lmKCFlLm1lc3NhZ2VzfHwwPT09ZS5tZXNzYWdlcy5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJNZXNzYWdlcyBhcnJheSBpcyByZXF1aXJlZCBhbmQgbXVzdCBub3QgYmUgZW1wdHkiKTtpZih2b2lkIDAhPT1lLm1heF90b2tlbnMmJmUubWF4X3Rva2Vuczw9MCl0aHJvdyBuZXcgRXJyb3IoIm1heF90b2tlbnMgbXVzdCBiZSBwb3NpdGl2ZSIpO2lmKHZvaWQgMCE9PWUudGVtcGVyYXR1cmUmJihlLnRlbXBlcmF0dXJlPDB8fGUudGVtcGVyYXR1cmU+MikpdGhyb3cgbmV3IEVycm9yKCJ0ZW1wZXJhdHVyZSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMiIpO3RoaXMudmFsaWRhdGVNb2RlbChlLm1vZGVsKX12YWxpZGF0ZUNyZWRlbnRpYWxzU3RydWN0dXJlKGUpe2lmKCFlfHwhZS5hcGlLZXkpdGhyb3cgbmV3IEVycm9yKCJBUEkga2V5IGlzIHJlcXVpcmVkIik7aWYoInN0cmluZyIhPXR5cGVvZiBlLmFwaUtleXx8MD09PWUuYXBpS2V5LnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJBUEkga2V5IG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nIil9fWNsYXNzIGhzIGV4dGVuZHMgZHN7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMubmFtZT0iYW50aHJvcGljIix0aGlzLl9hdmFpbGFibGVNb2RlbHM9bnVsbCx0aGlzLmRlZmF1bHRNb2RlbHM9bnVsbH1nZXQgYXZhaWxhYmxlTW9kZWxzKCl7cmV0dXJuIHRoaXMuX2F2YWlsYWJsZU1vZGVsc31hc3luYyBmZXRjaEF2YWlsYWJsZU1vZGVscyhlKXt0aGlzLnZhbGlkYXRlQ3JlZGVudGlhbHNTdHJ1Y3R1cmUoZSk7dHJ5e2NvbnN0IHQ9bmV3IGxzKHthcGlLZXk6ZS5hcGlLZXksZGFuZ2Vyb3VzbHlBbGxvd0Jyb3dzZXI6ITB9KSxzPShhd2FpdCB0Lm1vZGVscy5saXN0KCkpLmRhdGE7cmV0dXJuIHRoaXMuX2F2YWlsYWJsZU1vZGVscz1zLm1hcChlPT5lLmlkKSxzfWNhdGNoKGUpe3Rocm93IGNvbnNvbGUuZXJyb3IoIkZhaWxlZCB0byBmZXRjaCBtb2RlbHMgZnJvbSBBbnRocm9waWMgQVBJOiIsZSksbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggYXZhaWxhYmxlIG1vZGVsczogJHtlPy5tZXNzYWdlfHwiVW5rbm93biBlcnJvciJ9YCl9fWdldExhdGVzdE1vZGVsQnlGYW1pbHkoZSx0KXtjb25zdCBzPWUuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0LnRvTG93ZXJDYXNlKCkpKTtpZigwIT09cy5sZW5ndGgpcmV0dXJuIHMuc29ydCgoZSx0KT0+e2NvbnN0IHM9bmV3IERhdGUoZS5jcmVhdGVkX2F0KS5nZXRUaW1lKCk7cmV0dXJuIG5ldyBEYXRlKHQuY3JlYXRlZF9hdCkuZ2V0VGltZSgpLXN9KSxzWzBdLmlkfWFzeW5jIHZhbGlkYXRlQ3JlZGVudGlhbHMoZSl7dGhpcy52YWxpZGF0ZUNyZWRlbnRpYWxzU3RydWN0dXJlKGUpO3RyeXtyZXR1cm4gYXdhaXQgdGhpcy5mZXRjaEF2YWlsYWJsZU1vZGVscyhlKSwhMH1jYXRjaChlKXtpZig0MDE9PT1lPy5zdGF0dXN8fGU/Lm1lc3NhZ2U/LmluY2x1ZGVzKCJhdXRoZW50aWNhdGlvbiIpKXRocm93IG5ldyBFcnJvcigiSW52YWxpZCBBUEkga2V5Iik7dGhyb3cgbmV3IEVycm9yKGBDcmVkZW50aWFsIHZhbGlkYXRpb24gZmFpbGVkOiAke2U/Lm1lc3NhZ2V8fCJVbmtub3duIGVycm9yIn1gKX19YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe3RoaXMudmFsaWRhdGVSZXF1ZXN0KGUpLHRoaXMudmFsaWRhdGVDcmVkZW50aWFsc1N0cnVjdHVyZSh0KTtjb25zdCByPW5ldyBscyh7YXBpS2V5OnQuYXBpS2V5LGRhbmdlcm91c2x5QWxsb3dCcm93c2VyOiEwfSk7dHJ5e3JldHVybiBlLnN0cmVhbSYmcz9hd2FpdCB0aGlzLmhhbmRsZVN0cmVhbWluZ1JlcXVlc3QocixlLHMpOmF3YWl0IHRoaXMuaGFuZGxlTm9uU3RyZWFtaW5nUmVxdWVzdChyLGUpfWNhdGNoKGUpe3Rocm93IHRoaXMuaGFuZGxlRXJyb3IoZSl9fWFzeW5jIGhhbmRsZU5vblN0cmVhbWluZ1JlcXVlc3QoZSx0KXtjb25zdCBzPWF3YWl0IGUubWVzc2FnZXMuY3JlYXRlKHttb2RlbDp0Lm1vZGVsLG1heF90b2tlbnM6dC5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOnQudGVtcGVyYXR1cmUsc3lzdGVtOnQuc3lzdGVtLG1lc3NhZ2VzOnQubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKX0pLHI9cy5jb250ZW50LmZpbmQoZT0+InRleHQiPT09ZS50eXBlKTtyZXR1cm57Y29udGVudDpyJiYidGV4dCJpbiByP3IudGV4dDoiIixtb2RlbDpzLm1vZGVsLHByb3ZpZGVyOiJhbnRocm9waWMiLHVzYWdlOntpbnB1dF90b2tlbnM6cy51c2FnZS5pbnB1dF90b2tlbnMsb3V0cHV0X3Rva2VuczpzLnVzYWdlLm91dHB1dF90b2tlbnN9LHN0b3BfcmVhc29uOnMuc3RvcF9yZWFzb24/P3ZvaWQgMH19YXN5bmMgaGFuZGxlU3RyZWFtaW5nUmVxdWVzdChlLHQscyl7Y29uc3Qgcj1hd2FpdCBlLm1lc3NhZ2VzLmNyZWF0ZSh7bW9kZWw6dC5tb2RlbCxtYXhfdG9rZW5zOnQubWF4X3Rva2Vucz8/NDA5Nix0ZW1wZXJhdHVyZTp0LnRlbXBlcmF0dXJlLHN5c3RlbTp0LnN5c3RlbSxtZXNzYWdlczp0Lm1lc3NhZ2VzLmZpbHRlcihlPT4ic3lzdGVtIiE9PWUucm9sZSkubWFwKGU9Pih7cm9sZTplLnJvbGUsY29udGVudDplLmNvbnRlbnR9KSksc3RyZWFtOiEwfSk7bGV0IG4sYT0iIixvPXQubW9kZWwsaT0wLGM9MDtmb3IgYXdhaXQoY29uc3QgZSBvZiByKWlmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSlvPWUubWVzc2FnZS5tb2RlbCxpPWUubWVzc2FnZS51c2FnZS5pbnB1dF90b2tlbnM7ZWxzZSBpZigiY29udGVudF9ibG9ja19kZWx0YSI9PT1lLnR5cGUpe2lmKCJ0ZXh0X2RlbHRhIj09PWUuZGVsdGEudHlwZSl7Y29uc3QgdD1lLmRlbHRhLnRleHQ7YSs9dCxzKHQpfX1lbHNlIm1lc3NhZ2VfZGVsdGEiPT09ZS50eXBlJiYoYz1lLnVzYWdlLm91dHB1dF90b2tlbnMsbj1lLmRlbHRhLnN0b3BfcmVhc29uPz92b2lkIDApO3JldHVybntjb250ZW50OmEsbW9kZWw6byxwcm92aWRlcjoiYW50aHJvcGljIix1c2FnZTp7aW5wdXRfdG9rZW5zOmksb3V0cHV0X3Rva2VuczpjfSxzdG9wX3JlYXNvbjpufX1oYW5kbGVFcnJvcihlKXtyZXR1cm4gNDAxPT09ZT8uc3RhdHVzP25ldyBFcnJvcigiSW52YWxpZCBBUEkga2V5IG9yIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCIpOjQyOT09PWU/LnN0YXR1cz9uZXcgRXJyb3IoIlJhdGUgbGltaXQgZXhjZWVkZWQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuIik6NDAwPT09ZT8uc3RhdHVzP25ldyBFcnJvcihgQmFkIHJlcXVlc3Q6ICR7ZT8ubWVzc2FnZXx8IkludmFsaWQgcGFyYW1ldGVycyJ9YCk6NTAwPT09ZT8uc3RhdHVzP25ldyBFcnJvcigiQW50aHJvcGljIEFQSSBlcnJvci4gUGxlYXNlIHRyeSBhZ2Fpbi4iKTpuZXcgRXJyb3IoYEFQSSByZXF1ZXN0IGZhaWxlZDogJHtlPy5tZXNzYWdlfHwiVW5rbm93biBlcnJvciJ9YCl9fWNsYXNzIHVzIGV4dGVuZHMgZHN7Y29uc3RydWN0b3IoZSl7c3VwZXIoKSx0aGlzLm5hbWU9ImFudGhyb3BpYyIsdGhpcy5fYXZhaWxhYmxlTW9kZWxzPW51bGwsdGhpcy5kZWZhdWx0TW9kZWxzPW51bGwsdGhpcy5zZXJ2ZXJVcmw9ZS5jcmVkZW50aWFsU2VydmVyVXJsLnJlcGxhY2UoL1wvJC8sIiIpfWdldCBhdmFpbGFibGVNb2RlbHMoKXtyZXR1cm4gdGhpcy5fYXZhaWxhYmxlTW9kZWxzfWFzeW5jIGNoZWNrQXV0aFN0YXR1cygpe3JldHVybihhd2FpdCBmZXRjaChgJHt0aGlzLnNlcnZlclVybH0vc3RhdHVzYCx7bWV0aG9kOiJHRVQiLGNyZWRlbnRpYWxzOiJpbmNsdWRlIn0pKS5qc29uKCl9Z2V0U2V0dXBVcmwoKXtyZXR1cm5gJHt0aGlzLnNlcnZlclVybH0vc2V0dXBgfWFzeW5jIGZldGNoQXZhaWxhYmxlTW9kZWxzKGUpe3RyeXtjb25zdCBlPWF3YWl0IGZldGNoKGAke3RoaXMuc2VydmVyVXJsfS9wcm94eT9wYXRoPS92MS9tb2RlbHNgLHttZXRob2Q6IkdFVCIsY3JlZGVudGlhbHM6ImluY2x1ZGUifSk7aWYoIWUub2spdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggbW9kZWxzOiBIVFRQICR7ZS5zdGF0dXN9YCk7Y29uc3QgdD0oKGF3YWl0IGUuanNvbigpKS5kYXRhfHxbXSkubWFwKGU9Pih7aWQ6ZS5pZCxkaXNwbGF5X25hbWU6ZS5kaXNwbGF5X25hbWV8fGUuaWQsY3JlYXRlZF9hdDplLmNyZWF0ZWRfYXR8fChuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSx0eXBlOmUudHlwZXx8Im1vZGVsIn0pKTtyZXR1cm4gdGhpcy5fYXZhaWxhYmxlTW9kZWxzPXQubWFwKGU9PmUuaWQpLHR9Y2F0Y2goZSl7dGhyb3cgY29uc29sZS5lcnJvcigiW1Byb3hpZWRBbnRocm9waWNQcm92aWRlcl0gRmFpbGVkIHRvIGZldGNoIG1vZGVscyBmcm9tIEFQSToiLGUubWVzc2FnZSksbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggYXZhaWxhYmxlIG1vZGVsczogJHtlLm1lc3NhZ2V9YCl9fWdldExhdGVzdE1vZGVsQnlGYW1pbHkoZSx0KXtjb25zdCBzPWUuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0LnRvTG93ZXJDYXNlKCkpKTtpZigwIT09cy5sZW5ndGgpcmV0dXJuIHMuc29ydCgoZSx0KT0+e2NvbnN0IHM9bmV3IERhdGUoZS5jcmVhdGVkX2F0KS5nZXRUaW1lKCk7cmV0dXJuIG5ldyBEYXRlKHQuY3JlYXRlZF9hdCkuZ2V0VGltZSgpLXN9KSxzWzBdLmlkfWFzeW5jIHZhbGlkYXRlQ3JlZGVudGlhbHMoZSl7cmV0dXJuKGF3YWl0IHRoaXMuY2hlY2tBdXRoU3RhdHVzKCkpLmF1dGhlbnRpY2F0ZWR9YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe2lmKHRoaXMudmFsaWRhdGVSZXF1ZXN0KGUpLCEoYXdhaXQgdGhpcy5jaGVja0F1dGhTdGF0dXMoKSkuYXV0aGVudGljYXRlZCl0aHJvdyBuZXcgRXJyb3IoYE5vdCBhdXRoZW50aWNhdGVkLiBQbGVhc2UgdmlzaXQgJHt0aGlzLmdldFNldHVwVXJsKCl9IHRvIHNldCB1cCB5b3VyIEFQSSBrZXkuYCk7dHJ5e3JldHVybiBlLnN0cmVhbSYmcz9hd2FpdCB0aGlzLmhhbmRsZVN0cmVhbWluZ1JlcXVlc3QoZSxzKTphd2FpdCB0aGlzLmhhbmRsZU5vblN0cmVhbWluZ1JlcXVlc3QoZSl9Y2F0Y2goZSl7dGhyb3cgdGhpcy5oYW5kbGVFcnJvcihlKX19YXN5bmMgaGFuZGxlTm9uU3RyZWFtaW5nUmVxdWVzdChlKXtjb25zdCB0PXttb2RlbDplLm1vZGVsLG1heF90b2tlbnM6ZS5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOmUudGVtcGVyYXR1cmUsc3lzdGVtOmUuc3lzdGVtLG1lc3NhZ2VzOmUubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKX0scz1hd2FpdCBmZXRjaChgJHt0aGlzLnNlcnZlclVybH0vcHJveHk/cGF0aD0vdjEvbWVzc2FnZXNgLHttZXRob2Q6IlBPU1QiLGhlYWRlcnM6eyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIn0sY3JlZGVudGlhbHM6ImluY2x1ZGUiLGJvZHk6SlNPTi5zdHJpbmdpZnkodCl9KTtpZighcy5vayl7Y29uc3QgZT1hd2FpdCBzLmpzb24oKS5jYXRjaCgoKT0+KHtlcnJvcjoiVW5rbm93biBlcnJvciJ9KSk7dGhyb3cgbmV3IEVycm9yKGUuZXJyb3I/Lm1lc3NhZ2V8fGUuZXJyb3J8fGBIVFRQICR7cy5zdGF0dXN9YCl9Y29uc3Qgcj1hd2FpdCBzLmpzb24oKSxuPXIuY29udGVudD8uZmluZChlPT4idGV4dCI9PT1lLnR5cGUpO3JldHVybntjb250ZW50Om4mJiJ0ZXh0ImluIG4/bi50ZXh0OiIiLG1vZGVsOnIubW9kZWwscHJvdmlkZXI6ImFudGhyb3BpYyIsdXNhZ2U6e2lucHV0X3Rva2VuczpyLnVzYWdlPy5pbnB1dF90b2tlbnN8fDAsb3V0cHV0X3Rva2VuczpyLnVzYWdlPy5vdXRwdXRfdG9rZW5zfHwwfSxzdG9wX3JlYXNvbjpyLnN0b3BfcmVhc29uPz92b2lkIDB9fWFzeW5jIGhhbmRsZVN0cmVhbWluZ1JlcXVlc3QoZSx0KXtjb25zdCBzPXttb2RlbDplLm1vZGVsLG1heF90b2tlbnM6ZS5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOmUudGVtcGVyYXR1cmUsc3lzdGVtOmUuc3lzdGVtLG1lc3NhZ2VzOmUubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKSxzdHJlYW06ITB9LHI9YXdhaXQgZmV0Y2goYCR7dGhpcy5zZXJ2ZXJVcmx9L3Byb3h5P3BhdGg9L3YxL21lc3NhZ2VzYCx7bWV0aG9kOiJQT1NUIixoZWFkZXJzOnsiQ29udGVudC1UeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LGNyZWRlbnRpYWxzOiJpbmNsdWRlIixib2R5OkpTT04uc3RyaW5naWZ5KHMpfSk7aWYoIXIub2spe2NvbnN0IGU9YXdhaXQgci5qc29uKCkuY2F0Y2goKCk9Pih7ZXJyb3I6IlVua25vd24gZXJyb3IifSkpO3Rocm93IG5ldyBFcnJvcihlLmVycm9yPy5tZXNzYWdlfHxlLmVycm9yfHxgSFRUUCAke3Iuc3RhdHVzfWApfWNvbnN0IG49ci5ib2R5Py5nZXRSZWFkZXIoKTtpZighbil0aHJvdyBuZXcgRXJyb3IoIlN0cmVhbWluZyBub3Qgc3VwcG9ydGVkIik7Y29uc3QgYT1uZXcgVGV4dERlY29kZXI7bGV0IG8saT0iIixjPWUubW9kZWwsbD0wLGQ9MDt0cnl7Zm9yKDs7KXtjb25zdHtkb25lOmUsdmFsdWU6c309YXdhaXQgbi5yZWFkKCk7aWYoZSlicmVhaztjb25zdCByPWEuZGVjb2RlKHMse3N0cmVhbTohMH0pLnNwbGl0KCJcbiIpO2Zvcihjb25zdCBlIG9mIHIpaWYoZS5zdGFydHNXaXRoKCJkYXRhOiAiKSl7Y29uc3Qgcz1lLnNsaWNlKDYpO2lmKCJbRE9ORV0iPT09cyljb250aW51ZTt0cnl7Y29uc3QgZT1KU09OLnBhcnNlKHMpO2lmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSljPWUubWVzc2FnZS5tb2RlbCxsPWUubWVzc2FnZS51c2FnZT8uaW5wdXRfdG9rZW5zfHwwO2Vsc2UgaWYoImNvbnRlbnRfYmxvY2tfZGVsdGEiPT09ZS50eXBlKXtpZigidGV4dF9kZWx0YSI9PT1lLmRlbHRhPy50eXBlKXtjb25zdCBzPWUuZGVsdGEudGV4dDtpKz1zLHQocyl9fWVsc2UibWVzc2FnZV9kZWx0YSI9PT1lLnR5cGUmJihkPWUudXNhZ2U/Lm91dHB1dF90b2tlbnN8fDAsbz1lLmRlbHRhPy5zdG9wX3JlYXNvbj8/dm9pZCAwKX1jYXRjaHt9fX19ZmluYWxseXtuLnJlbGVhc2VMb2NrKCl9cmV0dXJue2NvbnRlbnQ6aSxtb2RlbDpjLHByb3ZpZGVyOiJhbnRocm9waWMiLHVzYWdlOntpbnB1dF90b2tlbnM6bCxvdXRwdXRfdG9rZW5zOmR9LHN0b3BfcmVhc29uOm99fWhhbmRsZUVycm9yKGUpe2NvbnN0IHQ9ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IiO3JldHVybiB0LmluY2x1ZGVzKCI0MDEiKXx8dC5pbmNsdWRlcygiYXV0aGVudGljYXRpb24iKT9uZXcgRXJyb3IoYE5vdCBhdXRoZW50aWNhdGVkLiBQbGVhc2UgdmlzaXQgJHt0aGlzLmdldFNldHVwVXJsKCl9IHRvIHNldCB1cCB5b3VyIEFQSSBrZXkuYCk6dC5pbmNsdWRlcygiNDI5Iik/bmV3IEVycm9yKCJSYXRlIGxpbWl0IGV4Y2VlZGVkLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLiIpOnQuaW5jbHVkZXMoIjQwMCIpP25ldyBFcnJvcihgQmFkIHJlcXVlc3Q6ICR7dH1gKTpuZXcgRXJyb3IoYEFQSSByZXF1ZXN0IGZhaWxlZDogJHt0fWApfX1jbGFzcyBwc3tjb25zdHJ1Y3RvcihlLHQscyl7dGhpcy5pc0luaXRpYWxpemVkPSExLHRoaXMuZm9yY2VMb2NhbE1vZGU9ITEsdGhpcy5jb25maWdNYW5hZ2VyPWUsdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsPXQsdGhpcy5hbGxvd0xvY2FsTW9kZT1zPz8hMX1zZXRQcm9tcHRIYW5kbGVyKGUpe3RoaXMucHJvbXB0SGFuZGxlcj1lfXN0YXRpYyBnZXRJbnN0YW5jZShlLHQscyl7aWYoIXBzLmluc3RhbmNlKXtpZighZSl0aHJvdyBuZXcgRXJyb3IoIkNvbmZpZ01hbmFnZXIgcmVxdWlyZWQgZm9yIGZpcnN0IGluaXRpYWxpemF0aW9uIik7cHMuaW5zdGFuY2U9bmV3IHBzKGUsdCxzKX1yZXR1cm4gcHMuaW5zdGFuY2V9aXNQcm94aWVkTW9kZSgpe3JldHVybiEhdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsJiYhdGhpcy5mb3JjZUxvY2FsTW9kZX1pc0xvY2FsTW9kZUFsbG93ZWQoKXtyZXR1cm4gdGhpcy5hbGxvd0xvY2FsTW9kZX1pc0xvY2FsTW9kZUZvcmNlZCgpe3JldHVybiB0aGlzLmZvcmNlTG9jYWxNb2RlfWFzeW5jIHNldEZvcmNlTG9jYWxNb2RlKGUpe2lmKHRoaXMuZm9yY2VMb2NhbE1vZGUhPT1lKXtpZih0aGlzLmZvcmNlTG9jYWxNb2RlPWUsYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnNldEZvcmNlTG9jYWxNb2RlKGUpLHRoaXMuY3JlZGVudGlhbHM9dm9pZCAwLHRoaXMud2VpZ2h0TWFwcGVyKXtjb25zdCBlPXRoaXMud2VpZ2h0TWFwcGVyLmdldFByb3ZpZGVyKCk7dGhpcy5wcm92aWRlcj10aGlzLmNyZWF0ZVByb3ZpZGVyKGUpfWNvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIFN3aXRjaGVkIG1vZGUiLHtmb3JjZUxvY2FsTW9kZTplLGlzUHJveGllZE1vZGU6dGhpcy5pc1Byb3hpZWRNb2RlKCl9KX19YXN5bmMgY29uZmlndXJlTG9jYWwodCxzLHI9ITApe3RoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCksdGhpcy5mb3JjZUxvY2FsTW9kZT0hMCxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuc2F2ZUxvY2FsKHQscyxyKSx0aGlzLnByb3ZpZGVyPXRoaXMuY3JlYXRlUHJvdmlkZXIodC5wcm92aWRlciksdGhpcy53ZWlnaHRNYXBwZXI9bmV3IGUodC5wcm92aWRlcix0Lm1vZGVscyksdC5jcmVkZW50aWFscyYmKHRoaXMuY3JlZGVudGlhbHM9dC5jcmVkZW50aWFscyksY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gQ29uZmlndXJlZCBsb2NhbCBtb2RlIix7cHJvdmlkZXI6dC5wcm92aWRlcixoYXNQYXNzd29yZDohIXN9KX1nZXRDcmVkZW50aWFsU2VydmVyU2V0dXBVcmwoKXtyZXR1cm4gdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsP2Ake3RoaXMuY3JlZGVudGlhbFNlcnZlclVybH0vc2V0dXBgOm51bGx9YXN5bmMgZmV0Y2hBdmFpbGFibGVNb2RlbHMoKXtpZihhd2FpdCB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCksIXRoaXMucHJvdmlkZXIpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBub3QgY29uZmlndXJlZCIpO2NvbnN0IGU9dGhpcy5jcmVkZW50aWFsc3x8e2FwaUtleToicHJveGllZCJ9O2NvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIEZldGNoaW5nIGF2YWlsYWJsZSBtb2RlbHMgZnJvbSBwcm92aWRlciIpO2NvbnN0IHQ9YXdhaXQgdGhpcy5wcm92aWRlci5mZXRjaEF2YWlsYWJsZU1vZGVscyhlKTtyZXR1cm4gY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gRmV0Y2hlZCBtb2RlbHM6Iix0Lm1hcChlPT5lLmlkKSksdH1hc3luYyBlbnN1cmVJbml0aWFsaXplZCgpe3RoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCl9YXN5bmMgaW5pdGlhbGl6ZSgpe2lmKHRoaXMuaXNJbml0aWFsaXplZClyZXR1cm4gdm9pZCBjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBBbHJlYWR5IGluaXRpYWxpemVkLCBza2lwcGluZyIpO3RoaXMuZm9yY2VMb2NhbE1vZGU9YXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLmdldEZvcmNlTG9jYWxNb2RlKCksY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gSW5pdGlhbGl6aW5nLi4uIix7aXNQcm94aWVkTW9kZTp0aGlzLmlzUHJveGllZE1vZGUoKSxjcmVkZW50aWFsU2VydmVyVXJsOnRoaXMuY3JlZGVudGlhbFNlcnZlclVybCxmb3JjZUxvY2FsTW9kZTp0aGlzLmZvcmNlTG9jYWxNb2RlLGFsbG93TG9jYWxNb2RlOnRoaXMuYWxsb3dMb2NhbE1vZGV9KTtjb25zdCB0PWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5sb2FkTWV0YWRhdGEoKTtpZihjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBMb2FkZWQgbWV0YWRhdGE6Iix0KSx0KXtjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBVc2luZyBleGlzdGluZyBtZXRhZGF0YSIpLHRoaXMucHJvdmlkZXI9dGhpcy5jcmVhdGVQcm92aWRlcih0LnByb3ZpZGVyKSx0aGlzLndlaWdodE1hcHBlcj1uZXcgZSh0LnByb3ZpZGVyLHQubW9kZWxzKTtjb25zdCBzPWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5nZXRQbGFpbnRleHRDcmVkZW50aWFscygpO3M/KGNvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIFVzaW5nIHBsYWludGV4dCBjcmVkZW50aWFscyAobG9jYWwgZGV2IG1vZGUpIiksdGhpcy5jcmVkZW50aWFscz1zKTp0aGlzLmlzUHJveGllZE1vZGUoKSYmKHRoaXMuY3JlZGVudGlhbHM9e2FwaUtleToicHJveGllZCJ9KX1lbHNlIHRoaXMuaXNQcm94aWVkTW9kZSgpPyhjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBObyBtZXRhZGF0YSwgaW5pdGlhbGl6aW5nIHByb3hpZWQgZGVmYXVsdHMiKSxhd2FpdCB0aGlzLmluaXRpYWxpemVQcm94aWVkRGVmYXVsdHMoKSk6Y29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gTm8gbWV0YWRhdGEgYW5kIG5vdCBwcm94aWVkIG1vZGUgLSB1bmluaXRpYWxpemVkIik7Y29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gSW5pdGlhbGl6YXRpb24gY29tcGxldGUiLHtwcm92aWRlcjohIXRoaXMucHJvdmlkZXIsd2VpZ2h0TWFwcGVyOiEhdGhpcy53ZWlnaHRNYXBwZXIsY3JlZGVudGlhbHM6ISF0aGlzLmNyZWRlbnRpYWxzfSksdGhpcy5pc0luaXRpYWxpemVkPSEwfWFzeW5jIGluaXRpYWxpemVQcm94aWVkRGVmYXVsdHMoKXt0aGlzLnByb3ZpZGVyPXRoaXMuY3JlYXRlUHJvdmlkZXIoImFudGhyb3BpYyIpLHRoaXMud2VpZ2h0TWFwcGVyPW5ldyBlKCJhbnRocm9waWMiLHt9KSx0aGlzLmNyZWRlbnRpYWxzPXthcGlLZXk6InByb3hpZWQifSxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuc2F2ZU1ldGFkYXRhKCJhbnRocm9waWMiLHt9LCEwKX1hc3luYyBjb25maWd1cmUoZSx0LHM9ITEpe2F3YWl0IHRoaXMuYXBwbHlDb25maWcoZSksYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnNhdmUoZSx0LHMpfWFzeW5jIGFwcGx5Q29uZmlnKHQpe2lmKHRoaXMucHJvdmlkZXI9dGhpcy5jcmVhdGVQcm92aWRlcih0LnByb3ZpZGVyKSx0aGlzLndlaWdodE1hcHBlcj1uZXcgZSh0LnByb3ZpZGVyLHQubW9kZWxzKSx0LmNyZWRlbnRpYWxzKXt0aGlzLmNyZWRlbnRpYWxzPXQuY3JlZGVudGlhbHM7dHJ5e2F3YWl0IHRoaXMucHJvdmlkZXIudmFsaWRhdGVDcmVkZW50aWFscyh0LmNyZWRlbnRpYWxzKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYENyZWRlbnRpYWwgdmFsaWRhdGlvbiBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApfX19YXN5bmMgbWFrZVJlcXVlc3QoZSl7dGhpcy5pc0luaXRpYWxpemVkfHxhd2FpdCB0aGlzLmluaXRpYWxpemUoKTtjb25zdCB0PWF3YWl0IHRoaXMuZ2V0U3RhdGUoKTtpZigidW5pbml0aWFsaXplZCI9PT10P2F3YWl0IHRoaXMucHJvbXB0Rm9yQ29uZmlndXJhdGlvbklmTmVlZGVkKCk6ImxvY2tlZCI9PT10JiZhd2FpdCB0aGlzLnByb21wdEZvclVubG9jaygpLCF0aGlzLnByb3ZpZGVyfHwhdGhpcy53ZWlnaHRNYXBwZXIpdGhyb3cgbmV3IEVycm9yKCJBaURlbGVnYXRlIGlzIG5vdCBjb25maWd1cmVkLiBQbGVhc2UgY2FsbCBjb25maWd1cmUoKSB3aXRoIHByb3ZpZGVyIGFuZCBjcmVkZW50aWFscy4iKTtpZighdGhpcy5jcmVkZW50aWFscyl0aHJvdyBuZXcgRXJyb3IoIk5vIGNyZWRlbnRpYWxzIGF2YWlsYWJsZS4gUGxlYXNlIHByb3ZpZGUgcGFzc3dvcmQgdG8gdW5sb2NrLiIpO2xldCBzPXRoaXMud2VpZ2h0TWFwcGVyLmdldE1vZGVsKGUud2VpZ2h0KTtjb25zb2xlLmxvZyhgW0FpRGVsZWdhdGVDb3JlXSBtYWtlUmVxdWVzdCB3ZWlnaHQ9JHtlLndlaWdodH0sIG1hcHBlZCBtb2RlbD0ke3N9YCksc3x8KGNvbnNvbGUubG9nKGBbQWlEZWxlZ2F0ZUNvcmVdIE5vIG1vZGVsIGZvciB3ZWlnaHQgJHtlLndlaWdodH0sIGF1dG8tc2VsZWN0aW5nLi4uYCkscz1hd2FpdCB0aGlzLmVuc3VyZU1vZGVsRm9yV2VpZ2h0KGUud2VpZ2h0KSxjb25zb2xlLmxvZyhgW0FpRGVsZWdhdGVDb3JlXSBBdXRvLXNlbGVjdGVkIG1vZGVsOiAke3N9YCkpO2NvbnN0IHI9e21vZGVsOnMsbWVzc2FnZXM6ZS5tZXNzYWdlcyxtYXhfdG9rZW5zOmUubWF4X3Rva2Vucyx0ZW1wZXJhdHVyZTplLnRlbXBlcmF0dXJlLHN0cmVhbTplLnN0cmVhbSxzeXN0ZW06ZS5zeXN0ZW19O2lmKGUuc3RyZWFtJiYhZS5vblN0cmVhbSl0aHJvdyBuZXcgRXJyb3IoIm9uU3RyZWFtIGNhbGxiYWNrIGlzIHJlcXVpcmVkIHdoZW4gc3RyZWFtPXRydWUiKTt0cnl7cmV0dXJuIGF3YWl0IHRoaXMucHJvdmlkZXIubWFrZVJlcXVlc3Qocix0aGlzLmNyZWRlbnRpYWxzLGUub25TdHJlYW0pfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcihgQUkgcmVxdWVzdCBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApfX1hc3luYyBlbnN1cmVNb2RlbEZvcldlaWdodChlKXtpZighdGhpcy5wcm92aWRlcnx8IXRoaXMuY3JlZGVudGlhbHMpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBhbmQgY3JlZGVudGlhbHMgbXVzdCBiZSBjb25maWd1cmVkIGZpcnN0Iik7Y29uc3QgdD1hd2FpdCB0aGlzLnByb3ZpZGVyLmZldGNoQXZhaWxhYmxlTW9kZWxzKHRoaXMuY3JlZGVudGlhbHMpO2lmKDA9PT10Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIk5vIG1vZGVscyBhdmFpbGFibGUgZnJvbSBwcm92aWRlciIpO2xldCBzO2lmKGF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5nZXRVc2VEZWZhdWx0TW9kZWxzKCkpcz1hd2FpdCB0aGlzLmF1dG9TZWxlY3RNb2RlbEZvcldlaWdodChlLHQpO2Vsc2V7aWYoIXRoaXMucHJvbXB0SGFuZGxlcil0aHJvdyBuZXcgRXJyb3IoIk1vZGVsIHNlbGVjdGlvbiByZXF1aXJlZCBidXQgcHJvbXB0IGhhbmRsZXIgbm90IHNldCIpO3M9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvck1vZGVsU2VsZWN0aW9uKGUsdCl9cmV0dXJuIGF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5zZXRNb2RlbEZvcldlaWdodChlLHMpLHRoaXMud2VpZ2h0TWFwcGVyJiZ0aGlzLndlaWdodE1hcHBlci5zZXRNb2RlbChlLHMpLHN9YXN5bmMgYXV0b1NlbGVjdE1vZGVsRm9yV2VpZ2h0KGUsdCl7aWYoIXRoaXMucHJvdmlkZXIpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBub3QgY29uZmlndXJlZCIpO2NvbnN0IHM9e2xpZ2h0OiJoYWlrdSIsbW9kZXJhdGU6InNvbm5ldCIsaGVhdnk6Im9wdXMifVtlXTtpZih0aGlzLnByb3ZpZGVyIGluc3RhbmNlb2YgaHMpe2NvbnN0IGU9dGhpcy5wcm92aWRlci5nZXRMYXRlc3RNb2RlbEJ5RmFtaWx5KHQscyk7aWYoZSlyZXR1cm4gZX1jb25zdCByPXQuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhzLnRvTG93ZXJDYXNlKCkpfHxlLmRpc3BsYXlfbmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHMudG9Mb3dlckNhc2UoKSkpO2lmKDA9PT1yLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYE5vICR7c30gbW9kZWxzIGZvdW5kIGZvciAke2V9IHdlaWdodGApO3JldHVybiByLnNvcnQoKGUsdCk9Pntjb25zdCBzPW5ldyBEYXRlKGUuY3JlYXRlZF9hdCkuZ2V0VGltZSgpO3JldHVybiBuZXcgRGF0ZSh0LmNyZWF0ZWRfYXQpLmdldFRpbWUoKS1zfSksclswXS5pZH1hc3luYyBnZXRTdGF0dXMoKXt0aGlzLmlzSW5pdGlhbGl6ZWR8fGF3YWl0IHRoaXMuaW5pdGlhbGl6ZSgpO2NvbnN0IGU9YXdhaXQgdGhpcy5nZXRTdGF0ZSgpO2xldCB0PWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5oYXNDcmVkZW50aWFscygpO2lmKHRoaXMuaXNQcm94aWVkTW9kZSgpKXtjb25zdCBlPXRoaXMucHJvdmlkZXI7aWYoZSYmImZ1bmN0aW9uIj09dHlwZW9mIGUuY2hlY2tBdXRoU3RhdHVzKXRyeXt0PShhd2FpdCBlLmNoZWNrQXV0aFN0YXR1cygpKS5hdXRoZW50aWNhdGVkfWNhdGNoe319cmV0dXJue3N0YXRlOmUsY29uZmlndXJlZDohIXRoaXMucHJvdmlkZXImJiEhdGhpcy53ZWlnaHRNYXBwZXIsaGFzQ3JlZGVudGlhbHM6dCxwcm92aWRlcjp0aGlzLnByb3ZpZGVyPy5uYW1lLG1vZGVsczp0aGlzLndlaWdodE1hcHBlcj8uZ2V0TWFwcGluZygpLGNhY2hlRW5hYmxlZDohMSx0cmFja2luZ0VuYWJsZWQ6ITF9fWFzeW5jIGxvY2soKXt0aGlzLmNyZWRlbnRpYWxzPXZvaWQgMCxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuY2xlYXJDcmVkZW50aWFscygpfWFzeW5jIHJlc2V0KCl7dGhpcy5wcm92aWRlcj12b2lkIDAsdGhpcy53ZWlnaHRNYXBwZXI9dm9pZCAwLHRoaXMuY3JlZGVudGlhbHM9dm9pZCAwLHRoaXMuaXNJbml0aWFsaXplZD0hMSxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuY2xlYXIoKX1jcmVhdGVQcm92aWRlcihlKXtzd2l0Y2goZSl7Y2FzZSJhbnRocm9waWMiOnJldHVybiB0aGlzLmlzUHJveGllZE1vZGUoKT9uZXcgdXMoe2NyZWRlbnRpYWxTZXJ2ZXJVcmw6dGhpcy5jcmVkZW50aWFsU2VydmVyVXJsfSk6bmV3IGhzO2Nhc2Uib3BlbmFpIjp0aHJvdyBuZXcgRXJyb3IoIk9wZW5BSSBwcm92aWRlciBub3QgeWV0IGltcGxlbWVudGVkIik7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gcHJvdmlkZXI6ICR7ZX1gKX19YXN5bmMgdXBkYXRlQ3JlZGVudGlhbHMoZSx0KXtpZighdGhpcy5wcm92aWRlcil0aHJvdyBuZXcgRXJyb3IoIlByb3ZpZGVyIG5vdCBjb25maWd1cmVkLiBDYWxsIGNvbmZpZ3VyZSgpIGZpcnN0LiIpO2F3YWl0IHRoaXMucHJvdmlkZXIudmFsaWRhdGVDcmVkZW50aWFscyhlKSx0aGlzLmNyZWRlbnRpYWxzPWUsYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnVwZGF0ZUNyZWRlbnRpYWxzKGUsdCl9YXN5bmMgaXNSZWFkeSgpe2lmKHRoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCksdGhpcy5pc1Byb3hpZWRNb2RlKCkpe2NvbnN0IGU9dGhpcy5wcm92aWRlcjtpZihlJiYiZnVuY3Rpb24iPT10eXBlb2YgZS5jaGVja0F1dGhTdGF0dXMpdHJ5e2NvbnN0IHQ9YXdhaXQgZS5jaGVja0F1dGhTdGF0dXMoKTtyZXR1cm4hIXRoaXMucHJvdmlkZXImJiEhdGhpcy53ZWlnaHRNYXBwZXImJnQuYXV0aGVudGljYXRlZH1jYXRjaHtyZXR1cm4hMX19cmV0dXJuISF0aGlzLnByb3ZpZGVyJiYhIXRoaXMud2VpZ2h0TWFwcGVyJiYhIXRoaXMuY3JlZGVudGlhbHN9YXN5bmMgZ2V0U3RhdGUoKXtpZih0aGlzLmlzUHJveGllZE1vZGUoKSl7Y29uc3QgZT10aGlzLnByb3ZpZGVyO2lmKGUmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLmNoZWNrQXV0aFN0YXR1cyl0cnl7aWYoKGF3YWl0IGUuY2hlY2tBdXRoU3RhdHVzKCkpLmF1dGhlbnRpY2F0ZWQpcmV0dXJuInVubG9ja2VkIn1jYXRjaHt9cmV0dXJuInVuaW5pdGlhbGl6ZWQifXJldHVybiBhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuaGFzQ29uZmlnKCk/dGhpcy5jcmVkZW50aWFscz8idW5sb2NrZWQiOiJsb2NrZWQiOiJ1bmluaXRpYWxpemVkIn1hc3luYyBwcm9tcHRGb3JDb25maWd1cmF0aW9uSWZOZWVkZWQoKXtpZighdGhpcy5wcm9tcHRIYW5kbGVyKXRocm93IG5ldyBFcnJvcigiQ29uZmlndXJhdGlvbiByZXF1aXJlZC4gUHJvbXB0IGhhbmRsZXIgbm90IHNldC4gVGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3b3JrZXIgY29udGV4dCB3aXRoIGEgcHJvbXB0IGhhbmRsZXIuIik7dHJ5e2NvbnN0IGU9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvckNvbmZpZ3VyYXRpb24oKTthd2FpdCB0aGlzLmNvbmZpZ3VyZShlLmNvbmZpZyxlLnBhc3N3b3JkLGUudXNlRGVmYXVsdE1vZGVscyl9Y2F0Y2goZSl7dGhyb3cgbmV3IEVycm9yKGBDb25maWd1cmF0aW9uIHJlcXVpcmVkOiAke2UubWVzc2FnZX1gKX19YXN5bmMgcHJvbXB0Rm9yVW5sb2NrKCl7aWYoIXRoaXMucHJvbXB0SGFuZGxlcil0aHJvdyBuZXcgRXJyb3IoIlBhc3N3b3JkIHJlcXVpcmVkIHRvIHVubG9jay4gUHJvbXB0IGhhbmRsZXIgbm90IHNldC4gVGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3b3JrZXIgY29udGV4dCB3aXRoIGEgcHJvbXB0IGhhbmRsZXIuIik7dHJ5e2NvbnN0IGU9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvclVubG9jaygpO2F3YWl0IHRoaXMudW5sb2NrKGUpfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcihgVW5sb2NrIHJlcXVpcmVkOiAke2UubWVzc2FnZX1gKX19YXN5bmMgdW5sb2NrKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnVubG9jayhlKTthd2FpdCB0aGlzLmFwcGx5Q29uZmlnKHQpfX0hZnVuY3Rpb24oZSl7ZS5JTklUPSJpbml0IixlLkNPTkZJR1VSRT0iY29uZmlndXJlIixlLk1BS0VfUkVRVUVTVD0ibWFrZVJlcXVlc3QiLGUuR0VUX1NUQVRVUz0iZ2V0U3RhdHVzIixlLkxPQ0s9ImxvY2siLGUuUkVTRVQ9InJlc2V0IixlLlVQREFURV9DUkVERU5USUFMUz0idXBkYXRlQ3JlZGVudGlhbHMiLGUuSVNfUkVBRFk9ImlzUmVhZHkiLGUuVU5MT0NLPSJ1bmxvY2siLGUuR0VUX1NFVFVQX1VSTD0iZ2V0U2V0dXBVcmwiLGUuU0VUX0xPQ0FMX01PREU9InNldExvY2FsTW9kZSIsZS5JU19MT0NBTF9NT0RFX0FMTE9XRUQ9ImlzTG9jYWxNb2RlQWxsb3dlZCIsZS5JU19MT0NBTF9NT0RFX0ZPUkNFRD0iaXNMb2NhbE1vZGVGb3JjZWQiLGUuQ09ORklHVVJFX0xPQ0FMPSJjb25maWd1cmVMb2NhbCIsZS5GRVRDSF9NT0RFTFM9ImZldGNoTW9kZWxzIixlLlJFR0lTVEVSX1BST01QVD0icmVnaXN0ZXJQcm9tcHQiLGUuUkVHSVNURVJfUFJPTVBUUz0icmVnaXN0ZXJQcm9tcHRzIixlLkdFVF9QUk9NUFQ9ImdldFByb21wdCIsZS5MSVNUX1BST01QVFM9Imxpc3RQcm9tcHRzIixlLlVQREFURV9QUk9NUFQ9InVwZGF0ZVByb21wdCIsZS5ERUxFVEVfUFJPTVBUPSJkZWxldGVQcm9tcHQiLGUuUkVTRVRfUFJPTVBUPSJyZXNldFByb21wdCIsZS5SRVNPTFZFX0NPTkZMSUNUPSJyZXNvbHZlQ29uZmxpY3QiLGUuUkVOREVSX1BST01QVD0icmVuZGVyUHJvbXB0In0ob3N8fChvcz17fSkpLGZ1bmN0aW9uKGUpe2UuQ09ORklHVVJFPSJjb25maWd1cmUiLGUuVU5MT0NLPSJ1bmxvY2siLGUuTU9ERUxfU0VMRUNUPSJtb2RlbFNlbGVjdCIsZS5QUk9NUFRfQ09ORkxJQ1Q9InByb21wdENvbmZsaWN0In0oaXN8fChpcz17fSkpO2NsYXNzIGZze3N0YXRpYyB2YWxpZGF0ZU1lc3NhZ2UoZSl7cmV0dXJuISghZXx8Im9iamVjdCIhPXR5cGVvZiBlfHwic3RyaW5nIiE9dHlwZW9mIGUuaWR8fDA9PT1lLmlkLmxlbmd0aHx8IU9iamVjdC52YWx1ZXMob3MpLmluY2x1ZGVzKGUuY29tbWFuZCkpfXN0YXRpYyBjcmVhdGVTdWNjZXNzUmVzcG9uc2UoZSx0KXtyZXR1cm57aWQ6ZSxzdWNjZXNzOiEwLGRhdGE6dH19c3RhdGljIGNyZWF0ZUVycm9yUmVzcG9uc2UoZSx0KXtjb25zdCBzPSJzdHJpbmciPT10eXBlb2YgdD90OnQubWVzc2FnZTtyZXR1cm57aWQ6ZSxzdWNjZXNzOiExLGVycm9yOnttZXNzYWdlOnRoaXMuc2FuaXRpemVFcnJvck1lc3NhZ2Uocyl9fX1zdGF0aWMgc2FuaXRpemVFcnJvck1lc3NhZ2UoZSl7cmV0dXJuIGUucmVwbGFjZSgvc2stYW50LVthLXpBLVowLTlfLV0rL2csIltBUElfS0VZX1JFREFDVEVEXSIpLnJlcGxhY2UoL3NrLVthLXpBLVowLTlfLV17NDgsfS9nLCJbQVBJX0tFWV9SRURBQ1RFRF0iKS5yZXBsYWNlKC8oYXBpW18tXT9rZXl8dG9rZW58cGFzc3dvcmR8c2VjcmV0KVs6XHM9XStbXlxzXSsvZ2ksIiQxOiBbUkVEQUNURURdIil9c3RhdGljIGdlbmVyYXRlSWQoKXtyZXR1cm5gJHtEYXRlLm5vdygpfS0ke01hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyLDExKX1gfX1jb25zdCBtcz0iQUVTLUdDTSI7YXN5bmMgZnVuY3Rpb24gZ3MoZSx0KXtjb25zdCBzPW5ldyBUZXh0RW5jb2RlcixyPWF3YWl0IGNyeXB0by5zdWJ0bGUuaW1wb3J0S2V5KCJyYXciLHMuZW5jb2RlKGUpLCJQQktERjIiLCExLFsiZGVyaXZlS2V5Il0pO3JldHVybiBjcnlwdG8uc3VidGxlLmRlcml2ZUtleSh7bmFtZToiUEJLREYyIixzYWx0OnQsaXRlcmF0aW9uczoxZTUsaGFzaDoiU0hBLTI1NiJ9LHIse25hbWU6bXMsbGVuZ3RoOjI1Nn0sITEsWyJlbmNyeXB0IiwiZGVjcnlwdCJdKX1jb25zdCB3cz0iMC4xLjAiLHlzPSJhaS1kZWxlZ2F0ZS1jb25maWciLGJzPTNlNSx2cz0icHJvbXB0cyI7Y2xhc3MgX3N7Y29uc3RydWN0b3IoKXt0aGlzLmRiPW51bGx9YXN5bmMgaW5pdERCKCl7cmV0dXJuIHRoaXMuZGI/dGhpcy5kYjpuZXcgUHJvbWlzZSgoZSx0KT0+e2NvbnN0IHM9aW5kZXhlZERCLm9wZW4oImFpLWRlbGVnYXRlLXByb21wdHMiLDEpO3Mub25lcnJvcj0oKT0+e3QobmV3IEVycm9yKGBGYWlsZWQgdG8gb3BlbiBJbmRleGVkREI6ICR7cy5lcnJvcn1gKSl9LHMub25zdWNjZXNzPSgpPT57dGhpcy5kYj1zLnJlc3VsdCxlKHRoaXMuZGIpfSxzLm9udXBncmFkZW5lZWRlZD1lPT57Y29uc3QgdD1lLnRhcmdldC5yZXN1bHQ7aWYoIXQub2JqZWN0U3RvcmVOYW1lcy5jb250YWlucyh2cykpe2NvbnN0IGU9dC5jcmVhdGVPYmplY3RTdG9yZSh2cyx7a2V5UGF0aDoibmFtZSJ9KTtlLmNyZWF0ZUluZGV4KCJ2ZXJzaW9uIiwidmVyc2lvbiIse3VuaXF1ZTohMX0pLGUuY3JlYXRlSW5kZXgoImxvY2FsbHlNb2RpZmllZCIsImxvY2FsbHlNb2RpZmllZCIse3VuaXF1ZTohMX0pfX19KX1hc3luYyBnZXQoZSl7dHJ5e2NvbnN0IHQ9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pntjb25zdCBuPXQudHJhbnNhY3Rpb24oW3ZzXSwicmVhZG9ubHkiKS5vYmplY3RTdG9yZSh2cykuZ2V0KGUpO24ub25zdWNjZXNzPSgpPT57cyhuLnJlc3VsdD8/bnVsbCl9LG4ub25lcnJvcj0oKT0+e3IobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IHByb21wdDogJHtuLmVycm9yfWApKX19KX1jYXRjaChlKXtyZXR1cm4gY29uc29sZS5lcnJvcigiW1Byb21wdFN0b3JlXSBnZXQgZXJyb3I6IixlKSxudWxsfX1hc3luYyBwdXQoZSl7Y29uc3QgdD1hd2FpdCB0aGlzLmluaXREQigpO3JldHVybiBuZXcgUHJvbWlzZSgocyxyKT0+e2NvbnN0IG49dC50cmFuc2FjdGlvbihbdnNdLCJyZWFkd3JpdGUiKS5vYmplY3RTdG9yZSh2cykucHV0KGUpO24ub25zdWNjZXNzPSgpPT57cygpfSxuLm9uZXJyb3I9KCk9PntyKG5ldyBFcnJvcihgRmFpbGVkIHRvIHNhdmUgcHJvbXB0OiAke24uZXJyb3J9YCkpfX0pfWFzeW5jIGRlbGV0ZShlKXtjb25zdCB0PWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChzLHIpPT57Y29uc3Qgbj10LnRyYW5zYWN0aW9uKFt2c10sInJlYWR3cml0ZSIpLm9iamVjdFN0b3JlKHZzKS5kZWxldGUoZSk7bi5vbnN1Y2Nlc3M9KCk9PntzKCl9LG4ub25lcnJvcj0oKT0+e3IobmV3IEVycm9yKGBGYWlsZWQgdG8gZGVsZXRlIHByb21wdDogJHtuLmVycm9yfWApKX19KX1hc3luYyBsaXN0KCl7Y29uc3QgZT1hd2FpdCB0aGlzLmluaXREQigpO3JldHVybiBuZXcgUHJvbWlzZSgodCxzKT0+e2NvbnN0IHI9ZS50cmFuc2FjdGlvbihbdnNdLCJyZWFkb25seSIpLm9iamVjdFN0b3JlKHZzKS5nZXRBbGwoKTtyLm9uc3VjY2Vzcz0oKT0+e3Qoci5yZXN1bHQ/P1tdKX0sci5vbmVycm9yPSgpPT57cyhuZXcgRXJyb3IoYEZhaWxlZCB0byBsaXN0IHByb21wdHM6ICR7ci5lcnJvcn1gKSl9fSl9YXN5bmMgZXhpc3RzKGUpe3JldHVybiBudWxsIT09YXdhaXQgdGhpcy5nZXQoZSl9YXN5bmMgZ2V0TW9kaWZpZWQoKXtjb25zdCBlPWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKCh0LHMpPT57Y29uc3Qgcj1lLnRyYW5zYWN0aW9uKFt2c10sInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodnMpLmluZGV4KCJsb2NhbGx5TW9kaWZpZWQiKS5nZXRBbGwoSURCS2V5UmFuZ2Uub25seSghMCkpO3Iub25zdWNjZXNzPSgpPT57dChyLnJlc3VsdD8/W10pfSxyLm9uZXJyb3I9KCk9PntzKG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBtb2RpZmllZCBwcm9tcHRzOiAke3IuZXJyb3J9YCkpfX0pfXN0YXRpYyBjcmVhdGVTdG9yZWRQcm9tcHQoZSx0LHMpe2NvbnN0IHI9KG5ldyBEYXRlKS50b0lTT1N0cmluZygpO3JldHVybnsuLi5zLG5hbWU6ZSx2ZXJzaW9uOnQsbG9jYWxseU1vZGlmaWVkOiExLGNyZWF0ZWRBdDpyLHVwZGF0ZWRBdDpyfX1hc3luYyBjbGVhcigpe2NvbnN0IGU9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHQscyk9Pntjb25zdCByPWUudHJhbnNhY3Rpb24oW3ZzXSwicmVhZHdyaXRlIikub2JqZWN0U3RvcmUodnMpLmNsZWFyKCk7ci5vbnN1Y2Nlc3M9KCk9Pnt0KCl9LHIub25lcnJvcj0oKT0+e3MobmV3IEVycm9yKGBGYWlsZWQgdG8gY2xlYXIgcHJvbXB0czogJHtyLmVycm9yfWApKX19KX19Y2xhc3Mga3MgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGBVbmRlZmluZWQgcGFyYW1ldGVyOiAke2V9JHt0P2AgaW4gcHJvbXB0ICIke3R9ImA6IiJ9YCksdGhpcy5wYXJhbU5hbWU9ZSx0aGlzLnByb21wdE5hbWU9dCx0aGlzLm5hbWU9IlVuZGVmaW5lZFBhcmFtRXJyb3IifX1jbGFzcyBTcyBleHRlbmRzIEVycm9ye2NvbnN0cnVjdG9yKGUsdCl7c3VwZXIoYFVucmVmZXJlbmNlZCBwYXJhbWV0ZXI6ICR7ZX0ke3Q/YCBpbiBwcm9tcHQgIiR7dH0iYDoiIn1gKSx0aGlzLnBhcmFtTmFtZT1lLHRoaXMucHJvbXB0TmFtZT10LHRoaXMubmFtZT0iVW5yZWZlcmVuY2VkUGFyYW1FcnJvciJ9fWNsYXNzIE1zIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihgTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXI6ICR7ZX0ke3Q/YCBmb3IgcHJvbXB0ICIke3R9ImA6IiJ9YCksdGhpcy5wYXJhbU5hbWU9ZSx0aGlzLnByb21wdE5hbWU9dCx0aGlzLm5hbWU9Ik1pc3NpbmdQYXJhbUVycm9yIn19Y2xhc3MgUHMgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGBVbmtub3duIHBhcmFtZXRlcjogJHtlfSR7dD9gIGZvciBwcm9tcHQgIiR7dH0iYDoiIn1gKSx0aGlzLnBhcmFtTmFtZT1lLHRoaXMucHJvbXB0TmFtZT10LHRoaXMubmFtZT0iVW5rbm93blBhcmFtRXJyb3IifX1jb25zdCBFcz0vXHsoW2EtekEtWl9dW2EtekEtWjAtOV9dKilcfS9nO2NsYXNzIFJze2V4dHJhY3RQYXJhbXMoZSl7Y29uc3QgdD1bXTtsZXQgcztmb3IoRXMubGFzdEluZGV4PTA7bnVsbCE9PShzPUVzLmV4ZWMoZSkpOyl7Y29uc3QgZT1zWzFdO3QuaW5jbHVkZXMoZSl8fHQucHVzaChlKX1yZXR1cm4gdH12YWxpZGF0ZURlZmluaXRpb24oZSx0KXtjb25zdCBzPXRoaXMuZXh0cmFjdFBhcmFtcyhlLnRlbXBsYXRlKSxyPU9iamVjdC5rZXlzKGUucGFyYW1zPz97fSk7Zm9yKGNvbnN0IGUgb2YgcylpZighci5pbmNsdWRlcyhlKSl0aHJvdyBuZXcga3MoZSx0KTtmb3IoY29uc3QgZSBvZiByKWlmKCFzLmluY2x1ZGVzKGUpKXRocm93IG5ldyBTcyhlLHQpO2lmKGUucm9sZSYmIVsidXNlciIsImFzc2lzdGFudCIsInN5c3RlbSJdLmluY2x1ZGVzKGUucm9sZSkpdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJvbGUgIiR7ZS5yb2xlfSIgZm9yIHByb21wdCR7dD9gICIke3R9ImA6IiJ9YCl9cmVuZGVyKGUsdCxzKXtjb25zdCByPXRoaXMuZXh0cmFjdFBhcmFtcyhlKSxuPXt9O2Zvcihjb25zdCBlIG9mIHIpaWYoZSBpbiBzKW5bZV09c1tlXTtlbHNle2lmKCEoZSBpbiB0KXx8dm9pZCAwPT09dFtlXS5kZWZhdWx0KXRocm93IG5ldyBNcyhlKTtuW2VdPXRbZV0uZGVmYXVsdH1mb3IoY29uc3QgZSBvZiBPYmplY3Qua2V5cyhzKSlpZighci5pbmNsdWRlcyhlKSl0aHJvdyBuZXcgUHMoZSk7cmV0dXJuIGUucmVwbGFjZShFcywoZSx0KT0+blt0XSl9cmVuZGVyV2l0aFNpbmdsZVBhcmFtKGUsdCxzKXtsZXQgcj17fTtpZih2b2lkIDA9PT1zKXI9e307ZWxzZSBpZigic3RyaW5nIj09dHlwZW9mIHMpe2NvbnN0IG49dGhpcy5leHRyYWN0UGFyYW1zKGUpLGE9bi5maWx0ZXIoZT0+IShlIGluIHQpfHx2b2lkIDA9PT10W2VdLmRlZmF1bHQpLG89bi5maWx0ZXIoZT0+ZSBpbiB0JiZ2b2lkIDAhPT10W2VdLmRlZmF1bHQpO2lmKDE9PT1hLmxlbmd0aClyW2FbMF1dPXM7ZWxzZXtpZihhLmxlbmd0aD4xKXRocm93IG5ldyBFcnJvcihgQW1iaWd1b3VzIHNpbmdsZSBwYXJhbWV0ZXI6IG11bHRpcGxlIHJlcXVpcmVkIHBhcmFtcyAoJHthLmpvaW4oIiwgIil9KWApO2lmKDEhPT1vLmxlbmd0aCl0aHJvdyBvLmxlbmd0aD4xP25ldyBFcnJvcihgQW1iaWd1b3VzIHNpbmdsZSBwYXJhbWV0ZXI6IG11bHRpcGxlIG9wdGlvbmFsIHBhcmFtcyAoJHtvLmpvaW4oIiwgIil9KWApOm5ldyBFcnJvcigiUHJvbXB0IHRha2VzIG5vIHBhcmFtZXRlcnMiKTtyW29bMF1dPXN9fWVsc2Ugcj1zO3JldHVybiB0aGlzLnJlbmRlcihlLHQscil9fWNvbnNvbGUubG9nKCJbQUkgRGVsZWdhdGUgV29ya2VyXSBWZXJzaW9uOiAwLjMuNCIpO2NvbnN0IHhzPW5ldyBjbGFzc3tjb25zdHJ1Y3Rvcigpe3RoaXMuZGJOYW1lPSJhaS1kZWxlZ2F0ZS1zdG9yYWdlIix0aGlzLnN0b3JlTmFtZT0iY29uZmlnIix0aGlzLmRiPW51bGx9YXN5bmMgaW5pdERCKCl7cmV0dXJuIHRoaXMuZGI/dGhpcy5kYjpuZXcgUHJvbWlzZSgoZSx0KT0+e2NvbnN0IHM9aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUsMSk7cy5vbmVycm9yPSgpPT57dChuZXcgRXJyb3IoYEZhaWxlZCB0byBvcGVuIEluZGV4ZWREQjogJHtzLmVycm9yfWApKX0scy5vbnN1Y2Nlc3M9KCk9Pnt0aGlzLmRiPXMucmVzdWx0LGUodGhpcy5kYil9LHMub251cGdyYWRlbmVlZGVkPWU9Pntjb25zdCB0PWUudGFyZ2V0LnJlc3VsdDt0Lm9iamVjdFN0b3JlTmFtZXMuY29udGFpbnModGhpcy5zdG9yZU5hbWUpfHx0LmNyZWF0ZU9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKX19KX1hc3luYyBnZXRJdGVtKGUpe3RyeXtjb25zdCB0PWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChzLHIpPT57Y29uc3Qgbj10LnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtuLm9uc3VjY2Vzcz0oKT0+e3Mobi5yZXN1bHQ/P251bGwpfSxuLm9uZXJyb3I9KCk9PntyKG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBpdGVtOiAke24uZXJyb3J9YCkpfX0pfWNhdGNoKGUpe3JldHVybiBjb25zb2xlLmVycm9yKCJbSW5kZXhlZERCQWRhcHRlcl0gZ2V0SXRlbSBlcnJvcjoiLGUpLG51bGx9fWFzeW5jIHNldEl0ZW0oZSx0KXtjb25zdCBzPWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChyLG4pPT57Y29uc3QgYT1zLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sInJlYWR3cml0ZSIpLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKS5wdXQodCxlKTthLm9uc3VjY2Vzcz0oKT0+e3IoKX0sYS5vbmVycm9yPSgpPT57bihuZXcgRXJyb3IoYEZhaWxlZCB0byBzZXQgaXRlbTogJHthLmVycm9yfWApKX19KX1hc3luYyByZW1vdmVJdGVtKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pntjb25zdCBuPXQudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwicmVhZHdyaXRlIikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmRlbGV0ZShlKTtuLm9uc3VjY2Vzcz0oKT0+e3MoKX0sbi5vbmVycm9yPSgpPT57cihuZXcgRXJyb3IoYEZhaWxlZCB0byByZW1vdmUgaXRlbTogJHtuLmVycm9yfWApKX19KX1hc3luYyBoYXNJdGVtKGUpe3RyeXtyZXR1cm4gbnVsbCE9PWF3YWl0IHRoaXMuZ2V0SXRlbShlKX1jYXRjaChlKXtyZXR1cm4hMX19fSxUcz1uZXcgY2xhc3N7Y29uc3RydWN0b3IoZSl7aWYoInVuZGVmaW5lZCI9PXR5cGVvZiBjcnlwdG98fHZvaWQgMD09PWNyeXB0by5zdWJ0bGV8fCJmdW5jdGlvbiIhPXR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKXRocm93IG5ldyBFcnJvcigiV2ViIENyeXB0byBBUEkgbm90IGF2YWlsYWJsZS4gVGhpcyBsaWJyYXJ5IHJlcXVpcmVzIGEgbW9kZXJuIGJyb3dzZXIgd2l0aCBjcnlwdG8gc3VwcG9ydC4iKTt0aGlzLnN0b3JhZ2U9ZX1hc3luYyBzYXZlKGUsdCxzPSExKXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3N3b3JkIGlzIHJlcXVpcmVkIHRvIHNhdmUgY29uZmlndXJhdGlvbiIpO2NvbnN0IHI9e3Byb3ZpZGVyOmUucHJvdmlkZXIsbW9kZWxzOmUubW9kZWxzLHVzZURlZmF1bHRNb2RlbHM6cyxlbmFibGVDYWNoZTplLmVuYWJsZUNhY2hlPz8hMSxjYWNoZVRUTDplLmNhY2hlVFRMPz9icyx0cmFja1VzYWdlOmUudHJhY2tVc2FnZT8/ITEsdmVyc2lvbjp3c307ZS5jcmVkZW50aWFscyYmKHIuZW5jcnlwdGVkQ3JlZGVudGlhbHM9YXdhaXQgdGhpcy5lbmNyeXB0Q3JlZGVudGlhbHMoZS5jcmVkZW50aWFscyx0KSk7dHJ5e2F3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHIpKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIGNvbmZpZ3VyYXRpb246ICR7ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IifWApfX1hc3luYyBsb2FkTWV0YWRhdGEoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuIG51bGw7Y29uc3QgdD1KU09OLnBhcnNlKGUpO3JldHVybiB0LnZlcnNpb24hPT13cyYmY29uc29sZS53YXJuKGBDb25maWd1cmF0aW9uIHZlcnNpb24gbWlzbWF0Y2guIEV4cGVjdGVkICR7d3N9LCBnb3QgJHt0LnZlcnNpb259YCkse3Byb3ZpZGVyOnQucHJvdmlkZXIsbW9kZWxzOnQubW9kZWxzLGVuYWJsZUNhY2hlOnQuZW5hYmxlQ2FjaGUsY2FjaGVUVEw6dC5jYWNoZVRUTCx0cmFja1VzYWdlOnQudHJhY2tVc2FnZX19Y2F0Y2goZSl7cmV0dXJuIGNvbnNvbGUuZXJyb3IoIkZhaWxlZCB0byBsb2FkIGNvbmZpZ3VyYXRpb246IixlKSxudWxsfX1hc3luYyB1bmxvY2soZSl7aWYoIWV8fDA9PT1lLnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJQYXNzd29yZCBpcyByZXF1aXJlZCB0byB1bmxvY2sgY3JlZGVudGlhbHMiKTtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighdCl0aHJvdyBuZXcgRXJyb3IoIk5vIGNvbmZpZ3VyYXRpb24gZm91bmQiKTtjb25zdCBzPUpTT04ucGFyc2UodCk7aWYoIXMuZW5jcnlwdGVkQ3JlZGVudGlhbHMpdGhyb3cgbmV3IEVycm9yKCJObyBlbmNyeXB0ZWQgY3JlZGVudGlhbHMgZm91bmQiKTtjb25zdCByPWF3YWl0IHRoaXMuZGVjcnlwdENyZWRlbnRpYWxzKHMuZW5jcnlwdGVkQ3JlZGVudGlhbHMsZSk7cmV0dXJue3Byb3ZpZGVyOnMucHJvdmlkZXIsbW9kZWxzOnMubW9kZWxzLGVuYWJsZUNhY2hlOnMuZW5hYmxlQ2FjaGUsY2FjaGVUVEw6cy5jYWNoZVRUTCx0cmFja1VzYWdlOnMudHJhY2tVc2FnZSxjcmVkZW50aWFsczpyfX1hc3luYyBjbGVhcigpe2F3YWl0IHRoaXMuc3RvcmFnZS5yZW1vdmVJdGVtKHlzKX1hc3luYyBoYXNDb25maWcoKXtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yYWdlLmhhc0l0ZW0oeXMpfWFzeW5jIHVwZGF0ZUNyZWRlbnRpYWxzKGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLmxvYWRNZXRhZGF0YSgpO2lmKCFzKXRocm93IG5ldyBFcnJvcigiTm8gY29uZmlndXJhdGlvbiBmb3VuZC4gUGxlYXNlIGNvbmZpZ3VyZSB0aGUgcHJvdmlkZXIgZmlyc3QuIik7Y29uc3Qgcj17Li4ucyxjcmVkZW50aWFsczplfTthd2FpdCB0aGlzLnNhdmUocix0KX1hc3luYyBjbGVhckNyZWRlbnRpYWxzKCl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuO2NvbnN0IHQ9SlNPTi5wYXJzZShlKTtkZWxldGUgdC5lbmNyeXB0ZWRDcmVkZW50aWFscyxhd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeSh0KSl9YXN5bmMgaGFzQ3JlZGVudGlhbHMoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuITE7Y29uc3QgdD1KU09OLnBhcnNlKGUpO3JldHVybiEhdC5lbmNyeXB0ZWRDcmVkZW50aWFsc3x8ISF0LnBsYWludGV4dENyZWRlbnRpYWxzfWNhdGNoe3JldHVybiExfX1hc3luYyBlbmNyeXB0Q3JlZGVudGlhbHMoZSx0KXtyZXR1cm4gYXN5bmMgZnVuY3Rpb24oZSx0KXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIGVuY3J5cHRpb24iKTtjb25zdCBzPShuZXcgVGV4dEVuY29kZXIpLmVuY29kZShlKSxyPWNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoMTYpKSxuPWNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoMTIpKSxhPWF3YWl0IGdzKHQsciksbz1hd2FpdCBjcnlwdG8uc3VidGxlLmVuY3J5cHQoe25hbWU6bXMsaXY6bn0sYSxzKSxpPW5ldyBVaW50OEFycmF5KDI4K28uYnl0ZUxlbmd0aCk7cmV0dXJuIGkuc2V0KHIsMCksaS5zZXQobiwxNiksaS5zZXQobmV3IFVpbnQ4QXJyYXkobyksMjgpLGJ0b2EoU3RyaW5nLmZyb21DaGFyQ29kZSguLi5pKSl9KEpTT04uc3RyaW5naWZ5KGUpLHQpfWFzeW5jIGRlY3J5cHRDcmVkZW50aWFscyhlLHQpe2NvbnN0IHM9YXdhaXQgYXN5bmMgZnVuY3Rpb24oZSx0KXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIGRlY3J5cHRpb24iKTtjb25zdCBzPVVpbnQ4QXJyYXkuZnJvbShhdG9iKGUpLGU9PmUuY2hhckNvZGVBdCgwKSk7aWYocy5sZW5ndGg8MjgpdGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIGVuY3J5cHRlZCBkYXRhIGZvcm1hdCIpO2NvbnN0IHI9cy5zbGljZSgwLDE2KSxuPXMuc2xpY2UoMTYsMjgpLGE9cy5zbGljZSgyOCksbz1hd2FpdCBncyh0LHIpO3RyeXtjb25zdCBlPWF3YWl0IGNyeXB0by5zdWJ0bGUuZGVjcnlwdCh7bmFtZTptcyxpdjpufSxvLGEpO3JldHVybihuZXcgVGV4dERlY29kZXIpLmRlY29kZShlKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoIkRlY3J5cHRpb24gZmFpbGVkLiBJbnZhbGlkIHBhc3NwaHJhc2Ugb3IgY29ycnVwdGVkIGRhdGEuIil9fShlLHQpO3JldHVybiBKU09OLnBhcnNlKHMpfWFzeW5jIHNldE1vZGVsRm9yV2VpZ2h0KGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIXMpdGhyb3cgbmV3IEVycm9yKCJObyBjb25maWd1cmF0aW9uIGZvdW5kLiBQbGVhc2UgY29uZmlndXJlIHRoZSBwcm92aWRlciBmaXJzdC4iKTtjb25zdCByPUpTT04ucGFyc2Uocyk7ci5tb2RlbHN8fChyLm1vZGVscz17fSksci5tb2RlbHNbZV09dCxhd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeShyKSl9YXN5bmMgZ2V0TW9kZWxGb3JXZWlnaHQoZSl7Y29uc3QgdD1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIXQpcmV0dXJuO2NvbnN0IHM9SlNPTi5wYXJzZSh0KTtyZXR1cm4gcy5tb2RlbHM/LltlXX1hc3luYyBzZXRVc2VEZWZhdWx0TW9kZWxzKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5zdG9yYWdlLmdldEl0ZW0oeXMpO2lmKCF0KXRocm93IG5ldyBFcnJvcigiTm8gY29uZmlndXJhdGlvbiBmb3VuZC4gUGxlYXNlIGNvbmZpZ3VyZSB0aGUgcHJvdmlkZXIgZmlyc3QuIik7Y29uc3Qgcz1KU09OLnBhcnNlKHQpO3MudXNlRGVmYXVsdE1vZGVscz1lLGF3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHMpKX1hc3luYyBnZXRVc2VEZWZhdWx0TW9kZWxzKCl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7cmV0dXJuISFlJiYoSlNPTi5wYXJzZShlKS51c2VEZWZhdWx0TW9kZWxzPz8hMSl9YXN5bmMgc2F2ZU1ldGFkYXRhKGUsdCxzPSEwKXtjb25zdCByPXtwcm92aWRlcjplLG1vZGVsczp0LHVzZURlZmF1bHRNb2RlbHM6cyxlbmFibGVDYWNoZTohMSxjYWNoZVRUTDpicyx0cmFja1VzYWdlOiExLHZlcnNpb246d3N9O3RyeXthd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeShyKSl9Y2F0Y2goZSl7dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gc2F2ZSBjb25maWd1cmF0aW9uOiAke2U/Lm1lc3NhZ2V8fCJVbmtub3duIGVycm9yIn1gKX19YXN5bmMgc2F2ZUxvY2FsKGUsdCxzPSExKXtjb25zdCByPXtwcm92aWRlcjplLnByb3ZpZGVyLG1vZGVsczplLm1vZGVscyx1c2VEZWZhdWx0TW9kZWxzOnMsZW5hYmxlQ2FjaGU6ZS5lbmFibGVDYWNoZT8/ITEsY2FjaGVUVEw6ZS5jYWNoZVRUTD8/YnMsdHJhY2tVc2FnZTplLnRyYWNrVXNhZ2U/PyExLGZvcmNlTG9jYWxNb2RlOiEwLHZlcnNpb246d3N9O2UuY3JlZGVudGlhbHMmJih0JiZ0LnRyaW0oKS5sZW5ndGg+MD9yLmVuY3J5cHRlZENyZWRlbnRpYWxzPWF3YWl0IHRoaXMuZW5jcnlwdENyZWRlbnRpYWxzKGUuY3JlZGVudGlhbHMsdCk6ci5wbGFpbnRleHRDcmVkZW50aWFscz1KU09OLnN0cmluZ2lmeShlLmNyZWRlbnRpYWxzKSk7dHJ5e2F3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHIpKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIGNvbmZpZ3VyYXRpb246ICR7ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IifWApfX1hc3luYyBnZXRQbGFpbnRleHRDcmVkZW50aWFscygpe3RyeXtjb25zdCBlPWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighZSlyZXR1cm4gbnVsbDtjb25zdCB0PUpTT04ucGFyc2UoZSk7cmV0dXJuIHQucGxhaW50ZXh0Q3JlZGVudGlhbHM/SlNPTi5wYXJzZSh0LnBsYWludGV4dENyZWRlbnRpYWxzKTpudWxsfWNhdGNoe3JldHVybiBudWxsfX1hc3luYyBoYXNQbGFpbnRleHRDcmVkZW50aWFscygpe3RyeXtjb25zdCBlPWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtyZXR1cm4hIWUmJiEhSlNPTi5wYXJzZShlKS5wbGFpbnRleHRDcmVkZW50aWFsc31jYXRjaHtyZXR1cm4hMX19YXN5bmMgZ2V0Rm9yY2VMb2NhbE1vZGUoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7cmV0dXJuISFlJiYoSlNPTi5wYXJzZShlKS5mb3JjZUxvY2FsTW9kZT8/ITEpfWNhdGNoe3JldHVybiExfX1hc3luYyBzZXRGb3JjZUxvY2FsTW9kZShlKXtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighdCl7Y29uc3QgdD17cHJvdmlkZXI6ImFudGhyb3BpYyIsdXNlRGVmYXVsdE1vZGVsczohMCxlbmFibGVDYWNoZTohMSxjYWNoZVRUTDpicyx0cmFja1VzYWdlOiExLGZvcmNlTG9jYWxNb2RlOmUsdmVyc2lvbjp3c307cmV0dXJuIHZvaWQgYXdhaXQgdGhpcy5zdG9yYWdlLnNldEl0ZW0oeXMsSlNPTi5zdHJpbmdpZnkodCkpfWNvbnN0IHM9SlNPTi5wYXJzZSh0KTtzLmZvcmNlTG9jYWxNb2RlPWUsYXdhaXQgdGhpcy5zdG9yYWdlLnNldEl0ZW0oeXMsSlNPTi5zdHJpbmdpZnkocykpfX0oeHMpLEFzPW5ldyBjbGFzc3tjb25zdHJ1Y3RvcihlKXt0aGlzLnBlbmRpbmdDb25mbGljdHM9bmV3IE1hcCx0aGlzLnN0b3JlPWU/P25ldyBfcyx0aGlzLnRlbXBsYXRlRW5naW5lPW5ldyBSc31hc3luYyByZWdpc3RlclByb21wdChlKXtjb25zdHtuYW1lOnQsdmVyc2lvbjpzLHByb21wdDpyfT1lO3RoaXMudGVtcGxhdGVFbmdpbmUudmFsaWRhdGVEZWZpbml0aW9uKHIpO2NvbnN0IG49YXdhaXQgdGhpcy5zdG9yZS5nZXQodCk7aWYoIW4pe2NvbnN0IGU9X3MuY3JlYXRlU3RvcmVkUHJvbXB0KHQscyxyKTtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yZS5wdXQoZSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBDcmVhdGVkIHByb21wdCAiJHt0fSIgdiR7c31gKSx7c3RhdHVzOiJjcmVhdGVkIixwcm9tcHQ6ZX19Y29uc3QgYT1mdW5jdGlvbihlLHQpe2NvbnN0IHM9ZS5zcGxpdCgiLiIpLm1hcChOdW1iZXIpLHI9dC5zcGxpdCgiLiIpLm1hcChOdW1iZXIpO2ZvcihsZXQgZT0wO2U8TWF0aC5tYXgocy5sZW5ndGgsci5sZW5ndGgpO2UrKyl7Y29uc3QgdD1zW2VdPz8wLG49cltlXT8/MDtpZih0PG4pcmV0dXJuLTE7aWYodD5uKXJldHVybiAxfXJldHVybiAwfShzLG4udmVyc2lvbik7aWYoMD09PWEpcmV0dXJuIGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gUHJvbXB0ICIke3R9IiB1bmNoYW5nZWQgKHYke3N9KWApLHtzdGF0dXM6InVuY2hhbmdlZCIscHJvbXB0Om59O2lmKGE8MClyZXR1cm4gY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBQcm9tcHQgIiR7dH0iIG5vdCBkb3duZ3JhZGVkICh2JHtuLnZlcnNpb259ID4gdiR7c30pYCkse3N0YXR1czoidW5jaGFuZ2VkIixwcm9tcHQ6bn07aWYoIW4ubG9jYWxseU1vZGlmaWVkKXtjb25zdCBlPW4udmVyc2lvbixhPXsuLi5yLG5hbWU6dCx2ZXJzaW9uOnMsbG9jYWxseU1vZGlmaWVkOiExLGNyZWF0ZWRBdDpuLmNyZWF0ZWRBdCx1cGRhdGVkQXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpfTtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yZS5wdXQoYSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBBdXRvLXVwZGF0ZWQgIiR7dH0iIHYke2V9IC0+IHYke3N9YCkse3N0YXR1czoidXBkYXRlZCIscHJvbXB0OmEscHJldmlvdXNWZXJzaW9uOmV9fWNvbnN0IG89e25hbWU6dCxsb2NhbFZlcnNpb246bi52ZXJzaW9uLHVwc3RyZWFtVmVyc2lvbjpzLGxvY2FsUHJvbXB0Om4sdXBzdHJlYW1Qcm9tcHQ6cn07cmV0dXJuIHRoaXMucGVuZGluZ0NvbmZsaWN0cy5zZXQodCxvKSxjb25zb2xlLmxvZyhgW1Byb21wdE1hbmFnZXJdIFZlcnNpb24gY29uZmxpY3QgZm9yICIke3R9IjogbG9jYWwgdiR7bi52ZXJzaW9ufSAobW9kaWZpZWQpIHZzIHVwc3RyZWFtIHYke3N9YCkse3N0YXR1czoiY29uZmxpY3QiLGNvbmZsaWN0Om99fWFzeW5jIHJlZ2lzdGVyUHJvbXB0cyhlKXtjb25zdCB0PVtdO2Zvcihjb25zdCBzIG9mIGUpe2NvbnN0IGU9YXdhaXQgdGhpcy5yZWdpc3RlclByb21wdChzKTt0LnB1c2goZSl9cmV0dXJuIHR9YXN5bmMgZ2V0UHJvbXB0KGUpe3JldHVybiB0aGlzLnN0b3JlLmdldChlKX1hc3luYyBsaXN0UHJvbXB0cygpe3JldHVybiB0aGlzLnN0b3JlLmxpc3QoKX1hc3luYyB1cGRhdGVQcm9tcHQoZSx0KXt0aGlzLnRlbXBsYXRlRW5naW5lLnZhbGlkYXRlRGVmaW5pdGlvbih0KTtjb25zdCBzPWF3YWl0IHRoaXMuc3RvcmUuZ2V0KGUpO2lmKCFzKXRocm93IG5ldyBFcnJvcihgUHJvbXB0ICIke2V9IiBub3QgZm91bmRgKTtjb25zdCByPXsuLi50LG5hbWU6ZSx2ZXJzaW9uOnMudmVyc2lvbixsb2NhbGx5TW9kaWZpZWQ6ITAsdXBzdHJlYW1WZXJzaW9uOnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1WZXJzaW9uOnMudmVyc2lvbix1cHN0cmVhbVRlbXBsYXRlOnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1UZW1wbGF0ZTpzLnRlbXBsYXRlLHVwc3RyZWFtV2VpZ2h0OnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1XZWlnaHQ6cy53ZWlnaHQsY3JlYXRlZEF0OnMuY3JlYXRlZEF0LHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHIpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gVXNlciBtb2RpZmllZCBwcm9tcHQgIiR7ZX0iYCl9YXN5bmMgZGVsZXRlUHJvbXB0KGUpe2F3YWl0IHRoaXMuc3RvcmUuZGVsZXRlKGUpLHRoaXMucGVuZGluZ0NvbmZsaWN0cy5kZWxldGUoZSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBEZWxldGVkIHByb21wdCAiJHtlfSJgKX1hc3luYyByZXNvbHZlQ29uZmxpY3QoZSx0LHMscil7Y29uc3Qgbj1hd2FpdCB0aGlzLnN0b3JlLmdldChlKTtpZighbil0aHJvdyBuZXcgRXJyb3IoYFByb21wdCAiJHtlfSIgbm90IGZvdW5kYCk7aWYoImxvY2FsIj09PXQpe2NvbnN0IHQ9ey4uLm4sdXBzdHJlYW1WZXJzaW9uOnIsdXBzdHJlYW1UZW1wbGF0ZTpzLnRlbXBsYXRlLHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHQpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gQ29uZmxpY3QgcmVzb2x2ZWQgZm9yICIke2V9Ijoga2VwdCBsb2NhbCB2ZXJzaW9uYCl9ZWxzZXtjb25zdCB0PXsuLi5zLG5hbWU6ZSx2ZXJzaW9uOnIsbG9jYWxseU1vZGlmaWVkOiExLHVwc3RyZWFtVmVyc2lvbjp2b2lkIDAsdXBzdHJlYW1UZW1wbGF0ZTp2b2lkIDAsY3JlYXRlZEF0Om4uY3JlYXRlZEF0LHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHQpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gQ29uZmxpY3QgcmVzb2x2ZWQgZm9yICIke2V9IjogYWNjZXB0ZWQgdXBzdHJlYW0gdiR7cn1gKX10aGlzLnBlbmRpbmdDb25mbGljdHMuZGVsZXRlKGUpfWFzeW5jIHJlc2V0VG9VcHN0cmVhbShlKXtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmUuZ2V0KGUpO2lmKCF0KXRocm93IG5ldyBFcnJvcihgUHJvbXB0ICIke2V9IiBub3QgZm91bmRgKTtpZighdC5sb2NhbGx5TW9kaWZpZWR8fCF0LnVwc3RyZWFtVGVtcGxhdGUpdGhyb3cgbmV3IEVycm9yKGBQcm9tcHQgIiR7ZX0iIGhhcyBubyBvcmlnaW5hbCB2ZXJzaW9uIHRvIHJlc2V0IHRvYCk7Y29uc3Qgcz17Li4udCx0ZW1wbGF0ZTp0LnVwc3RyZWFtVGVtcGxhdGUsd2VpZ2h0OnQudXBzdHJlYW1XZWlnaHQsbG9jYWxseU1vZGlmaWVkOiExLHVwc3RyZWFtVmVyc2lvbjp2b2lkIDAsdXBzdHJlYW1UZW1wbGF0ZTp2b2lkIDAsdXBzdHJlYW1XZWlnaHQ6dm9pZCAwLHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHMpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gUmVzZXQgcHJvbXB0ICIke2V9IiB0byB1cHN0cmVhbSB2ZXJzaW9uYCl9YXN5bmMgcmVuZGVyUHJvbXB0KGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLnN0b3JlLmdldChlKTtpZighcyl0aHJvdyBuZXcgRXJyb3IoYFByb21wdCAiJHtlfSIgbm90IGZvdW5kYCk7Y29uc3Qgcj10aGlzLnRlbXBsYXRlRW5naW5lLnJlbmRlcihzLnRlbXBsYXRlLHMucGFyYW1zPz97fSx0Pz97fSk7cmV0dXJue3JvbGU6cy5yb2xlPz8idXNlciIsY29udGVudDpyLGV4cGVjdF90YWdzOnMuZXhwZWN0X3RhZ3Msd2VpZ2h0OnMud2VpZ2h0LHByb21wdE5hbWU6ZX19Z2V0UGVuZGluZ0NvbmZsaWN0KGUpe3JldHVybiB0aGlzLnBlbmRpbmdDb25mbGljdHMuZ2V0KGUpfWhhc1BlbmRpbmdDb25mbGljdHMoKXtyZXR1cm4gdGhpcy5wZW5kaW5nQ29uZmxpY3RzLnNpemU+MH1nZXRQZW5kaW5nQ29uZmxpY3RzKCl7cmV0dXJuIEFycmF5LmZyb20odGhpcy5wZW5kaW5nQ29uZmxpY3RzLnZhbHVlcygpKX19O2xldCBDcz1udWxsLElzPSExO2Z1bmN0aW9uIE9zKGUsdCl7SXN8fChDcz1wcy5nZXRJbnN0YW5jZShUcyxlLHQpLENzLnNldFByb21wdEhhbmRsZXIoRHMpLElzPSEwLGNvbnNvbGUubG9nKCJbQUkgRGVsZWdhdGUgV29ya2VyXSBJbml0aWFsaXplZCB3aXRoIGNyZWRlbnRpYWwgc2VydmVyOiIsZXx8Iihub3QgY29uZmlndXJlZCkiLCJhbGxvd0xvY2FsTW9kZToiLHQpKX1mdW5jdGlvbiAkcygpe3JldHVybiBDc3x8T3MoKSxDc31jb25zdCBMcz1uZXcgTWFwO2FzeW5jIGZ1bmN0aW9uIE5zKGUsdCl7Y29uc3Qgcz1mcy5nZW5lcmF0ZUlkKCk7cmV0dXJuIG5ldyBQcm9taXNlKChyLG4pPT57THMuc2V0KHMse3Jlc29sdmU6cixyZWplY3Q6bn0pO2NvbnN0IGE9e3R5cGU6InByb21wdCIscHJvbXB0VHlwZTplLHJlcXVlc3RJZDpzLGRhdGE6dH07c2VsZi5wb3N0TWVzc2FnZShhKSxzZXRUaW1lb3V0KCgpPT57THMuaGFzKHMpJiYoTHMuZGVsZXRlKHMpLG4obmV3IEVycm9yKCJQcm9tcHQgdGltZW91dCAtIHVzZXIgZGlkIG5vdCByZXNwb25kIikpKX0sM2U1KX0pfWNvbnN0IERzPXthc3luYyBwcm9tcHRGb3JDb25maWd1cmF0aW9uKCl7Y29uc3QgZT1hd2FpdCBOcyhpcy5DT05GSUdVUkUpLHtwYXNzd29yZDp0LHVzZURlZmF1bHRNb2RlbHM6cywuLi5yfT1lO3JldHVybntjb25maWc6cixwYXNzd29yZDp0LHVzZURlZmF1bHRNb2RlbHM6cz8/ITF9fSxwcm9tcHRGb3JVbmxvY2s6YXN5bmMoKT0+YXdhaXQgTnMoaXMuVU5MT0NLKSxwcm9tcHRGb3JNb2RlbFNlbGVjdGlvbjphc3luYyhlLHQpPT5hd2FpdCBOcyhpcy5NT0RFTF9TRUxFQ1Qse3dlaWdodDplLGF2YWlsYWJsZU1vZGVsczp0fSkscHJvbXB0Rm9yQ29uZmxpY3RSZXNvbHV0aW9uOmFzeW5jIGU9PmF3YWl0IE5zKGlzLlBST01QVF9DT05GTElDVCxlKX07c2VsZi5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIixhc3luYyBlPT57Y29uc3QgdD1lLmRhdGE7aWYoInByb21wdFJlc3BvbnNlIj09PXQudHlwZSl7Y29uc3QgZT10LHM9THMuZ2V0KGUucmVxdWVzdElkKTtyZXR1cm4gdm9pZChzJiYoTHMuZGVsZXRlKGUucmVxdWVzdElkKSxlLnN1Y2Nlc3M/cy5yZXNvbHZlKGUuZGF0YSk6cy5yZWplY3QobmV3IEVycm9yKGUuZXJyb3J8fCJQcm9tcHQgZmFpbGVkIikpKSl9aWYoIWZzLnZhbGlkYXRlTWVzc2FnZSh0KSl7Y29uc3QgZT1mcy5jcmVhdGVFcnJvclJlc3BvbnNlKHQ/LmlkfHwidW5rbm93biIsIkludmFsaWQgbWVzc2FnZSBmb3JtYXQiKTtyZXR1cm4gdm9pZCBzZWxmLnBvc3RNZXNzYWdlKGUpfXRyeXtjb25zdCBlPWF3YWl0IGFzeW5jIGZ1bmN0aW9uKGUpe2NvbnN0e2lkOnQsY29tbWFuZDpzLHBheWxvYWQ6cn09ZTtzd2l0Y2gocyl7Y2FzZSBvcy5JTklUOnJldHVybiBPcyhyLmNyZWRlbnRpYWxTZXJ2ZXJVcmwsci5hbGxvd0xvY2FsTW9kZSksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQpO2Nhc2Ugb3MuQ09ORklHVVJFOnJldHVybiBhd2FpdCAkcygpLmNvbmZpZ3VyZShyLmNvbmZpZyxyLnBhc3N3b3JkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5NQUtFX1JFUVVFU1Q6ci5vcHRpb25zLnN0cmVhbSYmKHIub3B0aW9ucy5vblN0cmVhbT1lPT57Y29uc3Qgcz17dHlwZToic3RyZWFtQ2h1bmsiLHJlcXVlc3RJZDp0LGNodW5rOmV9O3NlbGYucG9zdE1lc3NhZ2Uocyl9KTtjb25zdCBlPWF3YWl0ICRzKCkubWFrZVJlcXVlc3Qoci5vcHRpb25zKTtpZihyLm9wdGlvbnMuc3RyZWFtKXtjb25zdCBlPXt0eXBlOiJzdHJlYW1Db21wbGV0ZSIscmVxdWVzdElkOnR9O3NlbGYucG9zdE1lc3NhZ2UoZSl9cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGUpO2Nhc2Ugb3MuR0VUX1NUQVRVUzpjb25zb2xlLmxvZygiW1dvcmtlcl0gR0VUX1NUQVRVUyBjYWxsZWQsIGRlbGVnYXRlIGluaXRpYWxpemVkOiIsSXMpO2NvbnN0IG49YXdhaXQgJHMoKS5nZXRTdGF0dXMoKTtyZXR1cm4gY29uc29sZS5sb2coIltXb3JrZXJdIEdFVF9TVEFUVVMgcmVzdWx0OiIsbiksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsbik7Y2FzZSBvcy5MT0NLOnJldHVybiBhd2FpdCAkcygpLmxvY2soKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5SRVNFVDpyZXR1cm4gYXdhaXQgJHMoKS5yZXNldCgpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLlVQREFURV9DUkVERU5USUFMUzpyZXR1cm4gYXdhaXQgJHMoKS51cGRhdGVDcmVkZW50aWFscyhyLmNyZWRlbnRpYWxzLHIucGFzc3dvcmQpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLklTX1JFQURZOmNvbnN0IGE9YXdhaXQgJHMoKS5pc1JlYWR5KCk7cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGEpO2Nhc2Ugb3MuVU5MT0NLOnJldHVybiBhd2FpdCAkcygpLnVubG9jayhyLnBhc3N3b3JkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5HRVRfU0VUVVBfVVJMOmNvbnN0IG89JHMoKS5nZXRDcmVkZW50aWFsU2VydmVyU2V0dXBVcmwoKTtyZXR1cm4gZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsbyk7Y2FzZSBvcy5GRVRDSF9NT0RFTFM6Y29uc3QgaT1hd2FpdCAkcygpLmZldGNoQXZhaWxhYmxlTW9kZWxzKCk7cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGkpO2Nhc2Ugb3MuU0VUX0xPQ0FMX01PREU6cmV0dXJuIGF3YWl0ICRzKCkuc2V0Rm9yY2VMb2NhbE1vZGUoci5lbmFibGVkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5JU19MT0NBTF9NT0RFX0FMTE9XRUQ6Y29uc3QgYz0kcygpLmlzTG9jYWxNb2RlQWxsb3dlZCgpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxjKTtjYXNlIG9zLklTX0xPQ0FMX01PREVfRk9SQ0VEOmNvbnN0IGw9JHMoKS5pc0xvY2FsTW9kZUZvcmNlZCgpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxsKTtjYXNlIG9zLkNPTkZJR1VSRV9MT0NBTDpjb25zb2xlLmxvZygiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIHJlY2VpdmVkOiIse2NvbmZpZzpyLmNvbmZpZyxoYXNQYXNzd29yZDohIXIucGFzc3dvcmQsdXNlRGVmYXVsdE1vZGVsczpyLnVzZURlZmF1bHRNb2RlbHN9KTt0cnl7cmV0dXJuIGF3YWl0ICRzKCkuY29uZmlndXJlTG9jYWwoci5jb25maWcsci5wYXNzd29yZCxyLnVzZURlZmF1bHRNb2RlbHM/PyEwKSxjb25zb2xlLmxvZygiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkiKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCl9Y2F0Y2goZSl7dGhyb3cgY29uc29sZS5lcnJvcigiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIGVycm9yOiIsZSxlLm1lc3NhZ2UsZS5zdGFjayksZX1jYXNlIG9zLlJFR0lTVEVSX1BST01QVDp7Y29uc3QgZT1hd2FpdCBBcy5yZWdpc3RlclByb21wdChyLnJlZ2lzdHJhdGlvbik7aWYoImNvbmZsaWN0Ij09PWUuc3RhdHVzKXtjb25zdCBzPWF3YWl0IERzLnByb21wdEZvckNvbmZsaWN0UmVzb2x1dGlvbihlLmNvbmZsaWN0KTthd2FpdCBBcy5yZXNvbHZlQ29uZmxpY3QoZS5jb25mbGljdC5uYW1lLHMsZS5jb25mbGljdC51cHN0cmVhbVByb21wdCxlLmNvbmZsaWN0LnVwc3RyZWFtVmVyc2lvbik7Y29uc3Qgcj1hd2FpdCBBcy5nZXRQcm9tcHQoZS5jb25mbGljdC5uYW1lKTtyZXR1cm4idXBzdHJlYW0iPT09cz9mcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCx7c3RhdHVzOiJ1cGRhdGVkIixwcm9tcHQ6cixwcmV2aW91c1ZlcnNpb246ZS5jb25mbGljdC5sb2NhbFZlcnNpb259KTpmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCx7c3RhdHVzOiJ1bmNoYW5nZWQiLHByb21wdDpyfSl9cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGUpfWNhc2Ugb3MuUkVHSVNURVJfUFJPTVBUUzp7Y29uc3QgZT1bXTtmb3IoY29uc3QgdCBvZiByLnJlZ2lzdHJhdGlvbnMpe2NvbnN0IHM9YXdhaXQgQXMucmVnaXN0ZXJQcm9tcHQodCk7aWYoImNvbmZsaWN0Ij09PXMuc3RhdHVzKXtjb25zdCB0PWF3YWl0IERzLnByb21wdEZvckNvbmZsaWN0UmVzb2x1dGlvbihzLmNvbmZsaWN0KTthd2FpdCBBcy5yZXNvbHZlQ29uZmxpY3Qocy5jb25mbGljdC5uYW1lLHQscy5jb25mbGljdC51cHN0cmVhbVByb21wdCxzLmNvbmZsaWN0LnVwc3RyZWFtVmVyc2lvbik7Y29uc3Qgcj1hd2FpdCBBcy5nZXRQcm9tcHQocy5jb25mbGljdC5uYW1lKTsidXBzdHJlYW0iPT09dD9lLnB1c2goe3N0YXR1czoidXBkYXRlZCIscHJvbXB0OnIscHJldmlvdXNWZXJzaW9uOnMuY29uZmxpY3QubG9jYWxWZXJzaW9ufSk6ZS5wdXNoKHtzdGF0dXM6InVuY2hhbmdlZCIscHJvbXB0OnJ9KX1lbHNlIGUucHVzaChzKX1yZXR1cm4gZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsZSl9Y2FzZSBvcy5HRVRfUFJPTVBUOntjb25zdCBlPWF3YWl0IEFzLmdldFByb21wdChyLm5hbWUpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1jYXNlIG9zLkxJU1RfUFJPTVBUUzp7Y29uc3QgZT1hd2FpdCBBcy5saXN0UHJvbXB0cygpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1jYXNlIG9zLlVQREFURV9QUk9NUFQ6cmV0dXJuIGF3YWl0IEFzLnVwZGF0ZVByb21wdChyLm5hbWUsci5wcm9tcHQpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLkRFTEVURV9QUk9NUFQ6cmV0dXJuIGF3YWl0IEFzLmRlbGV0ZVByb21wdChyLm5hbWUpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLlJFU0VUX1BST01QVDpyZXR1cm4gYXdhaXQgQXMucmVzZXRUb1Vwc3RyZWFtKHIubmFtZSksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQpO2Nhc2Ugb3MuUkVTT0xWRV9DT05GTElDVDpyZXR1cm4gYXdhaXQgQXMucmVzb2x2ZUNvbmZsaWN0KHIubmFtZSxyLmNob2ljZSxyLnVwc3RyZWFtUHJvbXB0LHIudXBzdHJlYW1WZXJzaW9uKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5SRU5ERVJfUFJPTVBUOntjb25zdCBlPWF3YWl0IEFzLnJlbmRlclByb21wdChyLm5hbWUsci5wYXJhbXMpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVW5rbm93biBjb21tYW5kOiAke3N9YCl9fSh0KTtzZWxmLnBvc3RNZXNzYWdlKGUpfWNhdGNoKGUpe2NvbnN0IHM9ZnMuY3JlYXRlRXJyb3JSZXNwb25zZSh0LmlkLGUpO3NlbGYucG9zdE1lc3NhZ2Uocyl9fSksY29uc29sZS5sb2coIltBSSBEZWxlZ2F0ZSBXb3JrZXJdIFJlYWR5IHRvIHJlY2VpdmUgY29tbWFuZHMiKX0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPWFpLWRlbGVnYXRlLXdvcmtlci5qcy5tYXA='; + +/** + * Decode the base64-encoded worker source. + */ +function decodeWorkerSource(): string { + // Use atob for browser environment + if (typeof atob === 'function') { + return atob(EMBEDDED_WORKER_BASE64); + } + // Fallback for Node.js environment (for testing) + return Buffer.from(EMBEDDED_WORKER_BASE64, 'base64').toString('utf8'); +} + +/** + * The worker source code as a string. + * Lazily decoded on first access. + */ +let _cachedSource: string | null = null; +export function getWorkerSource(): string { + if (_cachedSource === null) { + _cachedSource = decodeWorkerSource(); + } + return _cachedSource; +} + +/** + * Creates a Blob URL for the embedded worker. + * The URL should be revoked with URL.revokeObjectURL() when no longer needed. + */ +export function createWorkerBlobUrl(): string { + const source = getWorkerSource(); + const blob = new Blob([source], { type: 'application/javascript' }); + return URL.createObjectURL(blob); +} + +/** + * Version marker to help with debugging cache issues. + * This is extracted from the worker bundle if present. + */ +export const EMBEDDED_WORKER_VERSION: string = '0.3.4'; diff --git a/src/worker/worker.ts b/src/worker/worker.ts index 7738e53..720eb02 100644 --- a/src/worker/worker.ts +++ b/src/worker/worker.ts @@ -13,8 +13,11 @@ import { PromptConflict } from '../types/prompts'; * Credentials and sensitive data NEVER leave this context */ +// Version injected by webpack DefinePlugin from package.json +declare const __AI_DELEGATE_VERSION__: string; + // Version marker for debugging cache issues -console.log('[AI Delegate Worker] Version: 0.3.2'); +console.log(`[AI Delegate Worker] Version: ${__AI_DELEGATE_VERSION__}`); // Storage and config manager (initialized immediately) const storage = new IndexedDBAdapter(); diff --git a/webpack.main.config.js b/webpack.main.config.js new file mode 100644 index 0000000..f48cd41 --- /dev/null +++ b/webpack.main.config.js @@ -0,0 +1,111 @@ +/** + * Webpack config for building the main bundle, server, and credential-server. + * This is built after the worker bundle and embed-worker script have run. + */ +const path = require('path'); + +module.exports = [ + // Main bundle (for the browser/main thread) + { + entry: './src/index.ts', + output: { + filename: 'ai-delegate.js', + path: path.resolve(__dirname, 'dist'), + library: { + name: 'AiDelegate', + type: 'umd', + export: 'default' + }, + globalObject: 'this' + }, + resolve: { + extensions: ['.ts', '.js'] + }, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + optimization: { + minimize: true + }, + devtool: 'source-map' + }, + // Server bundle (for Node.js) + { + entry: './src/server/index.ts', + output: { + filename: 'server/index.js', + path: path.resolve(__dirname, 'dist'), + library: { + type: 'commonjs2' + } + }, + target: 'node', + externals: { + // Don't bundle Node.js built-in modules + fs: 'commonjs fs', + path: 'commonjs path', + http: 'commonjs http', + 'better-sqlite3': 'commonjs better-sqlite3' + }, + resolve: { + extensions: ['.ts', '.js'] + }, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + optimization: { + minimize: false // Don't minimize server code for easier debugging + }, + devtool: 'source-map' + }, + // Credential Server bundle (for Node.js) + { + entry: './src/credential-server/index.ts', + output: { + filename: 'credential-server/index.js', + path: path.resolve(__dirname, 'dist'), + library: { + type: 'commonjs2' + } + }, + target: 'node', + externals: { + // Don't bundle Node.js built-in modules + fs: 'commonjs fs', + path: 'commonjs path', + http: 'commonjs http', + https: 'commonjs https', + crypto: 'commonjs crypto', + url: 'commonjs url', + 'better-sqlite3': 'commonjs better-sqlite3' + }, + resolve: { + extensions: ['.ts', '.js'] + }, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + optimization: { + minimize: false // Don't minimize server code for easier debugging + }, + devtool: 'source-map' + } +]; diff --git a/webpack.worker.config.js b/webpack.worker.config.js new file mode 100644 index 0000000..ceabb10 --- /dev/null +++ b/webpack.worker.config.js @@ -0,0 +1,38 @@ +/** + * Webpack config for building the worker bundle. + * This is built first, before the main bundle. + */ +const path = require('path'); +const webpack = require('webpack'); +const packageJson = require('./package.json'); + +module.exports = { + entry: './src/worker-entry.ts', + output: { + filename: 'ai-delegate-worker.js', + path: path.resolve(__dirname, 'dist'), + globalObject: 'self' // Important: use 'self' for worker context + }, + target: 'webworker', // Target web worker environment + resolve: { + extensions: ['.ts', '.js'] + }, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + optimization: { + minimize: true + }, + plugins: [ + new webpack.DefinePlugin({ + __AI_DELEGATE_VERSION__: JSON.stringify(packageJson.version) + }) + ], + devtool: 'source-map' +}; -- GitLab From f5777ed8bf75bdfb84c46e4a12792408b282ecad Mon Sep 17 00:00:00 2001 From: Lembot Date: Fri, 9 Jan 2026 17:47:47 -0500 Subject: [PATCH 2/3] chore: gitignore generated embedded-worker.ts Per review feedback, remove the generated embedded-worker.ts from version control and add it to .gitignore. Users will generate it on build. Co-Authored-By: Claude Opus 4.5 --- .gitignore | 3 ++ src/worker/embedded-worker.ts | 53 ----------------------------------- 2 files changed, 3 insertions(+), 53 deletions(-) delete mode 100644 src/worker/embedded-worker.ts diff --git a/.gitignore b/.gitignore index 73632f4..2188385 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,8 @@ node_modules/ # Build output dist/ +# Generated files +src/worker/embedded-worker.ts + # Credential database (contains encrypted API keys) credentials.db diff --git a/src/worker/embedded-worker.ts b/src/worker/embedded-worker.ts deleted file mode 100644 index dd61196..0000000 --- a/src/worker/embedded-worker.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * AUTO-GENERATED FILE - DO NOT EDIT - * - * This file contains the embedded worker bundle for inline worker creation. - * Generated by scripts/embed-worker.js - * - * To regenerate: npm run build:worker && npm run embed-worker - */ - -/** - * The worker source code as a base64-encoded string. - */ -const EMBEDDED_WORKER_BASE64 = 'KCgpPT57InVzZSBzdHJpY3QiO2NsYXNzIGV7Y29uc3RydWN0b3IoZSx0KXt0aGlzLnByb3ZpZGVyPWUsdGhpcy5tb2RlbE1hcHBpbmc9dHx8e319Z2V0TW9kZWwoZSl7cmV0dXJuIHRoaXMubW9kZWxNYXBwaW5nW2VdfWdldE1hcHBpbmcoKXtyZXR1cm57Li4udGhpcy5tb2RlbE1hcHBpbmd9fXNldE1vZGVsKGUsdCl7dGhpcy5tb2RlbE1hcHBpbmdbZV09dH11cGRhdGVNYXBwaW5nKGUpe3RoaXMubW9kZWxNYXBwaW5nPXsuLi50aGlzLm1vZGVsTWFwcGluZywuLi5lfX1yZXNldFRvRGVmYXVsdHMoKXt0aGlzLm1vZGVsTWFwcGluZz17fX1jbGVhcigpe3RoaXMubW9kZWxNYXBwaW5nPXt9fXZhbGlkYXRlKCl7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB0aGlzLm1vZGVsTWFwcGluZy5saWdodCYmdGhpcy5tb2RlbE1hcHBpbmcubGlnaHQubGVuZ3RoPjAmJiJzdHJpbmciPT10eXBlb2YgdGhpcy5tb2RlbE1hcHBpbmcubW9kZXJhdGUmJnRoaXMubW9kZWxNYXBwaW5nLm1vZGVyYXRlLmxlbmd0aD4wJiYic3RyaW5nIj09dHlwZW9mIHRoaXMubW9kZWxNYXBwaW5nLmhlYXZ5JiZ0aGlzLm1vZGVsTWFwcGluZy5oZWF2eS5sZW5ndGg+MH1nZXRQcm92aWRlcigpe3JldHVybiB0aGlzLnByb3ZpZGVyfXNldFByb3ZpZGVyKGUpe3RoaXMucHJvdmlkZXI9ZSx0aGlzLnJlc2V0VG9EZWZhdWx0cygpfX1mdW5jdGlvbiB0KGUsdCxzLHIsbil7aWYoIm0iPT09cil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGUiKTtpZigiYSI9PT1yJiYhbil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXIiKTtpZigiZnVuY3Rpb24iPT10eXBlb2YgdD9lIT09dHx8IW46IXQuaGFzKGUpKXRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0Iik7cmV0dXJuImEiPT09cj9uLmNhbGwoZSxzKTpuP24udmFsdWU9czp0LnNldChlLHMpLHN9ZnVuY3Rpb24gcyhlLHQscyxyKXtpZigiYSI9PT1zJiYhcil0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXIiKTtpZigiZnVuY3Rpb24iPT10eXBlb2YgdD9lIT09dHx8IXI6IXQuaGFzKGUpKXRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdCIpO3JldHVybiJtIj09PXM/cjoiYSI9PT1zP3IuY2FsbChlKTpyP3IudmFsdWU6dC5nZXQoZSl9bGV0IHI9ZnVuY3Rpb24oKXtjb25zdHtjcnlwdG86ZX09Z2xvYmFsVGhpcztpZihlPy5yYW5kb21VVUlEKXJldHVybiByPWUucmFuZG9tVVVJRC5iaW5kKGUpLGUucmFuZG9tVVVJRCgpO2NvbnN0IHQ9bmV3IFVpbnQ4QXJyYXkoMSkscz1lPygpPT5lLmdldFJhbmRvbVZhbHVlcyh0KVswXTooKT0+MjU1Kk1hdGgucmFuZG9tKCkmMjU1O3JldHVybiIxMDAwMDAwMC0xMDAwLTQwMDAtODAwMC0xMDAwMDAwMDAwMDAiLnJlcGxhY2UoL1swMThdL2csZT0+KCtlXnMoKSYxNT4+K2UvNCkudG9TdHJpbmcoMTYpKX07ZnVuY3Rpb24gbihlKXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIGUmJm51bGwhPT1lJiYoIm5hbWUiaW4gZSYmIkFib3J0RXJyb3IiPT09ZS5uYW1lfHwibWVzc2FnZSJpbiBlJiZTdHJpbmcoZS5tZXNzYWdlKS5pbmNsdWRlcygiRmV0Y2hSZXF1ZXN0Q2FuY2VsZWRFeGNlcHRpb24iKSl9Y29uc3QgYT1lPT57aWYoZSBpbnN0YW5jZW9mIEVycm9yKXJldHVybiBlO2lmKCJvYmplY3QiPT10eXBlb2YgZSYmbnVsbCE9PWUpe3RyeXtpZigiW29iamVjdCBFcnJvcl0iPT09T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUpKXtjb25zdCB0PW5ldyBFcnJvcihlLm1lc3NhZ2UsZS5jYXVzZT97Y2F1c2U6ZS5jYXVzZX06e30pO3JldHVybiBlLnN0YWNrJiYodC5zdGFjaz1lLnN0YWNrKSxlLmNhdXNlJiYhdC5jYXVzZSYmKHQuY2F1c2U9ZS5jYXVzZSksZS5uYW1lJiYodC5uYW1lPWUubmFtZSksdH19Y2F0Y2h7fXRyeXtyZXR1cm4gbmV3IEVycm9yKEpTT04uc3RyaW5naWZ5KGUpKX1jYXRjaHt9fXJldHVybiBuZXcgRXJyb3IoZSl9O2NsYXNzIG8gZXh0ZW5kcyBFcnJvcnt9Y2xhc3MgaSBleHRlbmRzIG97Y29uc3RydWN0b3IoZSx0LHMscil7c3VwZXIoYCR7aS5tYWtlTWVzc2FnZShlLHQscyl9YCksdGhpcy5zdGF0dXM9ZSx0aGlzLmhlYWRlcnM9cix0aGlzLnJlcXVlc3RJRD1yPy5nZXQoInJlcXVlc3QtaWQiKSx0aGlzLmVycm9yPXR9c3RhdGljIG1ha2VNZXNzYWdlKGUsdCxzKXtjb25zdCByPXQ/Lm1lc3NhZ2U/InN0cmluZyI9PXR5cGVvZiB0Lm1lc3NhZ2U/dC5tZXNzYWdlOkpTT04uc3RyaW5naWZ5KHQubWVzc2FnZSk6dD9KU09OLnN0cmluZ2lmeSh0KTpzO3JldHVybiBlJiZyP2Ake2V9ICR7cn1gOmU/YCR7ZX0gc3RhdHVzIGNvZGUgKG5vIGJvZHkpYDpyfHwiKG5vIHN0YXR1cyBjb2RlIG9yIGJvZHkpIn1zdGF0aWMgZ2VuZXJhdGUoZSx0LHMscil7aWYoIWV8fCFyKXJldHVybiBuZXcgbCh7bWVzc2FnZTpzLGNhdXNlOmEodCl9KTtjb25zdCBuPXQ7cmV0dXJuIDQwMD09PWU/bmV3IGgoZSxuLHMscik6NDAxPT09ZT9uZXcgdShlLG4scyxyKTo0MDM9PT1lP25ldyBwKGUsbixzLHIpOjQwND09PWU/bmV3IGYoZSxuLHMscik6NDA5PT09ZT9uZXcgbShlLG4scyxyKTo0MjI9PT1lP25ldyBnKGUsbixzLHIpOjQyOT09PWU/bmV3IHcoZSxuLHMscik6ZT49NTAwP25ldyB5KGUsbixzLHIpOm5ldyBpKGUsbixzLHIpfX1jbGFzcyBjIGV4dGVuZHMgaXtjb25zdHJ1Y3Rvcih7bWVzc2FnZTplfT17fSl7c3VwZXIodm9pZCAwLHZvaWQgMCxlfHwiUmVxdWVzdCB3YXMgYWJvcnRlZC4iLHZvaWQgMCl9fWNsYXNzIGwgZXh0ZW5kcyBpe2NvbnN0cnVjdG9yKHttZXNzYWdlOmUsY2F1c2U6dH0pe3N1cGVyKHZvaWQgMCx2b2lkIDAsZXx8IkNvbm5lY3Rpb24gZXJyb3IuIix2b2lkIDApLHQmJih0aGlzLmNhdXNlPXQpfX1jbGFzcyBkIGV4dGVuZHMgbHtjb25zdHJ1Y3Rvcih7bWVzc2FnZTplfT17fSl7c3VwZXIoe21lc3NhZ2U6ZT8/IlJlcXVlc3QgdGltZWQgb3V0LiJ9KX19Y2xhc3MgaCBleHRlbmRzIGl7fWNsYXNzIHUgZXh0ZW5kcyBpe31jbGFzcyBwIGV4dGVuZHMgaXt9Y2xhc3MgZiBleHRlbmRzIGl7fWNsYXNzIG0gZXh0ZW5kcyBpe31jbGFzcyBnIGV4dGVuZHMgaXt9Y2xhc3MgdyBleHRlbmRzIGl7fWNsYXNzIHkgZXh0ZW5kcyBpe31jb25zdCBiPS9eW2Etel1bYS16MC05Ky4tXSo6L2k7bGV0IHY9ZT0+KHY9QXJyYXkuaXNBcnJheSx2KGUpKSxfPXY7ZnVuY3Rpb24gayhlKXtyZXR1cm4ib2JqZWN0IiE9dHlwZW9mIGU/e306ZT8/e319Y29uc3QgUz1lPT57dHJ5e3JldHVybiBKU09OLnBhcnNlKGUpfWNhdGNoKGUpe3JldHVybn19LE09IjAuNzEuMCIsUD0oKT0+e2NvbnN0IGU9InVuZGVmaW5lZCIhPXR5cGVvZiBEZW5vJiZudWxsIT1EZW5vLmJ1aWxkPyJkZW5vIjoidW5kZWZpbmVkIiE9dHlwZW9mIEVkZ2VSdW50aW1lPyJlZGdlIjoiW29iamVjdCBwcm9jZXNzXSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodm9pZCAwIT09Z2xvYmFsVGhpcy5wcm9jZXNzP2dsb2JhbFRoaXMucHJvY2VzczowKT8ibm9kZSI6InVua25vd24iO2lmKCJkZW5vIj09PWUpcmV0dXJueyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjpSKERlbm8uYnVpbGQub3MpLCJYLVN0YWlubGVzcy1BcmNoIjpFKERlbm8uYnVpbGQuYXJjaCksIlgtU3RhaW5sZXNzLVJ1bnRpbWUiOiJkZW5vIiwiWC1TdGFpbmxlc3MtUnVudGltZS1WZXJzaW9uIjoic3RyaW5nIj09dHlwZW9mIERlbm8udmVyc2lvbj9EZW5vLnZlcnNpb246RGVuby52ZXJzaW9uPy5kZW5vPz8idW5rbm93biJ9O2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgRWRnZVJ1bnRpbWUpcmV0dXJueyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjoiVW5rbm93biIsIlgtU3RhaW5sZXNzLUFyY2giOmBvdGhlcjoke0VkZ2VSdW50aW1lfWAsIlgtU3RhaW5sZXNzLVJ1bnRpbWUiOiJlZGdlIiwiWC1TdGFpbmxlc3MtUnVudGltZS1WZXJzaW9uIjpnbG9iYWxUaGlzLnByb2Nlc3MudmVyc2lvbn07aWYoIm5vZGUiPT09ZSlyZXR1cm57IlgtU3RhaW5sZXNzLUxhbmciOiJqcyIsIlgtU3RhaW5sZXNzLVBhY2thZ2UtVmVyc2lvbiI6TSwiWC1TdGFpbmxlc3MtT1MiOlIoZ2xvYmFsVGhpcy5wcm9jZXNzLnBsYXRmb3JtPz8idW5rbm93biIpLCJYLVN0YWlubGVzcy1BcmNoIjpFKGdsb2JhbFRoaXMucHJvY2Vzcy5hcmNoPz8idW5rbm93biIpLCJYLVN0YWlubGVzcy1SdW50aW1lIjoibm9kZSIsIlgtU3RhaW5sZXNzLVJ1bnRpbWUtVmVyc2lvbiI6Z2xvYmFsVGhpcy5wcm9jZXNzLnZlcnNpb24/PyJ1bmtub3duIn07Y29uc3QgdD1mdW5jdGlvbigpe2lmKCJ1bmRlZmluZWQiPT10eXBlb2YgbmF2aWdhdG9yfHwhbmF2aWdhdG9yKXJldHVybiBudWxsO2NvbnN0IGU9W3trZXk6ImVkZ2UiLHBhdHRlcm46L0VkZ2UoPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6ImllIixwYXR0ZXJuOi9NU0lFKD86XFcrKFxkKylcLihcZCspKD86XC4oXGQrKSk/KT8vfSx7a2V5OiJpZSIscGF0dGVybjovVHJpZGVudCg/Oi4qcnZcOihcZCspXC4oXGQrKSg/OlwuKFxkKykpPyk/L30se2tleToiY2hyb21lIixwYXR0ZXJuOi9DaHJvbWUoPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6ImZpcmVmb3giLHBhdHRlcm46L0ZpcmVmb3goPzpcVysoXGQrKVwuKFxkKykoPzpcLihcZCspKT8pPy99LHtrZXk6InNhZmFyaSIscGF0dGVybjovKD86VmVyc2lvblxXKyhcZCspXC4oXGQrKSg/OlwuKFxkKykpPyk/KD86XFcrTW9iaWxlXFMqKT9cVytTYWZhcmkvfV07Zm9yKGNvbnN0e2tleTp0LHBhdHRlcm46c31vZiBlKXtjb25zdCBlPXMuZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KTtpZihlKXJldHVybnticm93c2VyOnQsdmVyc2lvbjpgJHtlWzFdfHwwfS4ke2VbMl18fDB9LiR7ZVszXXx8MH1gfX1yZXR1cm4gbnVsbH0oKTtyZXR1cm4gdD97IlgtU3RhaW5sZXNzLUxhbmciOiJqcyIsIlgtU3RhaW5sZXNzLVBhY2thZ2UtVmVyc2lvbiI6TSwiWC1TdGFpbmxlc3MtT1MiOiJVbmtub3duIiwiWC1TdGFpbmxlc3MtQXJjaCI6InVua25vd24iLCJYLVN0YWlubGVzcy1SdW50aW1lIjpgYnJvd3Nlcjoke3QuYnJvd3Nlcn1gLCJYLVN0YWlubGVzcy1SdW50aW1lLVZlcnNpb24iOnQudmVyc2lvbn06eyJYLVN0YWlubGVzcy1MYW5nIjoianMiLCJYLVN0YWlubGVzcy1QYWNrYWdlLVZlcnNpb24iOk0sIlgtU3RhaW5sZXNzLU9TIjoiVW5rbm93biIsIlgtU3RhaW5sZXNzLUFyY2giOiJ1bmtub3duIiwiWC1TdGFpbmxlc3MtUnVudGltZSI6InVua25vd24iLCJYLVN0YWlubGVzcy1SdW50aW1lLVZlcnNpb24iOiJ1bmtub3duIn19LEU9ZT0+IngzMiI9PT1lPyJ4MzIiOiJ4ODZfNjQiPT09ZXx8Ing2NCI9PT1lPyJ4NjQiOiJhcm0iPT09ZT8iYXJtIjoiYWFyY2g2NCI9PT1lfHwiYXJtNjQiPT09ZT8iYXJtNjQiOmU/YG90aGVyOiR7ZX1gOiJ1bmtub3duIixSPWU9PihlPWUudG9Mb3dlckNhc2UoKSkuaW5jbHVkZXMoImlvcyIpPyJpT1MiOiJhbmRyb2lkIj09PWU/IkFuZHJvaWQiOiJkYXJ3aW4iPT09ZT8iTWFjT1MiOiJ3aW4zMiI9PT1lPyJXaW5kb3dzIjoiZnJlZWJzZCI9PT1lPyJGcmVlQlNEIjoib3BlbmJzZCI9PT1lPyJPcGVuQlNEIjoibGludXgiPT09ZT8iTGludXgiOmU/YE90aGVyOiR7ZX1gOiJVbmtub3duIjtsZXQgeDtmdW5jdGlvbiBUKC4uLmUpe2NvbnN0IHQ9Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTtpZih2b2lkIDA9PT10KXRocm93IG5ldyBFcnJvcigiYFJlYWRhYmxlU3RyZWFtYCBpcyBub3QgZGVmaW5lZCBhcyBhIGdsb2JhbDsgWW91IHdpbGwgbmVlZCB0byBwb2x5ZmlsbCBpdCwgYGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0gPSBSZWFkYWJsZVN0cmVhbWAiKTtyZXR1cm4gbmV3IHQoLi4uZSl9ZnVuY3Rpb24gQShlKXtsZXQgdD1TeW1ib2wuYXN5bmNJdGVyYXRvciBpbiBlP2VbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk6ZVtTeW1ib2wuaXRlcmF0b3JdKCk7cmV0dXJuIFQoe3N0YXJ0KCl7fSxhc3luYyBwdWxsKGUpe2NvbnN0e2RvbmU6cyx2YWx1ZTpyfT1hd2FpdCB0Lm5leHQoKTtzP2UuY2xvc2UoKTplLmVucXVldWUocil9LGFzeW5jIGNhbmNlbCgpe2F3YWl0KHQucmV0dXJuPy4oKSl9fSl9ZnVuY3Rpb24gQyhlKXtpZihlW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSlyZXR1cm4gZTtjb25zdCB0PWUuZ2V0UmVhZGVyKCk7cmV0dXJue2FzeW5jIG5leHQoKXt0cnl7Y29uc3QgZT1hd2FpdCB0LnJlYWQoKTtyZXR1cm4gZT8uZG9uZSYmdC5yZWxlYXNlTG9jaygpLGV9Y2F0Y2goZSl7dGhyb3cgdC5yZWxlYXNlTG9jaygpLGV9fSxhc3luYyByZXR1cm4oKXtjb25zdCBlPXQuY2FuY2VsKCk7cmV0dXJuIHQucmVsZWFzZUxvY2soKSxhd2FpdCBlLHtkb25lOiEwLHZhbHVlOnZvaWQgMH19LFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKXtyZXR1cm4gdGhpc319fWNvbnN0IEk9KHtoZWFkZXJzOmUsYm9keTp0fSk9Pih7Ym9keUhlYWRlcnM6eyJjb250ZW50LXR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIn0sYm9keTpKU09OLnN0cmluZ2lmeSh0KX0pO2xldCBPLCQ7ZnVuY3Rpb24gTChlKXtsZXQgdDtyZXR1cm4oTz8/KHQ9bmV3IGdsb2JhbFRoaXMuVGV4dEVuY29kZXIsTz10LmVuY29kZS5iaW5kKHQpKSkoZSl9ZnVuY3Rpb24gTihlKXtsZXQgdDtyZXR1cm4oJD8/KHQ9bmV3IGdsb2JhbFRoaXMuVGV4dERlY29kZXIsJD10LmRlY29kZS5iaW5kKHQpKSkoZSl9dmFyIEQsVTtjbGFzcyBxe2NvbnN0cnVjdG9yKCl7RC5zZXQodGhpcyx2b2lkIDApLFUuc2V0KHRoaXMsdm9pZCAwKSx0KHRoaXMsRCxuZXcgVWludDhBcnJheSwiZiIpLHQodGhpcyxVLG51bGwsImYiKX1kZWNvZGUoZSl7aWYobnVsbD09ZSlyZXR1cm5bXTtjb25zdCByPWUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9uZXcgVWludDhBcnJheShlKToic3RyaW5nIj09dHlwZW9mIGU/TChlKTplO3QodGhpcyxELGZ1bmN0aW9uKGUpe2xldCB0PTA7Zm9yKGNvbnN0IHMgb2YgZSl0Kz1zLmxlbmd0aDtjb25zdCBzPW5ldyBVaW50OEFycmF5KHQpO2xldCByPTA7Zm9yKGNvbnN0IHQgb2YgZSlzLnNldCh0LHIpLHIrPXQubGVuZ3RoO3JldHVybiBzfShbcyh0aGlzLEQsImYiKSxyXSksImYiKTtjb25zdCBuPVtdO2xldCBhO2Zvcig7bnVsbCE9KGE9aihzKHRoaXMsRCwiZiIpLHModGhpcyxVLCJmIikpKTspe2lmKGEuY2FycmlhZ2UmJm51bGw9PXModGhpcyxVLCJmIikpe3QodGhpcyxVLGEuaW5kZXgsImYiKTtjb250aW51ZX1pZihudWxsIT1zKHRoaXMsVSwiZiIpJiYoYS5pbmRleCE9PXModGhpcyxVLCJmIikrMXx8YS5jYXJyaWFnZSkpe24ucHVzaChOKHModGhpcyxELCJmIikuc3ViYXJyYXkoMCxzKHRoaXMsVSwiZiIpLTEpKSksdCh0aGlzLEQscyh0aGlzLEQsImYiKS5zdWJhcnJheShzKHRoaXMsVSwiZiIpKSwiZiIpLHQodGhpcyxVLG51bGwsImYiKTtjb250aW51ZX1jb25zdCBlPW51bGwhPT1zKHRoaXMsVSwiZiIpP2EucHJlY2VkaW5nLTE6YS5wcmVjZWRpbmcscj1OKHModGhpcyxELCJmIikuc3ViYXJyYXkoMCxlKSk7bi5wdXNoKHIpLHQodGhpcyxELHModGhpcyxELCJmIikuc3ViYXJyYXkoYS5pbmRleCksImYiKSx0KHRoaXMsVSxudWxsLCJmIil9cmV0dXJuIG59Zmx1c2goKXtyZXR1cm4gcyh0aGlzLEQsImYiKS5sZW5ndGg/dGhpcy5kZWNvZGUoIlxuIik6W119fWZ1bmN0aW9uIGooZSx0KXtmb3IobGV0IHM9dD8/MDtzPGUubGVuZ3RoO3MrKyl7aWYoMTA9PT1lW3NdKXJldHVybntwcmVjZWRpbmc6cyxpbmRleDpzKzEsY2FycmlhZ2U6ITF9O2lmKDEzPT09ZVtzXSlyZXR1cm57cHJlY2VkaW5nOnMsaW5kZXg6cysxLGNhcnJpYWdlOiEwfX1yZXR1cm4gbnVsbH1mdW5jdGlvbiBGKGUpe2ZvcihsZXQgdD0wO3Q8ZS5sZW5ndGgtMTt0Kyspe2lmKDEwPT09ZVt0XSYmMTA9PT1lW3QrMV0pcmV0dXJuIHQrMjtpZigxMz09PWVbdF0mJjEzPT09ZVt0KzFdKXJldHVybiB0KzI7aWYoMTM9PT1lW3RdJiYxMD09PWVbdCsxXSYmdCszPGUubGVuZ3RoJiYxMz09PWVbdCsyXSYmMTA9PT1lW3QrM10pcmV0dXJuIHQrNH1yZXR1cm4tMX1EPW5ldyBXZWFrTWFwLFU9bmV3IFdlYWtNYXAscS5ORVdMSU5FX0NIQVJTPW5ldyBTZXQoWyJcbiIsIlxyIl0pLHEuTkVXTElORV9SRUdFWFA9L1xyXG58W1xuXHJdL2c7Y29uc3QgVz17b2ZmOjAsZXJyb3I6MjAwLHdhcm46MzAwLGluZm86NDAwLGRlYnVnOjUwMH0sQj0oZSx0LHMpPT57dmFyIHIsbjtpZihlKXJldHVybiByPVcsbj1lLE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyLG4pP2U6dm9pZCBWKHMpLndhcm4oYCR7dH0gd2FzIHNldCB0byAke0pTT04uc3RyaW5naWZ5KGUpfSwgZXhwZWN0ZWQgb25lIG9mICR7SlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXMoVykpfWApfTtmdW5jdGlvbiBKKCl7fWZ1bmN0aW9uIHooZSx0LHMpe3JldHVybiF0fHxXW2VdPldbc10/Sjp0W2VdLmJpbmQodCl9Y29uc3QgSD17ZXJyb3I6Six3YXJuOkosaW5mbzpKLGRlYnVnOkp9O2xldCBLPW5ldyBXZWFrTWFwO2Z1bmN0aW9uIFYoZSl7Y29uc3QgdD1lLmxvZ2dlcixzPWUubG9nTGV2ZWw/PyJvZmYiO2lmKCF0KXJldHVybiBIO2NvbnN0IHI9Sy5nZXQodCk7aWYociYmclswXT09PXMpcmV0dXJuIHJbMV07Y29uc3Qgbj17ZXJyb3I6eigiZXJyb3IiLHQscyksd2Fybjp6KCJ3YXJuIix0LHMpLGluZm86eigiaW5mbyIsdCxzKSxkZWJ1Zzp6KCJkZWJ1ZyIsdCxzKX07cmV0dXJuIEsuc2V0KHQsW3Msbl0pLG59Y29uc3QgWD1lPT4oZS5vcHRpb25zJiYoZS5vcHRpb25zPXsuLi5lLm9wdGlvbnN9LGRlbGV0ZSBlLm9wdGlvbnMuaGVhZGVycyksZS5oZWFkZXJzJiYoZS5oZWFkZXJzPU9iamVjdC5mcm9tRW50cmllcygoZS5oZWFkZXJzIGluc3RhbmNlb2YgSGVhZGVycz9bLi4uZS5oZWFkZXJzXTpPYmplY3QuZW50cmllcyhlLmhlYWRlcnMpKS5tYXAoKFtlLHRdKT0+W2UsIngtYXBpLWtleSI9PT1lLnRvTG93ZXJDYXNlKCl8fCJhdXRob3JpemF0aW9uIj09PWUudG9Mb3dlckNhc2UoKXx8ImNvb2tpZSI9PT1lLnRvTG93ZXJDYXNlKCl8fCJzZXQtY29va2llIj09PWUudG9Mb3dlckNhc2UoKT8iKioqIjp0XSkpKSwicmV0cnlPZlJlcXVlc3RMb2dJRCJpbiBlJiYoZS5yZXRyeU9mUmVxdWVzdExvZ0lEJiYoZS5yZXRyeU9mPWUucmV0cnlPZlJlcXVlc3RMb2dJRCksZGVsZXRlIGUucmV0cnlPZlJlcXVlc3RMb2dJRCksZSk7dmFyIEcsWSxRO2NsYXNzIFp7Y29uc3RydWN0b3IoZSxzLHIpe3RoaXMuaXRlcmF0b3I9ZSxHLnNldCh0aGlzLHZvaWQgMCksdGhpcy5jb250cm9sbGVyPXMsdCh0aGlzLEcsciwiZiIpfXN0YXRpYyBmcm9tU1NFUmVzcG9uc2UoZSx0LHMpe2xldCByPSExO2NvbnN0IGE9cz9WKHMpOmNvbnNvbGU7cmV0dXJuIG5ldyBaKGFzeW5jIGZ1bmN0aW9uKigpe2lmKHIpdGhyb3cgbmV3IG8oIkNhbm5vdCBpdGVyYXRlIG92ZXIgYSBjb25zdW1lZCBzdHJlYW0sIHVzZSBgLnRlZSgpYCB0byBzcGxpdCB0aGUgc3RyZWFtLiIpO3I9ITA7bGV0IHM9ITE7dHJ5e2ZvciBhd2FpdChjb25zdCBzIG9mIGFzeW5jIGZ1bmN0aW9uKihlLHQpe2lmKCFlLmJvZHkpe2lmKHQuYWJvcnQoKSx2b2lkIDAhPT1nbG9iYWxUaGlzLm5hdmlnYXRvciYmIlJlYWN0TmF0aXZlIj09PWdsb2JhbFRoaXMubmF2aWdhdG9yLnByb2R1Y3QpdGhyb3cgbmV3IG8oIlRoZSBkZWZhdWx0IHJlYWN0LW5hdGl2ZSBmZXRjaCBpbXBsZW1lbnRhdGlvbiBkb2VzIG5vdCBzdXBwb3J0IHN0cmVhbWluZy4gUGxlYXNlIHVzZSBleHBvL2ZldGNoOiBodHRwczovL2RvY3MuZXhwby5kZXYvdmVyc2lvbnMvbGF0ZXN0L3Nkay9leHBvLyNleHBvZmV0Y2gtYXBpIik7dGhyb3cgbmV3IG8oIkF0dGVtcHRlZCB0byBpdGVyYXRlIG92ZXIgYSByZXNwb25zZSB3aXRoIG5vIGJvZHkiKX1jb25zdCBzPW5ldyBlZSxyPW5ldyBxLG49QyhlLmJvZHkpO2ZvciBhd2FpdChjb25zdCBlIG9mIGFzeW5jIGZ1bmN0aW9uKihlKXtsZXQgdD1uZXcgVWludDhBcnJheTtmb3IgYXdhaXQoY29uc3QgcyBvZiBlKXtpZihudWxsPT1zKWNvbnRpbnVlO2NvbnN0IGU9cyBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP25ldyBVaW50OEFycmF5KHMpOiJzdHJpbmciPT10eXBlb2Ygcz9MKHMpOnM7bGV0IHIsbj1uZXcgVWludDhBcnJheSh0Lmxlbmd0aCtlLmxlbmd0aCk7Zm9yKG4uc2V0KHQpLG4uc2V0KGUsdC5sZW5ndGgpLHQ9bjstMSE9PShyPUYodCkpOyl5aWVsZCB0LnNsaWNlKDAsciksdD10LnNsaWNlKHIpfXQubGVuZ3RoPjAmJih5aWVsZCB0KX0obikpZm9yKGNvbnN0IHQgb2Ygci5kZWNvZGUoZSkpe2NvbnN0IGU9cy5kZWNvZGUodCk7ZSYmKHlpZWxkIGUpfWZvcihjb25zdCBlIG9mIHIuZmx1c2goKSl7Y29uc3QgdD1zLmRlY29kZShlKTt0JiYoeWllbGQgdCl9fShlLHQpKXtpZigiY29tcGxldGlvbiI9PT1zLmV2ZW50KXRyeXt5aWVsZCBKU09OLnBhcnNlKHMuZGF0YSl9Y2F0Y2goZSl7dGhyb3cgYS5lcnJvcigiQ291bGQgbm90IHBhcnNlIG1lc3NhZ2UgaW50byBKU09OOiIscy5kYXRhKSxhLmVycm9yKCJGcm9tIGNodW5rOiIscy5yYXcpLGV9aWYoIm1lc3NhZ2Vfc3RhcnQiPT09cy5ldmVudHx8Im1lc3NhZ2VfZGVsdGEiPT09cy5ldmVudHx8Im1lc3NhZ2Vfc3RvcCI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19zdGFydCI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19kZWx0YSI9PT1zLmV2ZW50fHwiY29udGVudF9ibG9ja19zdG9wIj09PXMuZXZlbnQpdHJ5e3lpZWxkIEpTT04ucGFyc2Uocy5kYXRhKX1jYXRjaChlKXt0aHJvdyBhLmVycm9yKCJDb3VsZCBub3QgcGFyc2UgbWVzc2FnZSBpbnRvIEpTT046IixzLmRhdGEpLGEuZXJyb3IoIkZyb20gY2h1bms6IixzLnJhdyksZX1pZigicGluZyIhPT1zLmV2ZW50JiYiZXJyb3IiPT09cy5ldmVudCl0aHJvdyBuZXcgaSh2b2lkIDAsUyhzLmRhdGEpPz9zLmRhdGEsdm9pZCAwLGUuaGVhZGVycyl9cz0hMH1jYXRjaChlKXtpZihuKGUpKXJldHVybjt0aHJvdyBlfWZpbmFsbHl7c3x8dC5hYm9ydCgpfX0sdCxzKX1zdGF0aWMgZnJvbVJlYWRhYmxlU3RyZWFtKGUsdCxzKXtsZXQgcj0hMTtyZXR1cm4gbmV3IFooYXN5bmMgZnVuY3Rpb24qKCl7aWYocil0aHJvdyBuZXcgbygiQ2Fubm90IGl0ZXJhdGUgb3ZlciBhIGNvbnN1bWVkIHN0cmVhbSwgdXNlIGAudGVlKClgIHRvIHNwbGl0IHRoZSBzdHJlYW0uIik7cj0hMDtsZXQgcz0hMTt0cnl7Zm9yIGF3YWl0KGNvbnN0IHQgb2YgYXN5bmMgZnVuY3Rpb24qKCl7Y29uc3QgdD1uZXcgcSxzPUMoZSk7Zm9yIGF3YWl0KGNvbnN0IGUgb2Ygcylmb3IoY29uc3QgcyBvZiB0LmRlY29kZShlKSl5aWVsZCBzO2Zvcihjb25zdCBlIG9mIHQuZmx1c2goKSl5aWVsZCBlfSgpKXN8fHQmJih5aWVsZCBKU09OLnBhcnNlKHQpKTtzPSEwfWNhdGNoKGUpe2lmKG4oZSkpcmV0dXJuO3Rocm93IGV9ZmluYWxseXtzfHx0LmFib3J0KCl9fSx0LHMpfVsoRz1uZXcgV2Vha01hcCxTeW1ib2wuYXN5bmNJdGVyYXRvcildKCl7cmV0dXJuIHRoaXMuaXRlcmF0b3IoKX10ZWUoKXtjb25zdCBlPVtdLHQ9W10scj10aGlzLml0ZXJhdG9yKCksbj1zPT4oe25leHQ6KCk9PntpZigwPT09cy5sZW5ndGgpe2NvbnN0IHM9ci5uZXh0KCk7ZS5wdXNoKHMpLHQucHVzaChzKX1yZXR1cm4gcy5zaGlmdCgpfX0pO3JldHVybltuZXcgWigoKT0+bihlKSx0aGlzLmNvbnRyb2xsZXIscyh0aGlzLEcsImYiKSksbmV3IFooKCk9Pm4odCksdGhpcy5jb250cm9sbGVyLHModGhpcyxHLCJmIikpXX10b1JlYWRhYmxlU3RyZWFtKCl7Y29uc3QgZT10aGlzO2xldCB0O3JldHVybiBUKHthc3luYyBzdGFydCgpe3Q9ZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKX0sYXN5bmMgcHVsbChlKXt0cnl7Y29uc3R7dmFsdWU6cyxkb25lOnJ9PWF3YWl0IHQubmV4dCgpO2lmKHIpcmV0dXJuIGUuY2xvc2UoKTtjb25zdCBuPUwoSlNPTi5zdHJpbmdpZnkocykrIlxuIik7ZS5lbnF1ZXVlKG4pfWNhdGNoKHQpe2UuZXJyb3IodCl9fSxhc3luYyBjYW5jZWwoKXthd2FpdCh0LnJldHVybj8uKCkpfX0pfX1jbGFzcyBlZXtjb25zdHJ1Y3Rvcigpe3RoaXMuZXZlbnQ9bnVsbCx0aGlzLmRhdGE9W10sdGhpcy5jaHVua3M9W119ZGVjb2RlKGUpe2lmKGUuZW5kc1dpdGgoIlxyIikmJihlPWUuc3Vic3RyaW5nKDAsZS5sZW5ndGgtMSkpLCFlKXtpZighdGhpcy5ldmVudCYmIXRoaXMuZGF0YS5sZW5ndGgpcmV0dXJuIG51bGw7Y29uc3QgZT17ZXZlbnQ6dGhpcy5ldmVudCxkYXRhOnRoaXMuZGF0YS5qb2luKCJcbiIpLHJhdzp0aGlzLmNodW5rc307cmV0dXJuIHRoaXMuZXZlbnQ9bnVsbCx0aGlzLmRhdGE9W10sdGhpcy5jaHVua3M9W10sZX1pZih0aGlzLmNodW5rcy5wdXNoKGUpLGUuc3RhcnRzV2l0aCgiOiIpKXJldHVybiBudWxsO2xldFt0LHMscl09ZnVuY3Rpb24oZSl7Y29uc3QgdD1lLmluZGV4T2YoIjoiKTtyZXR1cm4tMSE9PXQ/W2Uuc3Vic3RyaW5nKDAsdCksIjoiLGUuc3Vic3RyaW5nKHQrMSldOltlLCIiLCIiXX0oZSk7cmV0dXJuIHIuc3RhcnRzV2l0aCgiICIpJiYocj1yLnN1YnN0cmluZygxKSksImV2ZW50Ij09PXQ/dGhpcy5ldmVudD1yOiJkYXRhIj09PXQmJnRoaXMuZGF0YS5wdXNoKHIpLG51bGx9fWFzeW5jIGZ1bmN0aW9uIHRlKGUsdCl7Y29uc3R7cmVzcG9uc2U6cyxyZXF1ZXN0TG9nSUQ6cixyZXRyeU9mUmVxdWVzdExvZ0lEOm4sc3RhcnRUaW1lOmF9PXQsbz1hd2FpdChhc3luYygpPT57aWYodC5vcHRpb25zLnN0cmVhbSlyZXR1cm4gVihlKS5kZWJ1ZygicmVzcG9uc2UiLHMuc3RhdHVzLHMudXJsLHMuaGVhZGVycyxzLmJvZHkpLHQub3B0aW9ucy5fX3N0cmVhbUNsYXNzP3Qub3B0aW9ucy5fX3N0cmVhbUNsYXNzLmZyb21TU0VSZXNwb25zZShzLHQuY29udHJvbGxlcik6Wi5mcm9tU1NFUmVzcG9uc2Uocyx0LmNvbnRyb2xsZXIpO2lmKDIwND09PXMuc3RhdHVzKXJldHVybiBudWxsO2lmKHQub3B0aW9ucy5fX2JpbmFyeVJlc3BvbnNlKXJldHVybiBzO2NvbnN0IHI9cy5oZWFkZXJzLmdldCgiY29udGVudC10eXBlIiksbj1yPy5zcGxpdCgiOyIpWzBdPy50cmltKCk7cmV0dXJuIG4/LmluY2x1ZGVzKCJhcHBsaWNhdGlvbi9qc29uIil8fG4/LmVuZHNXaXRoKCIranNvbiIpP3NlKGF3YWl0IHMuanNvbigpLHMpOmF3YWl0IHMudGV4dCgpfSkoKTtyZXR1cm4gVihlKS5kZWJ1ZyhgWyR7cn1dIHJlc3BvbnNlIHBhcnNlZGAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpuLHVybDpzLnVybCxzdGF0dXM6cy5zdGF0dXMsYm9keTpvLGR1cmF0aW9uTXM6RGF0ZS5ub3coKS1hfSkpLG99ZnVuY3Rpb24gc2UoZSx0KXtyZXR1cm4hZXx8Im9iamVjdCIhPXR5cGVvZiBlfHxBcnJheS5pc0FycmF5KGUpP2U6T2JqZWN0LmRlZmluZVByb3BlcnR5KGUsIl9yZXF1ZXN0X2lkIix7dmFsdWU6dC5oZWFkZXJzLmdldCgicmVxdWVzdC1pZCIpLGVudW1lcmFibGU6ITF9KX1jbGFzcyByZSBleHRlbmRzIFByb21pc2V7Y29uc3RydWN0b3IoZSxzLHI9dGUpe3N1cGVyKGU9PntlKG51bGwpfSksdGhpcy5yZXNwb25zZVByb21pc2U9cyx0aGlzLnBhcnNlUmVzcG9uc2U9cixZLnNldCh0aGlzLHZvaWQgMCksdCh0aGlzLFksZSwiZiIpfV90aGVuVW53cmFwKGUpe3JldHVybiBuZXcgcmUocyh0aGlzLFksImYiKSx0aGlzLnJlc3BvbnNlUHJvbWlzZSxhc3luYyh0LHMpPT5zZShlKGF3YWl0IHRoaXMucGFyc2VSZXNwb25zZSh0LHMpLHMpLHMucmVzcG9uc2UpKX1hc1Jlc3BvbnNlKCl7cmV0dXJuIHRoaXMucmVzcG9uc2VQcm9taXNlLnRoZW4oZT0+ZS5yZXNwb25zZSl9YXN5bmMgd2l0aFJlc3BvbnNlKCl7Y29uc3RbZSx0XT1hd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wYXJzZSgpLHRoaXMuYXNSZXNwb25zZSgpXSk7cmV0dXJue2RhdGE6ZSxyZXNwb25zZTp0LHJlcXVlc3RfaWQ6dC5oZWFkZXJzLmdldCgicmVxdWVzdC1pZCIpfX1wYXJzZSgpe3JldHVybiB0aGlzLnBhcnNlZFByb21pc2V8fCh0aGlzLnBhcnNlZFByb21pc2U9dGhpcy5yZXNwb25zZVByb21pc2UudGhlbihlPT50aGlzLnBhcnNlUmVzcG9uc2Uocyh0aGlzLFksImYiKSxlKSkpLHRoaXMucGFyc2VkUHJvbWlzZX10aGVuKGUsdCl7cmV0dXJuIHRoaXMucGFyc2UoKS50aGVuKGUsdCl9Y2F0Y2goZSl7cmV0dXJuIHRoaXMucGFyc2UoKS5jYXRjaChlKX1maW5hbGx5KGUpe3JldHVybiB0aGlzLnBhcnNlKCkuZmluYWxseShlKX19WT1uZXcgV2Vha01hcDtjbGFzcyBuZXtjb25zdHJ1Y3RvcihlLHMscixuKXtRLnNldCh0aGlzLHZvaWQgMCksdCh0aGlzLFEsZSwiZiIpLHRoaXMub3B0aW9ucz1uLHRoaXMucmVzcG9uc2U9cyx0aGlzLmJvZHk9cn1oYXNOZXh0UGFnZSgpe3JldHVybiEhdGhpcy5nZXRQYWdpbmF0ZWRJdGVtcygpLmxlbmd0aCYmbnVsbCE9dGhpcy5uZXh0UGFnZVJlcXVlc3RPcHRpb25zKCl9YXN5bmMgZ2V0TmV4dFBhZ2UoKXtjb25zdCBlPXRoaXMubmV4dFBhZ2VSZXF1ZXN0T3B0aW9ucygpO2lmKCFlKXRocm93IG5ldyBvKCJObyBuZXh0IHBhZ2UgZXhwZWN0ZWQ7IHBsZWFzZSBjaGVjayBgLmhhc05leHRQYWdlKClgIGJlZm9yZSBjYWxsaW5nIGAuZ2V0TmV4dFBhZ2UoKWAuIik7cmV0dXJuIGF3YWl0IHModGhpcyxRLCJmIikucmVxdWVzdEFQSUxpc3QodGhpcy5jb25zdHJ1Y3RvcixlKX1hc3luYyppdGVyUGFnZXMoKXtsZXQgZT10aGlzO2Zvcih5aWVsZCBlO2UuaGFzTmV4dFBhZ2UoKTspZT1hd2FpdCBlLmdldE5leHRQYWdlKCkseWllbGQgZX1hc3luYypbKFE9bmV3IFdlYWtNYXAsU3ltYm9sLmFzeW5jSXRlcmF0b3IpXSgpe2ZvciBhd2FpdChjb25zdCBlIG9mIHRoaXMuaXRlclBhZ2VzKCkpZm9yKGNvbnN0IHQgb2YgZS5nZXRQYWdpbmF0ZWRJdGVtcygpKXlpZWxkIHR9fWNsYXNzIGFlIGV4dGVuZHMgcmV7Y29uc3RydWN0b3IoZSx0LHMpe3N1cGVyKGUsdCxhc3luYyhlLHQpPT5uZXcgcyhlLHQucmVzcG9uc2UsYXdhaXQgdGUoZSx0KSx0Lm9wdGlvbnMpKX1hc3luYypbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7Y29uc3QgZT1hd2FpdCh0aGlzKTtmb3IgYXdhaXQoY29uc3QgdCBvZiBlKXlpZWxkIHR9fWNsYXNzIG9lIGV4dGVuZHMgbmV7Y29uc3RydWN0b3IoZSx0LHMscil7c3VwZXIoZSx0LHMsciksdGhpcy5kYXRhPXMuZGF0YXx8W10sdGhpcy5oYXNfbW9yZT1zLmhhc19tb3JlfHwhMSx0aGlzLmZpcnN0X2lkPXMuZmlyc3RfaWR8fG51bGwsdGhpcy5sYXN0X2lkPXMubGFzdF9pZHx8bnVsbH1nZXRQYWdpbmF0ZWRJdGVtcygpe3JldHVybiB0aGlzLmRhdGE/P1tdfWhhc05leHRQYWdlKCl7cmV0dXJuITEhPT10aGlzLmhhc19tb3JlJiZzdXBlci5oYXNOZXh0UGFnZSgpfW5leHRQYWdlUmVxdWVzdE9wdGlvbnMoKXtpZih0aGlzLm9wdGlvbnMucXVlcnk/LmJlZm9yZV9pZCl7Y29uc3QgZT10aGlzLmZpcnN0X2lkO3JldHVybiBlP3suLi50aGlzLm9wdGlvbnMscXVlcnk6ey4uLmsodGhpcy5vcHRpb25zLnF1ZXJ5KSxiZWZvcmVfaWQ6ZX19Om51bGx9Y29uc3QgZT10aGlzLmxhc3RfaWQ7cmV0dXJuIGU/ey4uLnRoaXMub3B0aW9ucyxxdWVyeTp7Li4uayh0aGlzLm9wdGlvbnMucXVlcnkpLGFmdGVyX2lkOmV9fTpudWxsfX1jbGFzcyBpZSBleHRlbmRzIG5le2NvbnN0cnVjdG9yKGUsdCxzLHIpe3N1cGVyKGUsdCxzLHIpLHRoaXMuZGF0YT1zLmRhdGF8fFtdLHRoaXMuaGFzX21vcmU9cy5oYXNfbW9yZXx8ITEsdGhpcy5uZXh0X3BhZ2U9cy5uZXh0X3BhZ2V8fG51bGx9Z2V0UGFnaW5hdGVkSXRlbXMoKXtyZXR1cm4gdGhpcy5kYXRhPz9bXX1oYXNOZXh0UGFnZSgpe3JldHVybiExIT09dGhpcy5oYXNfbW9yZSYmc3VwZXIuaGFzTmV4dFBhZ2UoKX1uZXh0UGFnZVJlcXVlc3RPcHRpb25zKCl7Y29uc3QgZT10aGlzLm5leHRfcGFnZTtyZXR1cm4gZT97Li4udGhpcy5vcHRpb25zLHF1ZXJ5OnsuLi5rKHRoaXMub3B0aW9ucy5xdWVyeSkscGFnZTplfX06bnVsbH19Y29uc3QgY2U9KCk9PntpZigidW5kZWZpbmVkIj09dHlwZW9mIEZpbGUpe2NvbnN0e3Byb2Nlc3M6ZX09Z2xvYmFsVGhpcyx0PSJzdHJpbmciPT10eXBlb2YgZT8udmVyc2lvbnM/Lm5vZGUmJnBhcnNlSW50KGUudmVyc2lvbnMubm9kZS5zcGxpdCgiLiIpKTwyMDt0aHJvdyBuZXcgRXJyb3IoImBGaWxlYCBpcyBub3QgZGVmaW5lZCBhcyBhIGdsb2JhbCwgd2hpY2ggaXMgcmVxdWlyZWQgZm9yIGZpbGUgdXBsb2Fkcy4iKyh0PyIgVXBkYXRlIHRvIE5vZGUgMjAgTFRTIG9yIG5ld2VyLCBvciBzZXQgYGdsb2JhbFRoaXMuRmlsZWAgdG8gYGltcG9ydCgnbm9kZTpidWZmZXInKS5GaWxlYC4iOiIiKSl9fTtmdW5jdGlvbiBsZShlLHQscyl7cmV0dXJuIGNlKCksbmV3IEZpbGUoZSx0Pz8idW5rbm93bl9maWxlIixzKX1mdW5jdGlvbiBkZShlKXtyZXR1cm4oIm9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZSYmKCJuYW1lImluIGUmJmUubmFtZSYmU3RyaW5nKGUubmFtZSl8fCJ1cmwiaW4gZSYmZS51cmwmJlN0cmluZyhlLnVybCl8fCJmaWxlbmFtZSJpbiBlJiZlLmZpbGVuYW1lJiZTdHJpbmcoZS5maWxlbmFtZSl8fCJwYXRoImluIGUmJmUucGF0aCYmU3RyaW5nKGUucGF0aCkpfHwiIikuc3BsaXQoL1tcXC9dLykucG9wKCl8fHZvaWQgMH1jb25zdCBoZT1lPT5udWxsIT1lJiYib2JqZWN0Ij09dHlwZW9mIGUmJiJmdW5jdGlvbiI9PXR5cGVvZiBlW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSx1ZT1hc3luYyhlLHQpPT4oey4uLmUsYm9keTphd2FpdCBmZShlLmJvZHksdCl9KSxwZT1uZXcgV2Vha01hcCxmZT1hc3luYyhlLHQpPT57aWYoIWF3YWl0IGZ1bmN0aW9uKGUpe2NvbnN0IHQ9ImZ1bmN0aW9uIj09dHlwZW9mIGU/ZTplLmZldGNoLHM9cGUuZ2V0KHQpO2lmKHMpcmV0dXJuIHM7Y29uc3Qgcj0oYXN5bmMoKT0+e3RyeXtjb25zdCBlPSJSZXNwb25zZSJpbiB0P3QuUmVzcG9uc2U6KGF3YWl0IHQoImRhdGE6LCIpKS5jb25zdHJ1Y3RvcixzPW5ldyBGb3JtRGF0YTtyZXR1cm4gcy50b1N0cmluZygpIT09YXdhaXQgbmV3IGUocykudGV4dCgpfWNhdGNoe3JldHVybiEwfX0pKCk7cmV0dXJuIHBlLnNldCh0LHIpLHJ9KHQpKXRocm93IG5ldyBUeXBlRXJyb3IoIlRoZSBwcm92aWRlZCBmZXRjaCBmdW5jdGlvbiBkb2VzIG5vdCBzdXBwb3J0IGZpbGUgdXBsb2FkcyB3aXRoIHRoZSBjdXJyZW50IGdsb2JhbCBGb3JtRGF0YSBjbGFzcy4iKTtjb25zdCBzPW5ldyBGb3JtRGF0YTtyZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoT2JqZWN0LmVudHJpZXMoZXx8e30pLm1hcCgoW2UsdF0pPT5tZShzLGUsdCkpKSxzfSxtZT1hc3luYyhlLHQscyk9PntpZih2b2lkIDAhPT1zKXtpZihudWxsPT1zKXRocm93IG5ldyBUeXBlRXJyb3IoYFJlY2VpdmVkIG51bGwgZm9yICIke3R9IjsgdG8gcGFzcyBudWxsIGluIEZvcm1EYXRhLCB5b3UgbXVzdCB1c2UgdGhlIHN0cmluZyAnbnVsbCdgKTtpZigic3RyaW5nIj09dHlwZW9mIHN8fCJudW1iZXIiPT10eXBlb2Ygc3x8ImJvb2xlYW4iPT10eXBlb2YgcyllLmFwcGVuZCh0LFN0cmluZyhzKSk7ZWxzZSBpZihzIGluc3RhbmNlb2YgUmVzcG9uc2Upe2xldCByPXt9O2NvbnN0IG49cy5oZWFkZXJzLmdldCgiQ29udGVudC1UeXBlIik7biYmKHI9e3R5cGU6bn0pLGUuYXBwZW5kKHQsbGUoW2F3YWl0IHMuYmxvYigpXSxkZShzKSxyKSl9ZWxzZSBpZihoZShzKSllLmFwcGVuZCh0LGxlKFthd2FpdCBuZXcgUmVzcG9uc2UoQShzKSkuYmxvYigpXSxkZShzKSkpO2Vsc2UgaWYoKGU9PmUgaW5zdGFuY2VvZiBCbG9iJiYibmFtZSJpbiBlKShzKSllLmFwcGVuZCh0LGxlKFtzXSxkZShzKSx7dHlwZTpzLnR5cGV9KSk7ZWxzZSBpZihBcnJheS5pc0FycmF5KHMpKWF3YWl0IFByb21pc2UuYWxsKHMubWFwKHM9Pm1lKGUsdCsiW10iLHMpKSk7ZWxzZXtpZigib2JqZWN0IiE9dHlwZW9mIHMpdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCB2YWx1ZSBnaXZlbiB0byBmb3JtLCBleHBlY3RlZCBhIHN0cmluZywgbnVtYmVyLCBib29sZWFuLCBvYmplY3QsIEFycmF5LCBGaWxlIG9yIEJsb2IgYnV0IGdvdCAke3N9IGluc3RlYWRgKTthd2FpdCBQcm9taXNlLmFsbChPYmplY3QuZW50cmllcyhzKS5tYXAoKFtzLHJdKT0+bWUoZSxgJHt0fVske3N9XWAscikpKX19fSxnZT1lPT5udWxsIT1lJiYib2JqZWN0Ij09dHlwZW9mIGUmJiJudW1iZXIiPT10eXBlb2YgZS5zaXplJiYic3RyaW5nIj09dHlwZW9mIGUudHlwZSYmImZ1bmN0aW9uIj09dHlwZW9mIGUudGV4dCYmImZ1bmN0aW9uIj09dHlwZW9mIGUuc2xpY2UmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLmFycmF5QnVmZmVyO2FzeW5jIGZ1bmN0aW9uIHdlKGUpe2xldCB0PVtdO2lmKCJzdHJpbmciPT10eXBlb2YgZXx8QXJyYXlCdWZmZXIuaXNWaWV3KGUpfHxlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpdC5wdXNoKGUpO2Vsc2UgaWYoZ2UoZSkpdC5wdXNoKGUgaW5zdGFuY2VvZiBCbG9iP2U6YXdhaXQgZS5hcnJheUJ1ZmZlcigpKTtlbHNle2lmKCFoZShlKSl7Y29uc3QgdD1lPy5jb25zdHJ1Y3Rvcj8ubmFtZTt0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZGF0YSB0eXBlOiAke3R5cGVvZiBlfSR7dD9gOyBjb25zdHJ1Y3RvcjogJHt0fWA6IiJ9JHtmdW5jdGlvbihlKXtpZigib2JqZWN0IiE9dHlwZW9mIGV8fG51bGw9PT1lKXJldHVybiIiO3JldHVybmA7IHByb3BzOiBbJHtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhlKS5tYXAoZT0+YCIke2V9ImApLmpvaW4oIiwgIil9XWB9KGUpfWApfWZvciBhd2FpdChjb25zdCBzIG9mIGUpdC5wdXNoKC4uLmF3YWl0IHdlKHMpKX1yZXR1cm4gdH1jbGFzcyB5ZXtjb25zdHJ1Y3RvcihlKXt0aGlzLl9jbGllbnQ9ZX19Y29uc3QgYmU9U3ltYm9sLmZvcigiYnJhbmQucHJpdmF0ZU51bGxhYmxlSGVhZGVycyIpO2Z1bmN0aW9uKnZlKGUpe2lmKCFlKXJldHVybjtpZihiZSBpbiBlKXtjb25zdHt2YWx1ZXM6dCxudWxsczpzfT1lO3lpZWxkKnQuZW50cmllcygpO2Zvcihjb25zdCBlIG9mIHMpeWllbGRbZSxudWxsXTtyZXR1cm59bGV0IHQscz0hMTtlIGluc3RhbmNlb2YgSGVhZGVycz90PWUuZW50cmllcygpOl8oZSk/dD1lOihzPSEwLHQ9T2JqZWN0LmVudHJpZXMoZT8/e30pKTtmb3IobGV0IGUgb2YgdCl7Y29uc3QgdD1lWzBdO2lmKCJzdHJpbmciIT10eXBlb2YgdCl0aHJvdyBuZXcgVHlwZUVycm9yKCJleHBlY3RlZCBoZWFkZXIgbmFtZSB0byBiZSBhIHN0cmluZyIpO2NvbnN0IHI9XyhlWzFdKT9lWzFdOltlWzFdXTtsZXQgbj0hMTtmb3IoY29uc3QgZSBvZiByKXZvaWQgMCE9PWUmJihzJiYhbiYmKG49ITAseWllbGRbdCxudWxsXSkseWllbGRbdCxlXSl9fWNvbnN0IF9lPWU9Pntjb25zdCB0PW5ldyBIZWFkZXJzLHM9bmV3IFNldDtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPW5ldyBTZXQ7Zm9yKGNvbnN0W24sYV1vZiB2ZShyKSl7Y29uc3Qgcj1uLnRvTG93ZXJDYXNlKCk7ZS5oYXMocil8fCh0LmRlbGV0ZShuKSxlLmFkZChyKSksbnVsbD09PWE/KHQuZGVsZXRlKG4pLHMuYWRkKHIpKToodC5hcHBlbmQobixhKSxzLmRlbGV0ZShyKSl9fXJldHVybntbYmVdOiEwLHZhbHVlczp0LG51bGxzOnN9fTtmdW5jdGlvbiBrZShlKXtyZXR1cm4gZS5yZXBsYWNlKC9bXkEtWmEtejAtOVwtLl9+ISQmJygpKissOz06QF0rL2csZW5jb2RlVVJJQ29tcG9uZW50KX1jb25zdCBTZT1PYmplY3QuZnJlZXplKE9iamVjdC5jcmVhdGUobnVsbCkpLE1lPShlPWtlKT0+ZnVuY3Rpb24odCwuLi5zKXtpZigxPT09dC5sZW5ndGgpcmV0dXJuIHRbMF07bGV0IHI9ITE7Y29uc3Qgbj1bXSxhPXQucmVkdWNlKCh0LGEsbyk9PnsvWz8jXS8udGVzdChhKSYmKHI9ITApO2NvbnN0IGk9c1tvXTtsZXQgYz0ocj9lbmNvZGVVUklDb21wb25lbnQ6ZSkoIiIraSk7cmV0dXJuIG8hPT1zLmxlbmd0aCYmKG51bGw9PWl8fCJvYmplY3QiPT10eXBlb2YgaSYmaS50b1N0cmluZz09PU9iamVjdC5nZXRQcm90b3R5cGVPZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoaS5oYXNPd25Qcm9wZXJ0eT8/U2UpPz9TZSk/LnRvU3RyaW5nKSYmKGM9aSsiIixuLnB1c2goe3N0YXJ0OnQubGVuZ3RoK2EubGVuZ3RoLGxlbmd0aDpjLmxlbmd0aCxlcnJvcjpgVmFsdWUgb2YgdHlwZSAke09iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpKS5zbGljZSg4LC0xKX0gaXMgbm90IGEgdmFsaWQgcGF0aCBwYXJhbWV0ZXJgfSkpLHQrYSsobz09PXMubGVuZ3RoPyIiOmMpfSwiIiksaT1hLnNwbGl0KC9bPyNdLywxKVswXSxjPS8oPzw9XnxcLykoPzpcLnwlMmUpezEsMn0oPz1cL3wkKS9naTtsZXQgbDtmb3IoO251bGwhPT0obD1jLmV4ZWMoaSkpOyluLnB1c2goe3N0YXJ0OmwuaW5kZXgsbGVuZ3RoOmxbMF0ubGVuZ3RoLGVycm9yOmBWYWx1ZSAiJHtsWzBdfSIgY2FuJ3QgYmUgc2FmZWx5IHBhc3NlZCBhcyBhIHBhdGggcGFyYW1ldGVyYH0pO2lmKG4uc29ydCgoZSx0KT0+ZS5zdGFydC10LnN0YXJ0KSxuLmxlbmd0aD4wKXtsZXQgZT0wO2NvbnN0IHQ9bi5yZWR1Y2UoKHQscyk9Pntjb25zdCByPSIgIi5yZXBlYXQocy5zdGFydC1lKSxuPSJeIi5yZXBlYXQocy5sZW5ndGgpO3JldHVybiBlPXMuc3RhcnQrcy5sZW5ndGgsdCtyK259LCIiKTt0aHJvdyBuZXcgbyhgUGF0aCBwYXJhbWV0ZXJzIHJlc3VsdCBpbiBwYXRoIHdpdGggaW52YWxpZCBzZWdtZW50czpcbiR7bi5tYXAoZT0+ZS5lcnJvcikuam9pbigiXG4iKX1cbiR7YX1cbiR7dH1gKX1yZXR1cm4gYX0sUGU9TWUoa2UpO2NsYXNzIEVlIGV4dGVuZHMgeWV7bGlzdChlPXt9LHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZT8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvZmlsZXMiLG9lLHtxdWVyeTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0pfWRlbGV0ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5kZWxldGUoUGVgL3YxL2ZpbGVzLyR7ZX1gLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwiZmlsZXMtYXBpLTIwMjUtMDQtMTQiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1kb3dubG9hZChlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL2ZpbGVzLyR7ZX0vY29udGVudGAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCksQWNjZXB0OiJhcHBsaWNhdGlvbi9iaW5hcnkifSxzPy5oZWFkZXJzXSksX19iaW5hcnlSZXNwb25zZTohMH0pfXJldHJpZXZlTWV0YWRhdGEoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9maWxlcy8ke2V9YCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucj8/W10sImZpbGVzLWFwaS0yMDI1LTA0LTE0Il0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9dXBsb2FkKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL2ZpbGVzIix1ZSh7Ym9keTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJmaWxlcy1hcGktMjAyNS0wNC0xNCJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0sdGhpcy5fY2xpZW50KSl9fWNsYXNzIFJlIGV4dGVuZHMgeWV7cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9tb2RlbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3suLi5udWxsIT1yPy50b1N0cmluZygpP3siYW50aHJvcGljLWJldGEiOnI/LnRvU3RyaW5nKCl9OnZvaWQgMH0scz8uaGVhZGVyc10pfSl9bGlzdChlPXt9LHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZT8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvbW9kZWxzP2JldGE9dHJ1ZSIsb2Use3F1ZXJ5OnIsLi4udCxoZWFkZXJzOl9lKFt7Li4ubnVsbCE9cz8udG9TdHJpbmcoKT97ImFudGhyb3BpYy1iZXRhIjpzPy50b1N0cmluZygpfTp2b2lkIDB9LHQ/LmhlYWRlcnNdKX0pfX1jb25zdCB4ZT17ImNsYXVkZS1vcHVzLTQtMjAyNTA1MTQiOjgxOTIsImNsYXVkZS1vcHVzLTQtMCI6ODE5MiwiY2xhdWRlLTQtb3B1cy0yMDI1MDUxNCI6ODE5MiwiYW50aHJvcGljLmNsYXVkZS1vcHVzLTQtMjAyNTA1MTQtdjE6MCI6ODE5MiwiY2xhdWRlLW9wdXMtNEAyMDI1MDUxNCI6ODE5MiwiY2xhdWRlLW9wdXMtNC0xLTIwMjUwODA1Ijo4MTkyLCJhbnRocm9waWMuY2xhdWRlLW9wdXMtNC0xLTIwMjUwODA1LXYxOjAiOjgxOTIsImNsYXVkZS1vcHVzLTQtMUAyMDI1MDgwNSI6ODE5Mn07ZnVuY3Rpb24gVGUoZSx0KXtyZXR1cm4gdCYmInBhcnNlImluKHQub3V0cHV0X2Zvcm1hdD8/e30pP0FlKGUsdCk6ey4uLmUsY29udGVudDplLmNvbnRlbnQubWFwKGU9PiJ0ZXh0Ij09PWUudHlwZT97Li4uZSxwYXJzZWQ6bnVsbH06ZSkscGFyc2VkX291dHB1dDpudWxsfX1mdW5jdGlvbiBBZShlLHQpe2xldCBzPW51bGw7Y29uc3Qgcj1lLmNvbnRlbnQubWFwKGU9PntpZigidGV4dCI9PT1lLnR5cGUpe2NvbnN0IHI9ZnVuY3Rpb24oZSx0KXtpZigianNvbl9zY2hlbWEiIT09ZS5vdXRwdXRfZm9ybWF0Py50eXBlKXJldHVybiBudWxsO3RyeXtyZXR1cm4icGFyc2UiaW4gZS5vdXRwdXRfZm9ybWF0P2Uub3V0cHV0X2Zvcm1hdC5wYXJzZSh0KTpKU09OLnBhcnNlKHQpfWNhdGNoKGUpe3Rocm93IG5ldyBvKGBGYWlsZWQgdG8gcGFyc2Ugc3RydWN0dXJlZCBvdXRwdXQ6ICR7ZX1gKX19KHQsZS50ZXh0KTtyZXR1cm4gbnVsbD09PXMmJihzPXIpLHsuLi5lLHBhcnNlZDpyfX1yZXR1cm4gZX0pO3JldHVybnsuLi5lLGNvbnRlbnQ6cixwYXJzZWRfb3V0cHV0OnN9fWNvbnN0IENlPWU9PntpZigwPT09ZS5sZW5ndGgpcmV0dXJuIGU7bGV0IHQ9ZVtlLmxlbmd0aC0xXTtzd2l0Y2godC50eXBlKXtjYXNlInNlcGFyYXRvciI6cmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2Nhc2UibnVtYmVyIjpsZXQgcz10LnZhbHVlW3QudmFsdWUubGVuZ3RoLTFdO2lmKCIuIj09PXN8fCItIj09PXMpcmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2Nhc2Uic3RyaW5nIjpsZXQgcj1lW2UubGVuZ3RoLTJdO2lmKCJkZWxpbWl0ZXIiPT09cj8udHlwZSlyZXR1cm4gZT1lLnNsaWNlKDAsZS5sZW5ndGgtMSksQ2UoZSk7aWYoImJyYWNlIj09PXI/LnR5cGUmJiJ7Ij09PXIudmFsdWUpcmV0dXJuIGU9ZS5zbGljZSgwLGUubGVuZ3RoLTEpLENlKGUpO2JyZWFrO2Nhc2UiZGVsaW1pdGVyIjpyZXR1cm4gZT1lLnNsaWNlKDAsZS5sZW5ndGgtMSksQ2UoZSl9cmV0dXJuIGV9LEllPWU9PkpTT04ucGFyc2UoKGU9PntsZXQgdD0iIjtyZXR1cm4gZS5tYXAoZT0+eyJzdHJpbmciPT09ZS50eXBlP3QrPSciJytlLnZhbHVlKyciJzp0Kz1lLnZhbHVlfSksdH0pKChlPT57bGV0IHQ9W107cmV0dXJuIGUubWFwKGU9PnsiYnJhY2UiPT09ZS50eXBlJiYoInsiPT09ZS52YWx1ZT90LnB1c2goIn0iKTp0LnNwbGljZSh0Lmxhc3RJbmRleE9mKCJ9IiksMSkpLCJwYXJlbiI9PT1lLnR5cGUmJigiWyI9PT1lLnZhbHVlP3QucHVzaCgiXSIpOnQuc3BsaWNlKHQubGFzdEluZGV4T2YoIl0iKSwxKSl9KSx0Lmxlbmd0aD4wJiZ0LnJldmVyc2UoKS5tYXAodD0+eyJ9Ij09PXQ/ZS5wdXNoKHt0eXBlOiJicmFjZSIsdmFsdWU6In0ifSk6Il0iPT09dCYmZS5wdXNoKHt0eXBlOiJwYXJlbiIsdmFsdWU6Il0ifSl9KSxlfSkoQ2UoKGU9PntsZXQgdD0wLHM9W107Zm9yKDt0PGUubGVuZ3RoOyl7bGV0IHI9ZVt0XTtpZigiXFwiPT09cil7dCsrO2NvbnRpbnVlfWlmKCJ7Ij09PXIpe3MucHVzaCh7dHlwZToiYnJhY2UiLHZhbHVlOiJ7In0pLHQrKztjb250aW51ZX1pZigifSI9PT1yKXtzLnB1c2goe3R5cGU6ImJyYWNlIix2YWx1ZToifSJ9KSx0Kys7Y29udGludWV9aWYoIlsiPT09cil7cy5wdXNoKHt0eXBlOiJwYXJlbiIsdmFsdWU6IlsifSksdCsrO2NvbnRpbnVlfWlmKCJdIj09PXIpe3MucHVzaCh7dHlwZToicGFyZW4iLHZhbHVlOiJdIn0pLHQrKztjb250aW51ZX1pZigiOiI9PT1yKXtzLnB1c2goe3R5cGU6InNlcGFyYXRvciIsdmFsdWU6IjoifSksdCsrO2NvbnRpbnVlfWlmKCIsIj09PXIpe3MucHVzaCh7dHlwZToiZGVsaW1pdGVyIix2YWx1ZToiLCJ9KSx0Kys7Y29udGludWV9aWYoJyInPT09cil7bGV0IG49IiIsYT0hMTtmb3Iocj1lWysrdF07JyInIT09cjspe2lmKHQ9PT1lLmxlbmd0aCl7YT0hMDticmVha31pZigiXFwiPT09cil7aWYodCsrLHQ9PT1lLmxlbmd0aCl7YT0hMDticmVha31uKz1yK2VbdF0scj1lWysrdF19ZWxzZSBuKz1yLHI9ZVsrK3RdfXI9ZVsrK3RdLGF8fHMucHVzaCh7dHlwZToic3RyaW5nIix2YWx1ZTpufSk7Y29udGludWV9aWYociYmL1xzLy50ZXN0KHIpKXt0Kys7Y29udGludWV9bGV0IG49L1swLTldLztpZihyJiZuLnRlc3Qocil8fCItIj09PXJ8fCIuIj09PXIpe2xldCBhPSIiO2ZvcigiLSI9PT1yJiYoYSs9cixyPWVbKyt0XSk7ciYmbi50ZXN0KHIpfHwiLiI9PT1yOylhKz1yLHI9ZVsrK3RdO3MucHVzaCh7dHlwZToibnVtYmVyIix2YWx1ZTphfSk7Y29udGludWV9bGV0IGE9L1thLXpdL2k7aWYociYmYS50ZXN0KHIpKXtsZXQgbj0iIjtmb3IoO3ImJmEudGVzdChyKSYmdCE9PWUubGVuZ3RoOyluKz1yLHI9ZVsrK3RdO2lmKCJ0cnVlIiE9biYmImZhbHNlIiE9biYmIm51bGwiIT09bil7dCsrO2NvbnRpbnVlfXMucHVzaCh7dHlwZToibmFtZSIsdmFsdWU6bn0pO2NvbnRpbnVlfXQrK31yZXR1cm4gc30pKGUpKSkpKTt2YXIgT2UsJGUsTGUsTmUsRGUsVWUscWUsamUsRmUsV2UsQmUsSmUsemUsSGUsS2UsVmUsWGUsR2UsWWUsUWUsWmUsZXQsdHQ7Y29uc3Qgc3Q9Il9fanNvbl9idWYiO2Z1bmN0aW9uIHJ0KGUpe3JldHVybiJ0b29sX3VzZSI9PT1lLnR5cGV8fCJzZXJ2ZXJfdG9vbF91c2UiPT09ZS50eXBlfHwibWNwX3Rvb2xfdXNlIj09PWUudHlwZX1jbGFzcyBudHtjb25zdHJ1Y3RvcihlKXtPZS5hZGQodGhpcyksdGhpcy5tZXNzYWdlcz1bXSx0aGlzLnJlY2VpdmVkTWVzc2FnZXM9W10sJGUuc2V0KHRoaXMsdm9pZCAwKSxMZS5zZXQodGhpcyxudWxsKSx0aGlzLmNvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcixOZS5zZXQodGhpcyx2b2lkIDApLERlLnNldCh0aGlzLCgpPT57fSksVWUuc2V0KHRoaXMsKCk9Pnt9KSxxZS5zZXQodGhpcyx2b2lkIDApLGplLnNldCh0aGlzLCgpPT57fSksRmUuc2V0KHRoaXMsKCk9Pnt9KSxXZS5zZXQodGhpcyx7fSksQmUuc2V0KHRoaXMsITEpLEplLnNldCh0aGlzLCExKSx6ZS5zZXQodGhpcywhMSksSGUuc2V0KHRoaXMsITEpLEtlLnNldCh0aGlzLHZvaWQgMCksVmUuc2V0KHRoaXMsdm9pZCAwKSxZZS5zZXQodGhpcyxlPT57aWYodCh0aGlzLEplLCEwLCJmIiksbihlKSYmKGU9bmV3IGMpLGUgaW5zdGFuY2VvZiBjKXJldHVybiB0KHRoaXMsemUsITAsImYiKSx0aGlzLl9lbWl0KCJhYm9ydCIsZSk7aWYoZSBpbnN0YW5jZW9mIG8pcmV0dXJuIHRoaXMuX2VtaXQoImVycm9yIixlKTtpZihlIGluc3RhbmNlb2YgRXJyb3Ipe2NvbnN0IHQ9bmV3IG8oZS5tZXNzYWdlKTtyZXR1cm4gdC5jYXVzZT1lLHRoaXMuX2VtaXQoImVycm9yIix0KX1yZXR1cm4gdGhpcy5fZW1pdCgiZXJyb3IiLG5ldyBvKFN0cmluZyhlKSkpfSksdCh0aGlzLE5lLG5ldyBQcm9taXNlKChlLHMpPT57dCh0aGlzLERlLGUsImYiKSx0KHRoaXMsVWUscywiZiIpfSksImYiKSx0KHRoaXMscWUsbmV3IFByb21pc2UoKGUscyk9Pnt0KHRoaXMsamUsZSwiZiIpLHQodGhpcyxGZSxzLCJmIil9KSwiZiIpLHModGhpcyxOZSwiZiIpLmNhdGNoKCgpPT57fSkscyh0aGlzLHFlLCJmIikuY2F0Y2goKCk9Pnt9KSx0KHRoaXMsTGUsZSwiZiIpfWdldCByZXNwb25zZSgpe3JldHVybiBzKHRoaXMsS2UsImYiKX1nZXQgcmVxdWVzdF9pZCgpe3JldHVybiBzKHRoaXMsVmUsImYiKX1hc3luYyB3aXRoUmVzcG9uc2UoKXtjb25zdCBlPWF3YWl0IHModGhpcyxOZSwiZiIpO2lmKCFlKXRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IHJlc29sdmUgYSBgUmVzcG9uc2VgIG9iamVjdCIpO3JldHVybntkYXRhOnRoaXMscmVzcG9uc2U6ZSxyZXF1ZXN0X2lkOmUuaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKX19c3RhdGljIGZyb21SZWFkYWJsZVN0cmVhbShlKXtjb25zdCB0PW5ldyBudChudWxsKTtyZXR1cm4gdC5fcnVuKCgpPT50Ll9mcm9tUmVhZGFibGVTdHJlYW0oZSkpLHR9c3RhdGljIGNyZWF0ZU1lc3NhZ2UoZSxzLHIpe2NvbnN0IG49bmV3IG50KHMpO2Zvcihjb25zdCBlIG9mIHMubWVzc2FnZXMpbi5fYWRkTWVzc2FnZVBhcmFtKGUpO3JldHVybiB0KG4sTGUsey4uLnMsc3RyZWFtOiEwfSwiZiIpLG4uX3J1bigoKT0+bi5fY3JlYXRlTWVzc2FnZShlLHsuLi5zLHN0cmVhbTohMH0sey4uLnIsaGVhZGVyczp7Li4ucj8uaGVhZGVycywiWC1TdGFpbmxlc3MtSGVscGVyLU1ldGhvZCI6InN0cmVhbSJ9fSkpLG59X3J1bihlKXtlKCkudGhlbigoKT0+e3RoaXMuX2VtaXRGaW5hbCgpLHRoaXMuX2VtaXQoImVuZCIpfSxzKHRoaXMsWWUsImYiKSl9X2FkZE1lc3NhZ2VQYXJhbShlKXt0aGlzLm1lc3NhZ2VzLnB1c2goZSl9X2FkZE1lc3NhZ2UoZSx0PSEwKXt0aGlzLnJlY2VpdmVkTWVzc2FnZXMucHVzaChlKSx0JiZ0aGlzLl9lbWl0KCJtZXNzYWdlIixlKX1hc3luYyBfY3JlYXRlTWVzc2FnZShlLHQscil7Y29uc3Qgbj1yPy5zaWduYWw7bGV0IGE7biYmKG4uYWJvcnRlZCYmdGhpcy5jb250cm9sbGVyLmFib3J0KCksYT10aGlzLmNvbnRyb2xsZXIuYWJvcnQuYmluZCh0aGlzLmNvbnRyb2xsZXIpLG4uYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLGEpKTt0cnl7cyh0aGlzLE9lLCJtIixRZSkuY2FsbCh0aGlzKTtjb25zdHtyZXNwb25zZTpuLGRhdGE6YX09YXdhaXQgZS5jcmVhdGUoey4uLnQsc3RyZWFtOiEwfSx7Li4ucixzaWduYWw6dGhpcy5jb250cm9sbGVyLnNpZ25hbH0pLndpdGhSZXNwb25zZSgpO3RoaXMuX2Nvbm5lY3RlZChuKTtmb3IgYXdhaXQoY29uc3QgZSBvZiBhKXModGhpcyxPZSwibSIsWmUpLmNhbGwodGhpcyxlKTtpZihhLmNvbnRyb2xsZXIuc2lnbmFsPy5hYm9ydGVkKXRocm93IG5ldyBjO3ModGhpcyxPZSwibSIsZXQpLmNhbGwodGhpcyl9ZmluYWxseXtuJiZhJiZuLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0IixhKX19X2Nvbm5lY3RlZChlKXt0aGlzLmVuZGVkfHwodCh0aGlzLEtlLGUsImYiKSx0KHRoaXMsVmUsZT8uaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKSwiZiIpLHModGhpcyxEZSwiZiIpLmNhbGwodGhpcyxlKSx0aGlzLl9lbWl0KCJjb25uZWN0IikpfWdldCBlbmRlZCgpe3JldHVybiBzKHRoaXMsQmUsImYiKX1nZXQgZXJyb3JlZCgpe3JldHVybiBzKHRoaXMsSmUsImYiKX1nZXQgYWJvcnRlZCgpe3JldHVybiBzKHRoaXMsemUsImYiKX1hYm9ydCgpe3RoaXMuY29udHJvbGxlci5hYm9ydCgpfW9uKGUsdCl7cmV0dXJuKHModGhpcyxXZSwiZiIpW2VdfHwocyh0aGlzLFdlLCJmIilbZV09W10pKS5wdXNoKHtsaXN0ZW5lcjp0fSksdGhpc31vZmYoZSx0KXtjb25zdCByPXModGhpcyxXZSwiZiIpW2VdO2lmKCFyKXJldHVybiB0aGlzO2NvbnN0IG49ci5maW5kSW5kZXgoZT0+ZS5saXN0ZW5lcj09PXQpO3JldHVybiBuPj0wJiZyLnNwbGljZShuLDEpLHRoaXN9b25jZShlLHQpe3JldHVybihzKHRoaXMsV2UsImYiKVtlXXx8KHModGhpcyxXZSwiZiIpW2VdPVtdKSkucHVzaCh7bGlzdGVuZXI6dCxvbmNlOiEwfSksdGhpc31lbWl0dGVkKGUpe3JldHVybiBuZXcgUHJvbWlzZSgocyxyKT0+e3QodGhpcyxIZSwhMCwiZiIpLCJlcnJvciIhPT1lJiZ0aGlzLm9uY2UoImVycm9yIixyKSx0aGlzLm9uY2UoZSxzKX0pfWFzeW5jIGRvbmUoKXt0KHRoaXMsSGUsITAsImYiKSxhd2FpdCBzKHRoaXMscWUsImYiKX1nZXQgY3VycmVudE1lc3NhZ2UoKXtyZXR1cm4gcyh0aGlzLCRlLCJmIil9YXN5bmMgZmluYWxNZXNzYWdlKCl7cmV0dXJuIGF3YWl0IHRoaXMuZG9uZSgpLHModGhpcyxPZSwibSIsWGUpLmNhbGwodGhpcyl9YXN5bmMgZmluYWxUZXh0KCl7cmV0dXJuIGF3YWl0IHRoaXMuZG9uZSgpLHModGhpcyxPZSwibSIsR2UpLmNhbGwodGhpcyl9X2VtaXQoZSwuLi5yKXtpZihzKHRoaXMsQmUsImYiKSlyZXR1cm47ImVuZCI9PT1lJiYodCh0aGlzLEJlLCEwLCJmIikscyh0aGlzLGplLCJmIikuY2FsbCh0aGlzKSk7Y29uc3Qgbj1zKHRoaXMsV2UsImYiKVtlXTtpZihuJiYocyh0aGlzLFdlLCJmIilbZV09bi5maWx0ZXIoZT0+IWUub25jZSksbi5mb3JFYWNoKCh7bGlzdGVuZXI6ZX0pPT5lKC4uLnIpKSksImFib3J0Ij09PWUpe2NvbnN0IGU9clswXTtyZXR1cm4gcyh0aGlzLEhlLCJmIil8fG4/Lmxlbmd0aHx8UHJvbWlzZS5yZWplY3QoZSkscyh0aGlzLFVlLCJmIikuY2FsbCh0aGlzLGUpLHModGhpcyxGZSwiZiIpLmNhbGwodGhpcyxlKSx2b2lkIHRoaXMuX2VtaXQoImVuZCIpfWlmKCJlcnJvciI9PT1lKXtjb25zdCBlPXJbMF07cyh0aGlzLEhlLCJmIil8fG4/Lmxlbmd0aHx8UHJvbWlzZS5yZWplY3QoZSkscyh0aGlzLFVlLCJmIikuY2FsbCh0aGlzLGUpLHModGhpcyxGZSwiZiIpLmNhbGwodGhpcyxlKSx0aGlzLl9lbWl0KCJlbmQiKX19X2VtaXRGaW5hbCgpe3RoaXMucmVjZWl2ZWRNZXNzYWdlcy5hdCgtMSkmJnRoaXMuX2VtaXQoImZpbmFsTWVzc2FnZSIscyh0aGlzLE9lLCJtIixYZSkuY2FsbCh0aGlzKSl9YXN5bmMgX2Zyb21SZWFkYWJsZVN0cmVhbShlLHQpe2NvbnN0IHI9dD8uc2lnbmFsO2xldCBuO3ImJihyLmFib3J0ZWQmJnRoaXMuY29udHJvbGxlci5hYm9ydCgpLG49dGhpcy5jb250cm9sbGVyLmFib3J0LmJpbmQodGhpcy5jb250cm9sbGVyKSxyLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IixuKSk7dHJ5e3ModGhpcyxPZSwibSIsUWUpLmNhbGwodGhpcyksdGhpcy5fY29ubmVjdGVkKG51bGwpO2NvbnN0IHQ9Wi5mcm9tUmVhZGFibGVTdHJlYW0oZSx0aGlzLmNvbnRyb2xsZXIpO2ZvciBhd2FpdChjb25zdCBlIG9mIHQpcyh0aGlzLE9lLCJtIixaZSkuY2FsbCh0aGlzLGUpO2lmKHQuY29udHJvbGxlci5zaWduYWw/LmFib3J0ZWQpdGhyb3cgbmV3IGM7cyh0aGlzLE9lLCJtIixldCkuY2FsbCh0aGlzKX1maW5hbGx5e3ImJm4mJnIucmVtb3ZlRXZlbnRMaXN0ZW5lcigiYWJvcnQiLG4pfX1bKCRlPW5ldyBXZWFrTWFwLExlPW5ldyBXZWFrTWFwLE5lPW5ldyBXZWFrTWFwLERlPW5ldyBXZWFrTWFwLFVlPW5ldyBXZWFrTWFwLHFlPW5ldyBXZWFrTWFwLGplPW5ldyBXZWFrTWFwLEZlPW5ldyBXZWFrTWFwLFdlPW5ldyBXZWFrTWFwLEJlPW5ldyBXZWFrTWFwLEplPW5ldyBXZWFrTWFwLHplPW5ldyBXZWFrTWFwLEhlPW5ldyBXZWFrTWFwLEtlPW5ldyBXZWFrTWFwLFZlPW5ldyBXZWFrTWFwLFllPW5ldyBXZWFrTWFwLE9lPW5ldyBXZWFrU2V0LFhlPWZ1bmN0aW9uKCl7aWYoMD09PXRoaXMucmVjZWl2ZWRNZXNzYWdlcy5sZW5ndGgpdGhyb3cgbmV3IG8oInN0cmVhbSBlbmRlZCB3aXRob3V0IHByb2R1Y2luZyBhIE1lc3NhZ2Ugd2l0aCByb2xlPWFzc2lzdGFudCIpO3JldHVybiB0aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpfSxHZT1mdW5jdGlvbigpe2lmKDA9PT10aGlzLnJlY2VpdmVkTWVzc2FnZXMubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBNZXNzYWdlIHdpdGggcm9sZT1hc3Npc3RhbnQiKTtjb25zdCBlPXRoaXMucmVjZWl2ZWRNZXNzYWdlcy5hdCgtMSkuY29udGVudC5maWx0ZXIoZT0+InRleHQiPT09ZS50eXBlKS5tYXAoZT0+ZS50ZXh0KTtpZigwPT09ZS5sZW5ndGgpdGhyb3cgbmV3IG8oInN0cmVhbSBlbmRlZCB3aXRob3V0IHByb2R1Y2luZyBhIGNvbnRlbnQgYmxvY2sgd2l0aCB0eXBlPXRleHQiKTtyZXR1cm4gZS5qb2luKCIgIil9LFFlPWZ1bmN0aW9uKCl7dGhpcy5lbmRlZHx8dCh0aGlzLCRlLHZvaWQgMCwiZiIpfSxaZT1mdW5jdGlvbihlKXtpZih0aGlzLmVuZGVkKXJldHVybjtjb25zdCByPXModGhpcyxPZSwibSIsdHQpLmNhbGwodGhpcyxlKTtzd2l0Y2godGhpcy5fZW1pdCgic3RyZWFtRXZlbnQiLGUsciksZS50eXBlKXtjYXNlImNvbnRlbnRfYmxvY2tfZGVsdGEiOntjb25zdCB0PXIuY29udGVudC5hdCgtMSk7c3dpdGNoKGUuZGVsdGEudHlwZSl7Y2FzZSJ0ZXh0X2RlbHRhIjoidGV4dCI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInRleHQiLGUuZGVsdGEudGV4dCx0LnRleHR8fCIiKTticmVhaztjYXNlImNpdGF0aW9uc19kZWx0YSI6InRleHQiPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJjaXRhdGlvbiIsZS5kZWx0YS5jaXRhdGlvbix0LmNpdGF0aW9ucz8/W10pO2JyZWFrO2Nhc2UiaW5wdXRfanNvbl9kZWx0YSI6cnQodCkmJnQuaW5wdXQmJnRoaXMuX2VtaXQoImlucHV0SnNvbiIsZS5kZWx0YS5wYXJ0aWFsX2pzb24sdC5pbnB1dCk7YnJlYWs7Y2FzZSJ0aGlua2luZ19kZWx0YSI6InRoaW5raW5nIj09PXQudHlwZSYmdGhpcy5fZW1pdCgidGhpbmtpbmciLGUuZGVsdGEudGhpbmtpbmcsdC50aGlua2luZyk7YnJlYWs7Y2FzZSJzaWduYXR1cmVfZGVsdGEiOiJ0aGlua2luZyI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInNpZ25hdHVyZSIsdC5zaWduYXR1cmUpO2JyZWFrO2RlZmF1bHQ6ZS5kZWx0YX1icmVha31jYXNlIm1lc3NhZ2Vfc3RvcCI6dGhpcy5fYWRkTWVzc2FnZVBhcmFtKHIpLHRoaXMuX2FkZE1lc3NhZ2UoVGUocixzKHRoaXMsTGUsImYiKSksITApO2JyZWFrO2Nhc2UiY29udGVudF9ibG9ja19zdG9wIjp0aGlzLl9lbWl0KCJjb250ZW50QmxvY2siLHIuY29udGVudC5hdCgtMSkpO2JyZWFrO2Nhc2UibWVzc2FnZV9zdGFydCI6dCh0aGlzLCRlLHIsImYiKX19LGV0PWZ1bmN0aW9uKCl7aWYodGhpcy5lbmRlZCl0aHJvdyBuZXcgbygic3RyZWFtIGhhcyBlbmRlZCwgdGhpcyBzaG91bGRuJ3QgaGFwcGVuIik7Y29uc3QgZT1zKHRoaXMsJGUsImYiKTtpZighZSl0aHJvdyBuZXcgbygicmVxdWVzdCBlbmRlZCB3aXRob3V0IHNlbmRpbmcgYW55IGNodW5rcyIpO3JldHVybiB0KHRoaXMsJGUsdm9pZCAwLCJmIiksVGUoZSxzKHRoaXMsTGUsImYiKSl9LHR0PWZ1bmN0aW9uKGUpe2xldCB0PXModGhpcywkZSwiZiIpO2lmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSl7aWYodCl0aHJvdyBuZXcgbyhgVW5leHBlY3RlZCBldmVudCBvcmRlciwgZ290ICR7ZS50eXBlfSBiZWZvcmUgcmVjZWl2aW5nICJtZXNzYWdlX3N0b3AiYCk7cmV0dXJuIGUubWVzc2FnZX1pZighdCl0aHJvdyBuZXcgbyhgVW5leHBlY3RlZCBldmVudCBvcmRlciwgZ290ICR7ZS50eXBlfSBiZWZvcmUgIm1lc3NhZ2Vfc3RhcnQiYCk7c3dpdGNoKGUudHlwZSl7Y2FzZSJtZXNzYWdlX3N0b3AiOmNhc2UiY29udGVudF9ibG9ja19zdG9wIjpyZXR1cm4gdDtjYXNlIm1lc3NhZ2VfZGVsdGEiOnJldHVybiB0LmNvbnRhaW5lcj1lLmRlbHRhLmNvbnRhaW5lcix0LnN0b3BfcmVhc29uPWUuZGVsdGEuc3RvcF9yZWFzb24sdC5zdG9wX3NlcXVlbmNlPWUuZGVsdGEuc3RvcF9zZXF1ZW5jZSx0LnVzYWdlLm91dHB1dF90b2tlbnM9ZS51c2FnZS5vdXRwdXRfdG9rZW5zLHQuY29udGV4dF9tYW5hZ2VtZW50PWUuY29udGV4dF9tYW5hZ2VtZW50LG51bGwhPWUudXNhZ2UuaW5wdXRfdG9rZW5zJiYodC51c2FnZS5pbnB1dF90b2tlbnM9ZS51c2FnZS5pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2UuY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zJiYodC51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnM9ZS51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMmJih0LnVzYWdlLmNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zPWUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMpLG51bGwhPWUudXNhZ2Uuc2VydmVyX3Rvb2xfdXNlJiYodC51c2FnZS5zZXJ2ZXJfdG9vbF91c2U9ZS51c2FnZS5zZXJ2ZXJfdG9vbF91c2UpLHQ7Y2FzZSJjb250ZW50X2Jsb2NrX3N0YXJ0IjpyZXR1cm4gdC5jb250ZW50LnB1c2goZS5jb250ZW50X2Jsb2NrKSx0O2Nhc2UiY29udGVudF9ibG9ja19kZWx0YSI6e2NvbnN0IHI9dC5jb250ZW50LmF0KGUuaW5kZXgpO3N3aXRjaChlLmRlbHRhLnR5cGUpe2Nhc2UidGV4dF9kZWx0YSI6InRleHQiPT09cj8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucix0ZXh0OihyLnRleHR8fCIiKStlLmRlbHRhLnRleHR9KTticmVhaztjYXNlImNpdGF0aW9uc19kZWx0YSI6InRleHQiPT09cj8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucixjaXRhdGlvbnM6Wy4uLnIuY2l0YXRpb25zPz9bXSxlLmRlbHRhLmNpdGF0aW9uXX0pO2JyZWFrO2Nhc2UiaW5wdXRfanNvbl9kZWx0YSI6aWYociYmcnQocikpe2xldCBuPXJbc3RdfHwiIjtuKz1lLmRlbHRhLnBhcnRpYWxfanNvbjtjb25zdCBhPXsuLi5yfTtpZihPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxzdCx7dmFsdWU6bixlbnVtZXJhYmxlOiExLHdyaXRhYmxlOiEwfSksbil0cnl7YS5pbnB1dD1JZShuKX1jYXRjaChlKXtjb25zdCB0PW5ldyBvKGBVbmFibGUgdG8gcGFyc2UgdG9vbCBwYXJhbWV0ZXIgSlNPTiBmcm9tIG1vZGVsLiBQbGVhc2UgcmV0cnkgeW91ciByZXF1ZXN0IG9yIGFkanVzdCB5b3VyIHByb21wdC4gRXJyb3I6ICR7ZX0uIEpTT046ICR7bn1gKTtzKHRoaXMsWWUsImYiKS5jYWxsKHRoaXMsdCl9dC5jb250ZW50W2UuaW5kZXhdPWF9YnJlYWs7Y2FzZSJ0aGlua2luZ19kZWx0YSI6InRoaW5raW5nIj09PXI/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnIsdGhpbmtpbmc6ci50aGlua2luZytlLmRlbHRhLnRoaW5raW5nfSk7YnJlYWs7Y2FzZSJzaWduYXR1cmVfZGVsdGEiOiJ0aGlua2luZyI9PT1yPy50eXBlJiYodC5jb250ZW50W2UuaW5kZXhdPXsuLi5yLHNpZ25hdHVyZTplLmRlbHRhLnNpZ25hdHVyZX0pO2JyZWFrO2RlZmF1bHQ6ZS5kZWx0YX1yZXR1cm4gdH19fSxTeW1ib2wuYXN5bmNJdGVyYXRvcildKCl7Y29uc3QgZT1bXSx0PVtdO2xldCBzPSExO3JldHVybiB0aGlzLm9uKCJzdHJlYW1FdmVudCIscz0+e2NvbnN0IHI9dC5zaGlmdCgpO3I/ci5yZXNvbHZlKHMpOmUucHVzaChzKX0pLHRoaXMub24oImVuZCIsKCk9PntzPSEwO2Zvcihjb25zdCBlIG9mIHQpZS5yZXNvbHZlKHZvaWQgMCk7dC5sZW5ndGg9MH0pLHRoaXMub24oImFib3J0IixlPT57cz0hMDtmb3IoY29uc3QgcyBvZiB0KXMucmVqZWN0KGUpO3QubGVuZ3RoPTB9KSx0aGlzLm9uKCJlcnJvciIsZT0+e3M9ITA7Zm9yKGNvbnN0IHMgb2YgdClzLnJlamVjdChlKTt0Lmxlbmd0aD0wfSkse25leHQ6YXN5bmMoKT0+ZS5sZW5ndGg/e3ZhbHVlOmUuc2hpZnQoKSxkb25lOiExfTpzP3t2YWx1ZTp2b2lkIDAsZG9uZTohMH06bmV3IFByb21pc2UoKGUscyk9PnQucHVzaCh7cmVzb2x2ZTplLHJlamVjdDpzfSkpLnRoZW4oZT0+ZT97dmFsdWU6ZSxkb25lOiExfTp7dmFsdWU6dm9pZCAwLGRvbmU6ITB9KSxyZXR1cm46YXN5bmMoKT0+KHRoaXMuYWJvcnQoKSx7dmFsdWU6dm9pZCAwLGRvbmU6ITB9KX19dG9SZWFkYWJsZVN0cmVhbSgpe3JldHVybiBuZXcgWih0aGlzW1N5bWJvbC5hc3luY0l0ZXJhdG9yXS5iaW5kKHRoaXMpLHRoaXMuY29udHJvbGxlcikudG9SZWFkYWJsZVN0cmVhbSgpfX12YXIgYXQsb3QsaXQsY3QsbHQsZHQsaHQsdXQscHQsZnQsbXQ7ZnVuY3Rpb24gZ3QoKXtsZXQgZSx0O3JldHVybntwcm9taXNlOm5ldyBQcm9taXNlKChzLHIpPT57ZT1zLHQ9cn0pLHJlc29sdmU6ZSxyZWplY3Q6dH19Y2xhc3Mgd3R7Y29uc3RydWN0b3IoZSxzLHIpe2F0LmFkZCh0aGlzKSx0aGlzLmNsaWVudD1lLG90LnNldCh0aGlzLCExKSxpdC5zZXQodGhpcywhMSksY3Quc2V0KHRoaXMsdm9pZCAwKSxsdC5zZXQodGhpcyx2b2lkIDApLGR0LnNldCh0aGlzLHZvaWQgMCksaHQuc2V0KHRoaXMsdm9pZCAwKSx1dC5zZXQodGhpcyx2b2lkIDApLHB0LnNldCh0aGlzLDApLHQodGhpcyxjdCx7cGFyYW1zOnsuLi5zLG1lc3NhZ2VzOnN0cnVjdHVyZWRDbG9uZShzLm1lc3NhZ2VzKX19LCJmIiksdCh0aGlzLGx0LHsuLi5yLGhlYWRlcnM6X2UoW3sieC1zdGFpbmxlc3MtaGVscGVyIjoiQmV0YVRvb2xSdW5uZXIifSxyPy5oZWFkZXJzXSl9LCJmIiksdCh0aGlzLHV0LGd0KCksImYiKX1hc3luYypbKG90PW5ldyBXZWFrTWFwLGl0PW5ldyBXZWFrTWFwLGN0PW5ldyBXZWFrTWFwLGx0PW5ldyBXZWFrTWFwLGR0PW5ldyBXZWFrTWFwLGh0PW5ldyBXZWFrTWFwLHV0PW5ldyBXZWFrTWFwLHB0PW5ldyBXZWFrTWFwLGF0PW5ldyBXZWFrU2V0LGZ0PWFzeW5jIGZ1bmN0aW9uKCl7Y29uc3QgZT1zKHRoaXMsY3QsImYiKS5wYXJhbXMuY29tcGFjdGlvbkNvbnRyb2w7aWYoIWV8fCFlLmVuYWJsZWQpcmV0dXJuITE7bGV0IHQ9MDtpZih2b2lkIDAhPT1zKHRoaXMsZHQsImYiKSl0cnl7Y29uc3QgZT1hd2FpdCBzKHRoaXMsZHQsImYiKTt0PWUudXNhZ2UuaW5wdXRfdG9rZW5zKyhlLnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2Vucz8/MCkrKGUudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM/PzApK2UudXNhZ2Uub3V0cHV0X3Rva2Vuc31jYXRjaHtyZXR1cm4hMX1pZih0PChlLmNvbnRleHRUb2tlblRocmVzaG9sZD8/MWU1KSlyZXR1cm4hMTtjb25zdCByPWUubW9kZWw/P3ModGhpcyxjdCwiZiIpLnBhcmFtcy5tb2RlbCxuPWUuc3VtbWFyeVByb21wdD8/IllvdSBoYXZlIGJlZW4gd29ya2luZyBvbiB0aGUgdGFzayBkZXNjcmliZWQgYWJvdmUgYnV0IGhhdmUgbm90IHlldCBjb21wbGV0ZWQgaXQuIFdyaXRlIGEgY29udGludWF0aW9uIHN1bW1hcnkgdGhhdCB3aWxsIGFsbG93IHlvdSAob3IgYW5vdGhlciBpbnN0YW5jZSBvZiB5b3Vyc2VsZikgdG8gcmVzdW1lIHdvcmsgZWZmaWNpZW50bHkgaW4gYSBmdXR1cmUgY29udGV4dCB3aW5kb3cgd2hlcmUgdGhlIGNvbnZlcnNhdGlvbiBoaXN0b3J5IHdpbGwgYmUgcmVwbGFjZWQgd2l0aCB0aGlzIHN1bW1hcnkuIFlvdXIgc3VtbWFyeSBzaG91bGQgYmUgc3RydWN0dXJlZCwgY29uY2lzZSwgYW5kIGFjdGlvbmFibGUuIEluY2x1ZGU6XG4xLiBUYXNrIE92ZXJ2aWV3XG5UaGUgdXNlcidzIGNvcmUgcmVxdWVzdCBhbmQgc3VjY2VzcyBjcml0ZXJpYVxuQW55IGNsYXJpZmljYXRpb25zIG9yIGNvbnN0cmFpbnRzIHRoZXkgc3BlY2lmaWVkXG4yLiBDdXJyZW50IFN0YXRlXG5XaGF0IGhhcyBiZWVuIGNvbXBsZXRlZCBzbyBmYXJcbkZpbGVzIGNyZWF0ZWQsIG1vZGlmaWVkLCBvciBhbmFseXplZCAod2l0aCBwYXRocyBpZiByZWxldmFudClcbktleSBvdXRwdXRzIG9yIGFydGlmYWN0cyBwcm9kdWNlZFxuMy4gSW1wb3J0YW50IERpc2NvdmVyaWVzXG5UZWNobmljYWwgY29uc3RyYWludHMgb3IgcmVxdWlyZW1lbnRzIHVuY292ZXJlZFxuRGVjaXNpb25zIG1hZGUgYW5kIHRoZWlyIHJhdGlvbmFsZVxuRXJyb3JzIGVuY291bnRlcmVkIGFuZCBob3cgdGhleSB3ZXJlIHJlc29sdmVkXG5XaGF0IGFwcHJvYWNoZXMgd2VyZSB0cmllZCB0aGF0IGRpZG4ndCB3b3JrIChhbmQgd2h5KVxuNC4gTmV4dCBTdGVwc1xuU3BlY2lmaWMgYWN0aW9ucyBuZWVkZWQgdG8gY29tcGxldGUgdGhlIHRhc2tcbkFueSBibG9ja2VycyBvciBvcGVuIHF1ZXN0aW9ucyB0byByZXNvbHZlXG5Qcmlvcml0eSBvcmRlciBpZiBtdWx0aXBsZSBzdGVwcyByZW1haW5cbjUuIENvbnRleHQgdG8gUHJlc2VydmVcblVzZXIgcHJlZmVyZW5jZXMgb3Igc3R5bGUgcmVxdWlyZW1lbnRzXG5Eb21haW4tc3BlY2lmaWMgZGV0YWlscyB0aGF0IGFyZW4ndCBvYnZpb3VzXG5BbnkgcHJvbWlzZXMgbWFkZSB0byB0aGUgdXNlclxuQmUgY29uY2lzZSBidXQgY29tcGxldGXigJRlcnIgb24gdGhlIHNpZGUgb2YgaW5jbHVkaW5nIGluZm9ybWF0aW9uIHRoYXQgd291bGQgcHJldmVudCBkdXBsaWNhdGUgd29yayBvciByZXBlYXRlZCBtaXN0YWtlcy4gV3JpdGUgaW4gYSB3YXkgdGhhdCBlbmFibGVzIGltbWVkaWF0ZSByZXN1bXB0aW9uIG9mIHRoZSB0YXNrLlxuV3JhcCB5b3VyIHN1bW1hcnkgaW4gPHN1bW1hcnk+PC9zdW1tYXJ5PiB0YWdzLiIsYT1zKHRoaXMsY3QsImYiKS5wYXJhbXMubWVzc2FnZXM7aWYoImFzc2lzdGFudCI9PT1hW2EubGVuZ3RoLTFdLnJvbGUpe2NvbnN0IGU9YVthLmxlbmd0aC0xXTtpZihBcnJheS5pc0FycmF5KGUuY29udGVudCkpe2NvbnN0IHQ9ZS5jb250ZW50LmZpbHRlcihlPT4idG9vbF91c2UiIT09ZS50eXBlKTswPT09dC5sZW5ndGg/YS5wb3AoKTplLmNvbnRlbnQ9dH19Y29uc3QgaT1hd2FpdCB0aGlzLmNsaWVudC5iZXRhLm1lc3NhZ2VzLmNyZWF0ZSh7bW9kZWw6cixtZXNzYWdlczpbLi4uYSx7cm9sZToidXNlciIsY29udGVudDpbe3R5cGU6InRleHQiLHRleHQ6bn1dfV0sbWF4X3Rva2VuczpzKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X3Rva2Vuc30se2hlYWRlcnM6eyJ4LXN0YWlubGVzcy1oZWxwZXIiOiJjb21wYWN0aW9uIn19KTtpZigidGV4dCIhPT1pLmNvbnRlbnRbMF0/LnR5cGUpdGhyb3cgbmV3IG8oIkV4cGVjdGVkIHRleHQgcmVzcG9uc2UgZm9yIGNvbXBhY3Rpb24iKTtyZXR1cm4gcyh0aGlzLGN0LCJmIikucGFyYW1zLm1lc3NhZ2VzPVt7cm9sZToidXNlciIsY29udGVudDppLmNvbnRlbnR9XSwhMH0sU3ltYm9sLmFzeW5jSXRlcmF0b3IpXSgpe3ZhciBlO2lmKHModGhpcyxvdCwiZiIpKXRocm93IG5ldyBvKCJDYW5ub3QgaXRlcmF0ZSBvdmVyIGEgY29uc3VtZWQgc3RyZWFtIik7dCh0aGlzLG90LCEwLCJmIiksdCh0aGlzLGl0LCEwLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpO3RyeXtmb3IoOzspe2xldCByO3RyeXtpZihzKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X2l0ZXJhdGlvbnMmJnModGhpcyxwdCwiZiIpPj1zKHRoaXMsY3QsImYiKS5wYXJhbXMubWF4X2l0ZXJhdGlvbnMpYnJlYWs7dCh0aGlzLGl0LCExLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpLHQodGhpcyxwdCwoZT1zKHRoaXMscHQsImYiKSwrK2UpLCJmIiksdCh0aGlzLGR0LHZvaWQgMCwiZiIpO2NvbnN0e21heF9pdGVyYXRpb25zOm4sY29tcGFjdGlvbkNvbnRyb2w6YSwuLi5vfT1zKHRoaXMsY3QsImYiKS5wYXJhbXM7aWYoby5zdHJlYW0/KHI9dGhpcy5jbGllbnQuYmV0YS5tZXNzYWdlcy5zdHJlYW0oey4uLm99LHModGhpcyxsdCwiZiIpKSx0KHRoaXMsZHQsci5maW5hbE1lc3NhZ2UoKSwiZiIpLHModGhpcyxkdCwiZiIpLmNhdGNoKCgpPT57fSkseWllbGQgcik6KHQodGhpcyxkdCx0aGlzLmNsaWVudC5iZXRhLm1lc3NhZ2VzLmNyZWF0ZSh7Li4ubyxzdHJlYW06ITF9LHModGhpcyxsdCwiZiIpKSwiZiIpLHlpZWxkIHModGhpcyxkdCwiZiIpKSwhYXdhaXQgcyh0aGlzLGF0LCJtIixmdCkuY2FsbCh0aGlzKSl7aWYoIXModGhpcyxpdCwiZiIpKXtjb25zdHtyb2xlOmUsY29udGVudDp0fT1hd2FpdCBzKHRoaXMsZHQsImYiKTtzKHRoaXMsY3QsImYiKS5wYXJhbXMubWVzc2FnZXMucHVzaCh7cm9sZTplLGNvbnRlbnQ6dH0pfWNvbnN0IGU9YXdhaXQgcyh0aGlzLGF0LCJtIixtdCkuY2FsbCh0aGlzLHModGhpcyxjdCwiZiIpLnBhcmFtcy5tZXNzYWdlcy5hdCgtMSkpO2lmKGUpcyh0aGlzLGN0LCJmIikucGFyYW1zLm1lc3NhZ2VzLnB1c2goZSk7ZWxzZSBpZighcyh0aGlzLGl0LCJmIikpYnJlYWt9fWZpbmFsbHl7ciYmci5hYm9ydCgpfX1pZighcyh0aGlzLGR0LCJmIikpdGhyb3cgbmV3IG8oIlRvb2xSdW5uZXIgY29uY2x1ZGVkIHdpdGhvdXQgYSBtZXNzYWdlIGZyb20gdGhlIHNlcnZlciIpO3ModGhpcyx1dCwiZiIpLnJlc29sdmUoYXdhaXQgcyh0aGlzLGR0LCJmIikpfWNhdGNoKGUpe3Rocm93IHQodGhpcyxvdCwhMSwiZiIpLHModGhpcyx1dCwiZiIpLnByb21pc2UuY2F0Y2goKCk9Pnt9KSxzKHRoaXMsdXQsImYiKS5yZWplY3QoZSksdCh0aGlzLHV0LGd0KCksImYiKSxlfX1zZXRNZXNzYWdlc1BhcmFtcyhlKXtzKHRoaXMsY3QsImYiKS5wYXJhbXM9ImZ1bmN0aW9uIj09dHlwZW9mIGU/ZShzKHRoaXMsY3QsImYiKS5wYXJhbXMpOmUsdCh0aGlzLGl0LCEwLCJmIiksdCh0aGlzLGh0LHZvaWQgMCwiZiIpfWFzeW5jIGdlbmVyYXRlVG9vbFJlc3BvbnNlKCl7Y29uc3QgZT1hd2FpdCBzKHRoaXMsZHQsImYiKT8/dGhpcy5wYXJhbXMubWVzc2FnZXMuYXQoLTEpO3JldHVybiBlP3ModGhpcyxhdCwibSIsbXQpLmNhbGwodGhpcyxlKTpudWxsfWRvbmUoKXtyZXR1cm4gcyh0aGlzLHV0LCJmIikucHJvbWlzZX1hc3luYyBydW5VbnRpbERvbmUoKXtpZighcyh0aGlzLG90LCJmIikpZm9yIGF3YWl0KGNvbnN0IGUgb2YgdGhpcyk7cmV0dXJuIHRoaXMuZG9uZSgpfWdldCBwYXJhbXMoKXtyZXR1cm4gcyh0aGlzLGN0LCJmIikucGFyYW1zfXB1c2hNZXNzYWdlcyguLi5lKXt0aGlzLnNldE1lc3NhZ2VzUGFyYW1zKHQ9Pih7Li4udCxtZXNzYWdlczpbLi4udC5tZXNzYWdlcywuLi5lXX0pKX10aGVuKGUsdCl7cmV0dXJuIHRoaXMucnVuVW50aWxEb25lKCkudGhlbihlLHQpfX1tdD1hc3luYyBmdW5jdGlvbihlKXtyZXR1cm4gdm9pZCAwIT09cyh0aGlzLGh0LCJmIil8fHQodGhpcyxodCxhc3luYyBmdW5jdGlvbihlLHQ9ZS5tZXNzYWdlcy5hdCgtMSkpe2lmKCF0fHwiYXNzaXN0YW50IiE9PXQucm9sZXx8IXQuY29udGVudHx8InN0cmluZyI9PXR5cGVvZiB0LmNvbnRlbnQpcmV0dXJuIG51bGw7Y29uc3Qgcz10LmNvbnRlbnQuZmlsdGVyKGU9PiJ0b29sX3VzZSI9PT1lLnR5cGUpO3JldHVybiAwPT09cy5sZW5ndGg/bnVsbDp7cm9sZToidXNlciIsY29udGVudDphd2FpdCBQcm9taXNlLmFsbChzLm1hcChhc3luYyB0PT57Y29uc3Qgcz1lLnRvb2xzLmZpbmQoZT0+KCJuYW1lImluIGU/ZS5uYW1lOmUubWNwX3NlcnZlcl9uYW1lKT09PXQubmFtZSk7aWYoIXN8fCEoInJ1biJpbiBzKSlyZXR1cm57dHlwZToidG9vbF9yZXN1bHQiLHRvb2xfdXNlX2lkOnQuaWQsY29udGVudDpgRXJyb3I6IFRvb2wgJyR7dC5uYW1lfScgbm90IGZvdW5kYCxpc19lcnJvcjohMH07dHJ5e2xldCBlPXQuaW5wdXQ7InBhcnNlImluIHMmJnMucGFyc2UmJihlPXMucGFyc2UoZSkpO2NvbnN0IHI9YXdhaXQgcy5ydW4oZSk7cmV0dXJue3R5cGU6InRvb2xfcmVzdWx0Iix0b29sX3VzZV9pZDp0LmlkLGNvbnRlbnQ6cn19Y2F0Y2goZSl7cmV0dXJue3R5cGU6InRvb2xfcmVzdWx0Iix0b29sX3VzZV9pZDp0LmlkLGNvbnRlbnQ6YEVycm9yOiAke2UgaW5zdGFuY2VvZiBFcnJvcj9lLm1lc3NhZ2U6U3RyaW5nKGUpfWAsaXNfZXJyb3I6ITB9fX0pKX19KHModGhpcyxjdCwiZiIpLnBhcmFtcyxlKSwiZiIpLHModGhpcyxodCwiZiIpfTtjbGFzcyB5dHtjb25zdHJ1Y3RvcihlLHQpe3RoaXMuaXRlcmF0b3I9ZSx0aGlzLmNvbnRyb2xsZXI9dH1hc3luYypkZWNvZGVyKCl7Y29uc3QgZT1uZXcgcTtmb3IgYXdhaXQoY29uc3QgdCBvZiB0aGlzLml0ZXJhdG9yKWZvcihjb25zdCBzIG9mIGUuZGVjb2RlKHQpKXlpZWxkIEpTT04ucGFyc2Uocyk7Zm9yKGNvbnN0IHQgb2YgZS5mbHVzaCgpKXlpZWxkIEpTT04ucGFyc2UodCl9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzLmRlY29kZXIoKX1zdGF0aWMgZnJvbVJlc3BvbnNlKGUsdCl7aWYoIWUuYm9keSl7aWYodC5hYm9ydCgpLHZvaWQgMCE9PWdsb2JhbFRoaXMubmF2aWdhdG9yJiYiUmVhY3ROYXRpdmUiPT09Z2xvYmFsVGhpcy5uYXZpZ2F0b3IucHJvZHVjdCl0aHJvdyBuZXcgbygiVGhlIGRlZmF1bHQgcmVhY3QtbmF0aXZlIGZldGNoIGltcGxlbWVudGF0aW9uIGRvZXMgbm90IHN1cHBvcnQgc3RyZWFtaW5nLiBQbGVhc2UgdXNlIGV4cG8vZmV0Y2g6IGh0dHBzOi8vZG9jcy5leHBvLmRldi92ZXJzaW9ucy9sYXRlc3Qvc2RrL2V4cG8vI2V4cG9mZXRjaC1hcGkiKTt0aHJvdyBuZXcgbygiQXR0ZW1wdGVkIHRvIGl0ZXJhdGUgb3ZlciBhIHJlc3BvbnNlIHdpdGggbm8gYm9keSIpfXJldHVybiBuZXcgeXQoQyhlLmJvZHkpLHQpfX1jbGFzcyBidCBleHRlbmRzIHlle2NyZWF0ZShlLHQpe2NvbnN0e2JldGFzOnMsLi4ucn09ZTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9tZXNzYWdlcy9iYXRjaGVzP2JldGE9dHJ1ZSIse2JvZHk6ciwuLi50LGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5zPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX1yZXRyaWV2ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL21lc3NhZ2VzL2JhdGNoZXMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9tZXNzYWdlcy9iYXRjaGVzP2JldGE9dHJ1ZSIsb2Use3F1ZXJ5OnIsLi4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucz8/W10sIm1lc3NhZ2UtYmF0Y2hlcy0yMDI0LTA5LTI0Il0udG9TdHJpbmcoKX0sdD8uaGVhZGVyc10pfSl9ZGVsZXRlKGUsdD17fSxzKXtjb25zdHtiZXRhczpyfT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmRlbGV0ZShQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9P2JldGE9dHJ1ZWAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJtZXNzYWdlLWJhdGNoZXMtMjAyNC0wOS0yNCJdLnRvU3RyaW5nKCl9LHM/LmhlYWRlcnNdKX0pfWNhbmNlbChlLHQ9e30scyl7Y29uc3R7YmV0YXM6cn09dD8/e307cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KFBlYC92MS9tZXNzYWdlcy9iYXRjaGVzLyR7ZX0vY2FuY2VsP2JldGE9dHJ1ZWAsey4uLnMsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnI/P1tdLCJtZXNzYWdlLWJhdGNoZXMtMjAyNC0wOS0yNCJdLnRvU3RyaW5nKCl9LHM/LmhlYWRlcnNdKX0pfWFzeW5jIHJlc3VsdHMoZSx0PXt9LHMpe2NvbnN0IHI9YXdhaXQgdGhpcy5yZXRyaWV2ZShlKTtpZighci5yZXN1bHRzX3VybCl0aHJvdyBuZXcgbyhgTm8gYmF0Y2ggXGByZXN1bHRzX3VybFxgOyBIYXMgaXQgZmluaXNoZWQgcHJvY2Vzc2luZz8gJHtyLnByb2Nlc3Npbmdfc3RhdHVzfSAtICR7ci5pZH1gKTtjb25zdHtiZXRhczpufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChyLnJlc3VsdHNfdXJsLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5uPz9bXSwibWVzc2FnZS1iYXRjaGVzLTIwMjQtMDktMjQiXS50b1N0cmluZygpLEFjY2VwdDoiYXBwbGljYXRpb24vYmluYXJ5In0scz8uaGVhZGVyc10pLHN0cmVhbTohMCxfX2JpbmFyeVJlc3BvbnNlOiEwfSkuX3RoZW5VbndyYXAoKGUsdCk9Pnl0LmZyb21SZXNwb25zZSh0LnJlc3BvbnNlLHQuY29udHJvbGxlcikpfX1jb25zdCB2dD17ImNsYXVkZS0xLjMiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtMS4zLTEwMGsiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjEiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjEtMTAwayI6Ik5vdmVtYmVyIDZ0aCwgMjAyNCIsImNsYXVkZS1pbnN0YW50LTEuMiI6Ik5vdmVtYmVyIDZ0aCwgMjAyNCIsImNsYXVkZS0zLXNvbm5ldC0yMDI0MDIyOSI6Ikp1bHkgMjFzdCwgMjAyNSIsImNsYXVkZS0zLW9wdXMtMjAyNDAyMjkiOiJKYW51YXJ5IDV0aCwgMjAyNiIsImNsYXVkZS0yLjEiOiJKdWx5IDIxc3QsIDIwMjUiLCJjbGF1ZGUtMi4wIjoiSnVseSAyMXN0LCAyMDI1IiwiY2xhdWRlLTMtNy1zb25uZXQtbGF0ZXN0IjoiRmVicnVhcnkgMTl0aCwgMjAyNiIsImNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5IjoiRmVicnVhcnkgMTl0aCwgMjAyNiJ9O2NsYXNzIF90IGV4dGVuZHMgeWV7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMuYmF0Y2hlcz1uZXcgYnQodGhpcy5fY2xpZW50KX1jcmVhdGUoZSx0KXtjb25zdHtiZXRhczpzLC4uLnJ9PWU7ci5tb2RlbCBpbiB2dCYmY29uc29sZS53YXJuKGBUaGUgbW9kZWwgJyR7ci5tb2RlbH0nIGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgcmVhY2ggZW5kLW9mLWxpZmUgb24gJHt2dFtyLm1vZGVsXX1cblBsZWFzZSBtaWdyYXRlIHRvIGEgbmV3ZXIgbW9kZWwuIFZpc2l0IGh0dHBzOi8vZG9jcy5hbnRocm9waWMuY29tL2VuL2RvY3MvcmVzb3VyY2VzL21vZGVsLWRlcHJlY2F0aW9ucyBmb3IgbW9yZSBpbmZvcm1hdGlvbi5gKTtsZXQgbj10aGlzLl9jbGllbnQuX29wdGlvbnMudGltZW91dDtpZighci5zdHJlYW0mJm51bGw9PW4pe2NvbnN0IGU9eGVbci5tb2RlbF0/P3ZvaWQgMDtuPXRoaXMuX2NsaWVudC5jYWxjdWxhdGVOb25zdHJlYW1pbmdUaW1lb3V0KHIubWF4X3Rva2VucyxlKX1yZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9tZXNzYWdlcz9iZXRhPXRydWUiLHtib2R5OnIsdGltZW91dDpuPz82ZTUsLi4udCxoZWFkZXJzOl9lKFt7Li4ubnVsbCE9cz8udG9TdHJpbmcoKT97ImFudGhyb3BpYy1iZXRhIjpzPy50b1N0cmluZygpfTp2b2lkIDB9LHQ/LmhlYWRlcnNdKSxzdHJlYW06ZS5zdHJlYW0/PyExfSl9cGFyc2UoZSx0KXtyZXR1cm4gdD17Li4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4uZS5iZXRhcz8/W10sInN0cnVjdHVyZWQtb3V0cHV0cy0yMDI1LTExLTEzIl0udG9TdHJpbmcoKX0sdD8uaGVhZGVyc10pfSx0aGlzLmNyZWF0ZShlLHQpLnRoZW4odD0+QWUodCxlKSl9c3RyZWFtKGUsdCl7cmV0dXJuIG50LmNyZWF0ZU1lc3NhZ2UodGhpcyxlLHQpfWNvdW50VG9rZW5zKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL21lc3NhZ2VzL2NvdW50X3Rva2Vucz9iZXRhPXRydWUiLHtib2R5OnIsLi4udCxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucz8/W10sInRva2VuLWNvdW50aW5nLTIwMjQtMTEtMDEiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX10b29sUnVubmVyKGUsdCl7cmV0dXJuIG5ldyB3dCh0aGlzLl9jbGllbnQsZSx0KX19X3QuQmF0Y2hlcz1idCxfdC5CZXRhVG9vbFJ1bm5lcj13dDtjbGFzcyBrdCBleHRlbmRzIHlle2NyZWF0ZShlLHQ9e30scyl7Y29uc3R7YmV0YXM6ciwuLi5ufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoUGVgL3YxL3NraWxscy8ke2V9L3ZlcnNpb25zP2JldGE9dHJ1ZWAsdWUoe2JvZHk6biwuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9LHRoaXMuX2NsaWVudCkpfXJldHJpZXZlKGUsdCxzKXtjb25zdHtza2lsbF9pZDpyLGJldGFzOm59PXQ7cmV0dXJuIHRoaXMuX2NsaWVudC5nZXQoUGVgL3YxL3NraWxscy8ke3J9L3ZlcnNpb25zLyR7ZX0/YmV0YT10cnVlYCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ubj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9bGlzdChlLHQ9e30scyl7Y29uc3R7YmV0YXM6ciwuLi5ufT10Pz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoUGVgL3YxL3NraWxscy8ke2V9L3ZlcnNpb25zP2JldGE9dHJ1ZWAsaWUse3F1ZXJ5Om4sLi4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ucj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9ZGVsZXRlKGUsdCxzKXtjb25zdHtza2lsbF9pZDpyLGJldGFzOm59PXQ7cmV0dXJuIHRoaXMuX2NsaWVudC5kZWxldGUoUGVgL3YxL3NraWxscy8ke3J9L3ZlcnNpb25zLyR7ZX0/YmV0YT10cnVlYCx7Li4ucyxoZWFkZXJzOl9lKFt7ImFudGhyb3BpYy1iZXRhIjpbLi4ubj8/W10sInNraWxscy0yMDI1LTEwLTAyIl0udG9TdHJpbmcoKX0scz8uaGVhZGVyc10pfSl9fWNsYXNzIFN0IGV4dGVuZHMgeWV7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMudmVyc2lvbnM9bmV3IGt0KHRoaXMuX2NsaWVudCl9Y3JlYXRlKGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LnBvc3QoIi92MS9za2lsbHM/YmV0YT10cnVlIix1ZSh7Ym9keTpyLC4uLnQsaGVhZGVyczpfZShbeyJhbnRocm9waWMtYmV0YSI6Wy4uLnM/P1tdLCJza2lsbHMtMjAyNS0xMC0wMiJdLnRvU3RyaW5nKCl9LHQ/LmhlYWRlcnNdKX0sdGhpcy5fY2xpZW50KSl9cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9za2lsbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9za2lsbHM/YmV0YT10cnVlIixpZSx7cXVlcnk6ciwuLi50LGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5zPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSx0Py5oZWFkZXJzXSl9KX1kZWxldGUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZGVsZXRlKFBlYC92MS9za2lsbHMvJHtlfT9iZXRhPXRydWVgLHsuLi5zLGhlYWRlcnM6X2UoW3siYW50aHJvcGljLWJldGEiOlsuLi5yPz9bXSwic2tpbGxzLTIwMjUtMTAtMDIiXS50b1N0cmluZygpfSxzPy5oZWFkZXJzXSl9KX19U3QuVmVyc2lvbnM9a3Q7Y2xhc3MgTXQgZXh0ZW5kcyB5ZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5tb2RlbHM9bmV3IFJlKHRoaXMuX2NsaWVudCksdGhpcy5tZXNzYWdlcz1uZXcgX3QodGhpcy5fY2xpZW50KSx0aGlzLmZpbGVzPW5ldyBFZSh0aGlzLl9jbGllbnQpLHRoaXMuc2tpbGxzPW5ldyBTdCh0aGlzLl9jbGllbnQpfX1NdC5Nb2RlbHM9UmUsTXQuTWVzc2FnZXM9X3QsTXQuRmlsZXM9RWUsTXQuU2tpbGxzPVN0O2NsYXNzIFB0IGV4dGVuZHMgeWV7Y3JlYXRlKGUsdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lO3JldHVybiB0aGlzLl9jbGllbnQucG9zdCgiL3YxL2NvbXBsZXRlIix7Ym9keTpyLHRpbWVvdXQ6dGhpcy5fY2xpZW50Ll9vcHRpb25zLnRpbWVvdXQ/PzZlNSwuLi50LGhlYWRlcnM6X2UoW3suLi5udWxsIT1zPy50b1N0cmluZygpP3siYW50aHJvcGljLWJldGEiOnM/LnRvU3RyaW5nKCl9OnZvaWQgMH0sdD8uaGVhZGVyc10pLHN0cmVhbTplLnN0cmVhbT8/ITF9KX19dmFyIEV0LFJ0LHh0LFR0LEF0LEN0LEl0LE90LCR0LEx0LE50LER0LFV0LHF0LGp0LEZ0LFd0LEJ0LEp0LHp0LEh0LEt0O2NvbnN0IFZ0PSJfX2pzb25fYnVmIjtmdW5jdGlvbiBYdChlKXtyZXR1cm4idG9vbF91c2UiPT09ZS50eXBlfHwic2VydmVyX3Rvb2xfdXNlIj09PWUudHlwZX1jbGFzcyBHdHtjb25zdHJ1Y3Rvcigpe0V0LmFkZCh0aGlzKSx0aGlzLm1lc3NhZ2VzPVtdLHRoaXMucmVjZWl2ZWRNZXNzYWdlcz1bXSxSdC5zZXQodGhpcyx2b2lkIDApLHRoaXMuY29udHJvbGxlcj1uZXcgQWJvcnRDb250cm9sbGVyLHh0LnNldCh0aGlzLHZvaWQgMCksVHQuc2V0KHRoaXMsKCk9Pnt9KSxBdC5zZXQodGhpcywoKT0+e30pLEN0LnNldCh0aGlzLHZvaWQgMCksSXQuc2V0KHRoaXMsKCk9Pnt9KSxPdC5zZXQodGhpcywoKT0+e30pLCR0LnNldCh0aGlzLHt9KSxMdC5zZXQodGhpcywhMSksTnQuc2V0KHRoaXMsITEpLER0LnNldCh0aGlzLCExKSxVdC5zZXQodGhpcywhMSkscXQuc2V0KHRoaXMsdm9pZCAwKSxqdC5zZXQodGhpcyx2b2lkIDApLEJ0LnNldCh0aGlzLGU9PntpZih0KHRoaXMsTnQsITAsImYiKSxuKGUpJiYoZT1uZXcgYyksZSBpbnN0YW5jZW9mIGMpcmV0dXJuIHQodGhpcyxEdCwhMCwiZiIpLHRoaXMuX2VtaXQoImFib3J0IixlKTtpZihlIGluc3RhbmNlb2YgbylyZXR1cm4gdGhpcy5fZW1pdCgiZXJyb3IiLGUpO2lmKGUgaW5zdGFuY2VvZiBFcnJvcil7Y29uc3QgdD1uZXcgbyhlLm1lc3NhZ2UpO3JldHVybiB0LmNhdXNlPWUsdGhpcy5fZW1pdCgiZXJyb3IiLHQpfXJldHVybiB0aGlzLl9lbWl0KCJlcnJvciIsbmV3IG8oU3RyaW5nKGUpKSl9KSx0KHRoaXMseHQsbmV3IFByb21pc2UoKGUscyk9Pnt0KHRoaXMsVHQsZSwiZiIpLHQodGhpcyxBdCxzLCJmIil9KSwiZiIpLHQodGhpcyxDdCxuZXcgUHJvbWlzZSgoZSxzKT0+e3QodGhpcyxJdCxlLCJmIiksdCh0aGlzLE90LHMsImYiKX0pLCJmIikscyh0aGlzLHh0LCJmIikuY2F0Y2goKCk9Pnt9KSxzKHRoaXMsQ3QsImYiKS5jYXRjaCgoKT0+e30pfWdldCByZXNwb25zZSgpe3JldHVybiBzKHRoaXMscXQsImYiKX1nZXQgcmVxdWVzdF9pZCgpe3JldHVybiBzKHRoaXMsanQsImYiKX1hc3luYyB3aXRoUmVzcG9uc2UoKXtjb25zdCBlPWF3YWl0IHModGhpcyx4dCwiZiIpO2lmKCFlKXRocm93IG5ldyBFcnJvcigiQ291bGQgbm90IHJlc29sdmUgYSBgUmVzcG9uc2VgIG9iamVjdCIpO3JldHVybntkYXRhOnRoaXMscmVzcG9uc2U6ZSxyZXF1ZXN0X2lkOmUuaGVhZGVycy5nZXQoInJlcXVlc3QtaWQiKX19c3RhdGljIGZyb21SZWFkYWJsZVN0cmVhbShlKXtjb25zdCB0PW5ldyBHdDtyZXR1cm4gdC5fcnVuKCgpPT50Ll9mcm9tUmVhZGFibGVTdHJlYW0oZSkpLHR9c3RhdGljIGNyZWF0ZU1lc3NhZ2UoZSx0LHMpe2NvbnN0IHI9bmV3IEd0O2Zvcihjb25zdCBlIG9mIHQubWVzc2FnZXMpci5fYWRkTWVzc2FnZVBhcmFtKGUpO3JldHVybiByLl9ydW4oKCk9PnIuX2NyZWF0ZU1lc3NhZ2UoZSx7Li4udCxzdHJlYW06ITB9LHsuLi5zLGhlYWRlcnM6ey4uLnM/LmhlYWRlcnMsIlgtU3RhaW5sZXNzLUhlbHBlci1NZXRob2QiOiJzdHJlYW0ifX0pKSxyfV9ydW4oZSl7ZSgpLnRoZW4oKCk9Pnt0aGlzLl9lbWl0RmluYWwoKSx0aGlzLl9lbWl0KCJlbmQiKX0scyh0aGlzLEJ0LCJmIikpfV9hZGRNZXNzYWdlUGFyYW0oZSl7dGhpcy5tZXNzYWdlcy5wdXNoKGUpfV9hZGRNZXNzYWdlKGUsdD0hMCl7dGhpcy5yZWNlaXZlZE1lc3NhZ2VzLnB1c2goZSksdCYmdGhpcy5fZW1pdCgibWVzc2FnZSIsZSl9YXN5bmMgX2NyZWF0ZU1lc3NhZ2UoZSx0LHIpe2NvbnN0IG49cj8uc2lnbmFsO2xldCBhO24mJihuLmFib3J0ZWQmJnRoaXMuY29udHJvbGxlci5hYm9ydCgpLGE9dGhpcy5jb250cm9sbGVyLmFib3J0LmJpbmQodGhpcy5jb250cm9sbGVyKSxuLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IixhKSk7dHJ5e3ModGhpcyxFdCwibSIsSnQpLmNhbGwodGhpcyk7Y29uc3R7cmVzcG9uc2U6bixkYXRhOmF9PWF3YWl0IGUuY3JlYXRlKHsuLi50LHN0cmVhbTohMH0sey4uLnIsc2lnbmFsOnRoaXMuY29udHJvbGxlci5zaWduYWx9KS53aXRoUmVzcG9uc2UoKTt0aGlzLl9jb25uZWN0ZWQobik7Zm9yIGF3YWl0KGNvbnN0IGUgb2YgYSlzKHRoaXMsRXQsIm0iLHp0KS5jYWxsKHRoaXMsZSk7aWYoYS5jb250cm9sbGVyLnNpZ25hbD8uYWJvcnRlZCl0aHJvdyBuZXcgYztzKHRoaXMsRXQsIm0iLEh0KS5jYWxsKHRoaXMpfWZpbmFsbHl7biYmYSYmbi5yZW1vdmVFdmVudExpc3RlbmVyKCJhYm9ydCIsYSl9fV9jb25uZWN0ZWQoZSl7dGhpcy5lbmRlZHx8KHQodGhpcyxxdCxlLCJmIiksdCh0aGlzLGp0LGU/LmhlYWRlcnMuZ2V0KCJyZXF1ZXN0LWlkIiksImYiKSxzKHRoaXMsVHQsImYiKS5jYWxsKHRoaXMsZSksdGhpcy5fZW1pdCgiY29ubmVjdCIpKX1nZXQgZW5kZWQoKXtyZXR1cm4gcyh0aGlzLEx0LCJmIil9Z2V0IGVycm9yZWQoKXtyZXR1cm4gcyh0aGlzLE50LCJmIil9Z2V0IGFib3J0ZWQoKXtyZXR1cm4gcyh0aGlzLER0LCJmIil9YWJvcnQoKXt0aGlzLmNvbnRyb2xsZXIuYWJvcnQoKX1vbihlLHQpe3JldHVybihzKHRoaXMsJHQsImYiKVtlXXx8KHModGhpcywkdCwiZiIpW2VdPVtdKSkucHVzaCh7bGlzdGVuZXI6dH0pLHRoaXN9b2ZmKGUsdCl7Y29uc3Qgcj1zKHRoaXMsJHQsImYiKVtlXTtpZighcilyZXR1cm4gdGhpcztjb25zdCBuPXIuZmluZEluZGV4KGU9PmUubGlzdGVuZXI9PT10KTtyZXR1cm4gbj49MCYmci5zcGxpY2UobiwxKSx0aGlzfW9uY2UoZSx0KXtyZXR1cm4ocyh0aGlzLCR0LCJmIilbZV18fChzKHRoaXMsJHQsImYiKVtlXT1bXSkpLnB1c2goe2xpc3RlbmVyOnQsb25jZTohMH0pLHRoaXN9ZW1pdHRlZChlKXtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pnt0KHRoaXMsVXQsITAsImYiKSwiZXJyb3IiIT09ZSYmdGhpcy5vbmNlKCJlcnJvciIsciksdGhpcy5vbmNlKGUscyl9KX1hc3luYyBkb25lKCl7dCh0aGlzLFV0LCEwLCJmIiksYXdhaXQgcyh0aGlzLEN0LCJmIil9Z2V0IGN1cnJlbnRNZXNzYWdlKCl7cmV0dXJuIHModGhpcyxSdCwiZiIpfWFzeW5jIGZpbmFsTWVzc2FnZSgpe3JldHVybiBhd2FpdCB0aGlzLmRvbmUoKSxzKHRoaXMsRXQsIm0iLEZ0KS5jYWxsKHRoaXMpfWFzeW5jIGZpbmFsVGV4dCgpe3JldHVybiBhd2FpdCB0aGlzLmRvbmUoKSxzKHRoaXMsRXQsIm0iLFd0KS5jYWxsKHRoaXMpfV9lbWl0KGUsLi4ucil7aWYocyh0aGlzLEx0LCJmIikpcmV0dXJuOyJlbmQiPT09ZSYmKHQodGhpcyxMdCwhMCwiZiIpLHModGhpcyxJdCwiZiIpLmNhbGwodGhpcykpO2NvbnN0IG49cyh0aGlzLCR0LCJmIilbZV07aWYobiYmKHModGhpcywkdCwiZiIpW2VdPW4uZmlsdGVyKGU9PiFlLm9uY2UpLG4uZm9yRWFjaCgoe2xpc3RlbmVyOmV9KT0+ZSguLi5yKSkpLCJhYm9ydCI9PT1lKXtjb25zdCBlPXJbMF07cmV0dXJuIHModGhpcyxVdCwiZiIpfHxuPy5sZW5ndGh8fFByb21pc2UucmVqZWN0KGUpLHModGhpcyxBdCwiZiIpLmNhbGwodGhpcyxlKSxzKHRoaXMsT3QsImYiKS5jYWxsKHRoaXMsZSksdm9pZCB0aGlzLl9lbWl0KCJlbmQiKX1pZigiZXJyb3IiPT09ZSl7Y29uc3QgZT1yWzBdO3ModGhpcyxVdCwiZiIpfHxuPy5sZW5ndGh8fFByb21pc2UucmVqZWN0KGUpLHModGhpcyxBdCwiZiIpLmNhbGwodGhpcyxlKSxzKHRoaXMsT3QsImYiKS5jYWxsKHRoaXMsZSksdGhpcy5fZW1pdCgiZW5kIil9fV9lbWl0RmluYWwoKXt0aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpJiZ0aGlzLl9lbWl0KCJmaW5hbE1lc3NhZ2UiLHModGhpcyxFdCwibSIsRnQpLmNhbGwodGhpcykpfWFzeW5jIF9mcm9tUmVhZGFibGVTdHJlYW0oZSx0KXtjb25zdCByPXQ/LnNpZ25hbDtsZXQgbjtyJiYoci5hYm9ydGVkJiZ0aGlzLmNvbnRyb2xsZXIuYWJvcnQoKSxuPXRoaXMuY29udHJvbGxlci5hYm9ydC5iaW5kKHRoaXMuY29udHJvbGxlciksci5hZGRFdmVudExpc3RlbmVyKCJhYm9ydCIsbikpO3RyeXtzKHRoaXMsRXQsIm0iLEp0KS5jYWxsKHRoaXMpLHRoaXMuX2Nvbm5lY3RlZChudWxsKTtjb25zdCB0PVouZnJvbVJlYWRhYmxlU3RyZWFtKGUsdGhpcy5jb250cm9sbGVyKTtmb3IgYXdhaXQoY29uc3QgZSBvZiB0KXModGhpcyxFdCwibSIsenQpLmNhbGwodGhpcyxlKTtpZih0LmNvbnRyb2xsZXIuc2lnbmFsPy5hYm9ydGVkKXRocm93IG5ldyBjO3ModGhpcyxFdCwibSIsSHQpLmNhbGwodGhpcyl9ZmluYWxseXtyJiZuJiZyLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0IixuKX19WyhSdD1uZXcgV2Vha01hcCx4dD1uZXcgV2Vha01hcCxUdD1uZXcgV2Vha01hcCxBdD1uZXcgV2Vha01hcCxDdD1uZXcgV2Vha01hcCxJdD1uZXcgV2Vha01hcCxPdD1uZXcgV2Vha01hcCwkdD1uZXcgV2Vha01hcCxMdD1uZXcgV2Vha01hcCxOdD1uZXcgV2Vha01hcCxEdD1uZXcgV2Vha01hcCxVdD1uZXcgV2Vha01hcCxxdD1uZXcgV2Vha01hcCxqdD1uZXcgV2Vha01hcCxCdD1uZXcgV2Vha01hcCxFdD1uZXcgV2Vha1NldCxGdD1mdW5jdGlvbigpe2lmKDA9PT10aGlzLnJlY2VpdmVkTWVzc2FnZXMubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBNZXNzYWdlIHdpdGggcm9sZT1hc3Npc3RhbnQiKTtyZXR1cm4gdGhpcy5yZWNlaXZlZE1lc3NhZ2VzLmF0KC0xKX0sV3Q9ZnVuY3Rpb24oKXtpZigwPT09dGhpcy5yZWNlaXZlZE1lc3NhZ2VzLmxlbmd0aCl0aHJvdyBuZXcgbygic3RyZWFtIGVuZGVkIHdpdGhvdXQgcHJvZHVjaW5nIGEgTWVzc2FnZSB3aXRoIHJvbGU9YXNzaXN0YW50Iik7Y29uc3QgZT10aGlzLnJlY2VpdmVkTWVzc2FnZXMuYXQoLTEpLmNvbnRlbnQuZmlsdGVyKGU9PiJ0ZXh0Ij09PWUudHlwZSkubWFwKGU9PmUudGV4dCk7aWYoMD09PWUubGVuZ3RoKXRocm93IG5ldyBvKCJzdHJlYW0gZW5kZWQgd2l0aG91dCBwcm9kdWNpbmcgYSBjb250ZW50IGJsb2NrIHdpdGggdHlwZT10ZXh0Iik7cmV0dXJuIGUuam9pbigiICIpfSxKdD1mdW5jdGlvbigpe3RoaXMuZW5kZWR8fHQodGhpcyxSdCx2b2lkIDAsImYiKX0senQ9ZnVuY3Rpb24oZSl7aWYodGhpcy5lbmRlZClyZXR1cm47Y29uc3Qgcj1zKHRoaXMsRXQsIm0iLEt0KS5jYWxsKHRoaXMsZSk7c3dpdGNoKHRoaXMuX2VtaXQoInN0cmVhbUV2ZW50IixlLHIpLGUudHlwZSl7Y2FzZSJjb250ZW50X2Jsb2NrX2RlbHRhIjp7Y29uc3QgdD1yLmNvbnRlbnQuYXQoLTEpO3N3aXRjaChlLmRlbHRhLnR5cGUpe2Nhc2UidGV4dF9kZWx0YSI6InRleHQiPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJ0ZXh0IixlLmRlbHRhLnRleHQsdC50ZXh0fHwiIik7YnJlYWs7Y2FzZSJjaXRhdGlvbnNfZGVsdGEiOiJ0ZXh0Ij09PXQudHlwZSYmdGhpcy5fZW1pdCgiY2l0YXRpb24iLGUuZGVsdGEuY2l0YXRpb24sdC5jaXRhdGlvbnM/P1tdKTticmVhaztjYXNlImlucHV0X2pzb25fZGVsdGEiOlh0KHQpJiZ0LmlucHV0JiZ0aGlzLl9lbWl0KCJpbnB1dEpzb24iLGUuZGVsdGEucGFydGlhbF9qc29uLHQuaW5wdXQpO2JyZWFrO2Nhc2UidGhpbmtpbmdfZGVsdGEiOiJ0aGlua2luZyI9PT10LnR5cGUmJnRoaXMuX2VtaXQoInRoaW5raW5nIixlLmRlbHRhLnRoaW5raW5nLHQudGhpbmtpbmcpO2JyZWFrO2Nhc2Uic2lnbmF0dXJlX2RlbHRhIjoidGhpbmtpbmciPT09dC50eXBlJiZ0aGlzLl9lbWl0KCJzaWduYXR1cmUiLHQuc2lnbmF0dXJlKTticmVhaztkZWZhdWx0OmUuZGVsdGF9YnJlYWt9Y2FzZSJtZXNzYWdlX3N0b3AiOnRoaXMuX2FkZE1lc3NhZ2VQYXJhbShyKSx0aGlzLl9hZGRNZXNzYWdlKHIsITApO2JyZWFrO2Nhc2UiY29udGVudF9ibG9ja19zdG9wIjp0aGlzLl9lbWl0KCJjb250ZW50QmxvY2siLHIuY29udGVudC5hdCgtMSkpO2JyZWFrO2Nhc2UibWVzc2FnZV9zdGFydCI6dCh0aGlzLFJ0LHIsImYiKX19LEh0PWZ1bmN0aW9uKCl7aWYodGhpcy5lbmRlZCl0aHJvdyBuZXcgbygic3RyZWFtIGhhcyBlbmRlZCwgdGhpcyBzaG91bGRuJ3QgaGFwcGVuIik7Y29uc3QgZT1zKHRoaXMsUnQsImYiKTtpZighZSl0aHJvdyBuZXcgbygicmVxdWVzdCBlbmRlZCB3aXRob3V0IHNlbmRpbmcgYW55IGNodW5rcyIpO3JldHVybiB0KHRoaXMsUnQsdm9pZCAwLCJmIiksZX0sS3Q9ZnVuY3Rpb24oZSl7bGV0IHQ9cyh0aGlzLFJ0LCJmIik7aWYoIm1lc3NhZ2Vfc3RhcnQiPT09ZS50eXBlKXtpZih0KXRocm93IG5ldyBvKGBVbmV4cGVjdGVkIGV2ZW50IG9yZGVyLCBnb3QgJHtlLnR5cGV9IGJlZm9yZSByZWNlaXZpbmcgIm1lc3NhZ2Vfc3RvcCJgKTtyZXR1cm4gZS5tZXNzYWdlfWlmKCF0KXRocm93IG5ldyBvKGBVbmV4cGVjdGVkIGV2ZW50IG9yZGVyLCBnb3QgJHtlLnR5cGV9IGJlZm9yZSAibWVzc2FnZV9zdGFydCJgKTtzd2l0Y2goZS50eXBlKXtjYXNlIm1lc3NhZ2Vfc3RvcCI6Y2FzZSJjb250ZW50X2Jsb2NrX3N0b3AiOnJldHVybiB0O2Nhc2UibWVzc2FnZV9kZWx0YSI6cmV0dXJuIHQuc3RvcF9yZWFzb249ZS5kZWx0YS5zdG9wX3JlYXNvbix0LnN0b3Bfc2VxdWVuY2U9ZS5kZWx0YS5zdG9wX3NlcXVlbmNlLHQudXNhZ2Uub3V0cHV0X3Rva2Vucz1lLnVzYWdlLm91dHB1dF90b2tlbnMsbnVsbCE9ZS51c2FnZS5pbnB1dF90b2tlbnMmJih0LnVzYWdlLmlucHV0X3Rva2Vucz1lLnVzYWdlLmlucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMmJih0LnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2Vucz1lLnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyYmKHQudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM9ZS51c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyksbnVsbCE9ZS51c2FnZS5zZXJ2ZXJfdG9vbF91c2UmJih0LnVzYWdlLnNlcnZlcl90b29sX3VzZT1lLnVzYWdlLnNlcnZlcl90b29sX3VzZSksdDtjYXNlImNvbnRlbnRfYmxvY2tfc3RhcnQiOnJldHVybiB0LmNvbnRlbnQucHVzaCh7Li4uZS5jb250ZW50X2Jsb2NrfSksdDtjYXNlImNvbnRlbnRfYmxvY2tfZGVsdGEiOntjb25zdCBzPXQuY29udGVudC5hdChlLmluZGV4KTtzd2l0Y2goZS5kZWx0YS50eXBlKXtjYXNlInRleHRfZGVsdGEiOiJ0ZXh0Ij09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsdGV4dDoocy50ZXh0fHwiIikrZS5kZWx0YS50ZXh0fSk7YnJlYWs7Y2FzZSJjaXRhdGlvbnNfZGVsdGEiOiJ0ZXh0Ij09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsY2l0YXRpb25zOlsuLi5zLmNpdGF0aW9ucz8/W10sZS5kZWx0YS5jaXRhdGlvbl19KTticmVhaztjYXNlImlucHV0X2pzb25fZGVsdGEiOmlmKHMmJlh0KHMpKXtsZXQgcj1zW1Z0XXx8IiI7cis9ZS5kZWx0YS5wYXJ0aWFsX2pzb247Y29uc3Qgbj17Li4uc307T2JqZWN0LmRlZmluZVByb3BlcnR5KG4sVnQse3ZhbHVlOnIsZW51bWVyYWJsZTohMSx3cml0YWJsZTohMH0pLHImJihuLmlucHV0PUllKHIpKSx0LmNvbnRlbnRbZS5pbmRleF09bn1icmVhaztjYXNlInRoaW5raW5nX2RlbHRhIjoidGhpbmtpbmciPT09cz8udHlwZSYmKHQuY29udGVudFtlLmluZGV4XT17Li4ucyx0aGlua2luZzpzLnRoaW5raW5nK2UuZGVsdGEudGhpbmtpbmd9KTticmVhaztjYXNlInNpZ25hdHVyZV9kZWx0YSI6InRoaW5raW5nIj09PXM/LnR5cGUmJih0LmNvbnRlbnRbZS5pbmRleF09ey4uLnMsc2lnbmF0dXJlOmUuZGVsdGEuc2lnbmF0dXJlfSk7YnJlYWs7ZGVmYXVsdDplLmRlbHRhfXJldHVybiB0fX19LFN5bWJvbC5hc3luY0l0ZXJhdG9yKV0oKXtjb25zdCBlPVtdLHQ9W107bGV0IHM9ITE7cmV0dXJuIHRoaXMub24oInN0cmVhbUV2ZW50IixzPT57Y29uc3Qgcj10LnNoaWZ0KCk7cj9yLnJlc29sdmUocyk6ZS5wdXNoKHMpfSksdGhpcy5vbigiZW5kIiwoKT0+e3M9ITA7Zm9yKGNvbnN0IGUgb2YgdCllLnJlc29sdmUodm9pZCAwKTt0Lmxlbmd0aD0wfSksdGhpcy5vbigiYWJvcnQiLGU9PntzPSEwO2Zvcihjb25zdCBzIG9mIHQpcy5yZWplY3QoZSk7dC5sZW5ndGg9MH0pLHRoaXMub24oImVycm9yIixlPT57cz0hMDtmb3IoY29uc3QgcyBvZiB0KXMucmVqZWN0KGUpO3QubGVuZ3RoPTB9KSx7bmV4dDphc3luYygpPT5lLmxlbmd0aD97dmFsdWU6ZS5zaGlmdCgpLGRvbmU6ITF9OnM/e3ZhbHVlOnZvaWQgMCxkb25lOiEwfTpuZXcgUHJvbWlzZSgoZSxzKT0+dC5wdXNoKHtyZXNvbHZlOmUscmVqZWN0OnN9KSkudGhlbihlPT5lP3t2YWx1ZTplLGRvbmU6ITF9Ont2YWx1ZTp2b2lkIDAsZG9uZTohMH0pLHJldHVybjphc3luYygpPT4odGhpcy5hYm9ydCgpLHt2YWx1ZTp2b2lkIDAsZG9uZTohMH0pfX10b1JlYWRhYmxlU3RyZWFtKCl7cmV0dXJuIG5ldyBaKHRoaXNbU3ltYm9sLmFzeW5jSXRlcmF0b3JdLmJpbmQodGhpcyksdGhpcy5jb250cm9sbGVyKS50b1JlYWRhYmxlU3RyZWFtKCl9fWNsYXNzIFl0IGV4dGVuZHMgeWV7Y3JlYXRlKGUsdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMvYmF0Y2hlcyIse2JvZHk6ZSwuLi50fSl9cmV0cmlldmUoZSx0KXtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9YCx0KX1saXN0KGU9e30sdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5nZXRBUElMaXN0KCIvdjEvbWVzc2FnZXMvYmF0Y2hlcyIsb2Use3F1ZXJ5OmUsLi4udH0pfWRlbGV0ZShlLHQpe3JldHVybiB0aGlzLl9jbGllbnQuZGVsZXRlKFBlYC92MS9tZXNzYWdlcy9iYXRjaGVzLyR7ZX1gLHQpfWNhbmNlbChlLHQpe3JldHVybiB0aGlzLl9jbGllbnQucG9zdChQZWAvdjEvbWVzc2FnZXMvYmF0Y2hlcy8ke2V9L2NhbmNlbGAsdCl9YXN5bmMgcmVzdWx0cyhlLHQpe2NvbnN0IHM9YXdhaXQgdGhpcy5yZXRyaWV2ZShlKTtpZighcy5yZXN1bHRzX3VybCl0aHJvdyBuZXcgbyhgTm8gYmF0Y2ggXGByZXN1bHRzX3VybFxgOyBIYXMgaXQgZmluaXNoZWQgcHJvY2Vzc2luZz8gJHtzLnByb2Nlc3Npbmdfc3RhdHVzfSAtICR7cy5pZH1gKTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldChzLnJlc3VsdHNfdXJsLHsuLi50LGhlYWRlcnM6X2UoW3tBY2NlcHQ6ImFwcGxpY2F0aW9uL2JpbmFyeSJ9LHQ/LmhlYWRlcnNdKSxzdHJlYW06ITAsX19iaW5hcnlSZXNwb25zZTohMH0pLl90aGVuVW53cmFwKChlLHQpPT55dC5mcm9tUmVzcG9uc2UodC5yZXNwb25zZSx0LmNvbnRyb2xsZXIpKX19Y2xhc3MgUXQgZXh0ZW5kcyB5ZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5iYXRjaGVzPW5ldyBZdCh0aGlzLl9jbGllbnQpfWNyZWF0ZShlLHQpe2UubW9kZWwgaW4gWnQmJmNvbnNvbGUud2FybihgVGhlIG1vZGVsICcke2UubW9kZWx9JyBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIHJlYWNoIGVuZC1vZi1saWZlIG9uICR7WnRbZS5tb2RlbF19XG5QbGVhc2UgbWlncmF0ZSB0byBhIG5ld2VyIG1vZGVsLiBWaXNpdCBodHRwczovL2RvY3MuYW50aHJvcGljLmNvbS9lbi9kb2NzL3Jlc291cmNlcy9tb2RlbC1kZXByZWNhdGlvbnMgZm9yIG1vcmUgaW5mb3JtYXRpb24uYCk7bGV0IHM9dGhpcy5fY2xpZW50Ll9vcHRpb25zLnRpbWVvdXQ7aWYoIWUuc3RyZWFtJiZudWxsPT1zKXtjb25zdCB0PXhlW2UubW9kZWxdPz92b2lkIDA7cz10aGlzLl9jbGllbnQuY2FsY3VsYXRlTm9uc3RyZWFtaW5nVGltZW91dChlLm1heF90b2tlbnMsdCl9cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMiLHtib2R5OmUsdGltZW91dDpzPz82ZTUsLi4udCxzdHJlYW06ZS5zdHJlYW0/PyExfSl9c3RyZWFtKGUsdCl7cmV0dXJuIEd0LmNyZWF0ZU1lc3NhZ2UodGhpcyxlLHQpfWNvdW50VG9rZW5zKGUsdCl7cmV0dXJuIHRoaXMuX2NsaWVudC5wb3N0KCIvdjEvbWVzc2FnZXMvY291bnRfdG9rZW5zIix7Ym9keTplLC4uLnR9KX19Y29uc3QgWnQ9eyJjbGF1ZGUtMS4zIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLTEuMy0xMDBrIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLWluc3RhbnQtMS4xIjoiTm92ZW1iZXIgNnRoLCAyMDI0IiwiY2xhdWRlLWluc3RhbnQtMS4xLTEwMGsiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtaW5zdGFudC0xLjIiOiJOb3ZlbWJlciA2dGgsIDIwMjQiLCJjbGF1ZGUtMy1zb25uZXQtMjAyNDAyMjkiOiJKdWx5IDIxc3QsIDIwMjUiLCJjbGF1ZGUtMy1vcHVzLTIwMjQwMjI5IjoiSmFudWFyeSA1dGgsIDIwMjYiLCJjbGF1ZGUtMi4xIjoiSnVseSAyMXN0LCAyMDI1IiwiY2xhdWRlLTIuMCI6Ikp1bHkgMjFzdCwgMjAyNSIsImNsYXVkZS0zLTctc29ubmV0LWxhdGVzdCI6IkZlYnJ1YXJ5IDE5dGgsIDIwMjYiLCJjbGF1ZGUtMy03LXNvbm5ldC0yMDI1MDIxOSI6IkZlYnJ1YXJ5IDE5dGgsIDIwMjYifTtRdC5CYXRjaGVzPVl0O2NsYXNzIGVzIGV4dGVuZHMgeWV7cmV0cmlldmUoZSx0PXt9LHMpe2NvbnN0e2JldGFzOnJ9PXQ/P3t9O3JldHVybiB0aGlzLl9jbGllbnQuZ2V0KFBlYC92MS9tb2RlbHMvJHtlfWAsey4uLnMsaGVhZGVyczpfZShbey4uLm51bGwhPXI/LnRvU3RyaW5nKCk/eyJhbnRocm9waWMtYmV0YSI6cj8udG9TdHJpbmcoKX06dm9pZCAwfSxzPy5oZWFkZXJzXSl9KX1saXN0KGU9e30sdCl7Y29uc3R7YmV0YXM6cywuLi5yfT1lPz97fTtyZXR1cm4gdGhpcy5fY2xpZW50LmdldEFQSUxpc3QoIi92MS9tb2RlbHMiLG9lLHtxdWVyeTpyLC4uLnQsaGVhZGVyczpfZShbey4uLm51bGwhPXM/LnRvU3RyaW5nKCk/eyJhbnRocm9waWMtYmV0YSI6cz8udG9TdHJpbmcoKX06dm9pZCAwfSx0Py5oZWFkZXJzXSl9KX19Y29uc3QgdHM9ZT0+dm9pZCAwIT09Z2xvYmFsVGhpcy5wcm9jZXNzP2dsb2JhbFRoaXMucHJvY2Vzcy5lbnY/LltlXT8udHJpbSgpPz92b2lkIDA6dm9pZCAwIT09Z2xvYmFsVGhpcy5EZW5vP2dsb2JhbFRoaXMuRGVuby5lbnY/LmdldD8uKGUpPy50cmltKCk6dm9pZCAwO3ZhciBzcyxycyxucyxhcyxvcyxpcztjbGFzcyBjc3tjb25zdHJ1Y3Rvcih7YmFzZVVSTDplPXRzKCJBTlRIUk9QSUNfQkFTRV9VUkwiKSxhcGlLZXk6cz10cygiQU5USFJPUElDX0FQSV9LRVkiKT8/bnVsbCxhdXRoVG9rZW46cj10cygiQU5USFJPUElDX0FVVEhfVE9LRU4iKT8/bnVsbCwuLi5ufT17fSl7c3MuYWRkKHRoaXMpLG5zLnNldCh0aGlzLHZvaWQgMCk7Y29uc3QgYT17YXBpS2V5OnMsYXV0aFRva2VuOnIsLi4ubixiYXNlVVJMOmV8fCJodHRwczovL2FwaS5hbnRocm9waWMuY29tIn07aWYoIWEuZGFuZ2Vyb3VzbHlBbGxvd0Jyb3dzZXImJiJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiZ2b2lkIDAhPT13aW5kb3cuZG9jdW1lbnQmJiJ1bmRlZmluZWQiIT10eXBlb2YgbmF2aWdhdG9yKXRocm93IG5ldyBvKCJJdCBsb29rcyBsaWtlIHlvdSdyZSBydW5uaW5nIGluIGEgYnJvd3Nlci1saWtlIGVudmlyb25tZW50LlxuXG5UaGlzIGlzIGRpc2FibGVkIGJ5IGRlZmF1bHQsIGFzIGl0IHJpc2tzIGV4cG9zaW5nIHlvdXIgc2VjcmV0IEFQSSBjcmVkZW50aWFscyB0byBhdHRhY2tlcnMuXG5JZiB5b3UgdW5kZXJzdGFuZCB0aGUgcmlza3MgYW5kIGhhdmUgYXBwcm9wcmlhdGUgbWl0aWdhdGlvbnMgaW4gcGxhY2UsXG55b3UgY2FuIHNldCB0aGUgYGRhbmdlcm91c2x5QWxsb3dCcm93c2VyYCBvcHRpb24gdG8gYHRydWVgLCBlLmcuLFxuXG5uZXcgQW50aHJvcGljKHsgYXBpS2V5LCBkYW5nZXJvdXNseUFsbG93QnJvd3NlcjogdHJ1ZSB9KTtcbiIpO3RoaXMuYmFzZVVSTD1hLmJhc2VVUkwsdGhpcy50aW1lb3V0PWEudGltZW91dD8/cnMuREVGQVVMVF9USU1FT1VULHRoaXMubG9nZ2VyPWEubG9nZ2VyPz9jb25zb2xlO2NvbnN0IGk9Indhcm4iO3RoaXMubG9nTGV2ZWw9aSx0aGlzLmxvZ0xldmVsPUIoYS5sb2dMZXZlbCwiQ2xpZW50T3B0aW9ucy5sb2dMZXZlbCIsdGhpcyk/P0IodHMoIkFOVEhST1BJQ19MT0ciKSwicHJvY2Vzcy5lbnZbJ0FOVEhST1BJQ19MT0cnXSIsdGhpcyk/P2ksdGhpcy5mZXRjaE9wdGlvbnM9YS5mZXRjaE9wdGlvbnMsdGhpcy5tYXhSZXRyaWVzPWEubWF4UmV0cmllcz8/Mix0aGlzLmZldGNoPWEuZmV0Y2g/P2Z1bmN0aW9uKCl7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBmZXRjaClyZXR1cm4gZmV0Y2g7dGhyb3cgbmV3IEVycm9yKCJgZmV0Y2hgIGlzIG5vdCBkZWZpbmVkIGFzIGEgZ2xvYmFsOyBFaXRoZXIgcGFzcyBgZmV0Y2hgIHRvIHRoZSBjbGllbnQsIGBuZXcgQW50aHJvcGljKHsgZmV0Y2ggfSlgIG9yIHBvbHlmaWxsIHRoZSBnbG9iYWwsIGBnbG9iYWxUaGlzLmZldGNoID0gZmV0Y2hgIil9KCksdCh0aGlzLG5zLEksImYiKSx0aGlzLl9vcHRpb25zPWEsdGhpcy5hcGlLZXk9InN0cmluZyI9PXR5cGVvZiBzP3M6bnVsbCx0aGlzLmF1dGhUb2tlbj1yfXdpdGhPcHRpb25zKGUpe3JldHVybiBuZXcgdGhpcy5jb25zdHJ1Y3Rvcih7Li4udGhpcy5fb3B0aW9ucyxiYXNlVVJMOnRoaXMuYmFzZVVSTCxtYXhSZXRyaWVzOnRoaXMubWF4UmV0cmllcyx0aW1lb3V0OnRoaXMudGltZW91dCxsb2dnZXI6dGhpcy5sb2dnZXIsbG9nTGV2ZWw6dGhpcy5sb2dMZXZlbCxmZXRjaDp0aGlzLmZldGNoLGZldGNoT3B0aW9uczp0aGlzLmZldGNoT3B0aW9ucyxhcGlLZXk6dGhpcy5hcGlLZXksYXV0aFRva2VuOnRoaXMuYXV0aFRva2VuLC4uLmV9KX1kZWZhdWx0UXVlcnkoKXtyZXR1cm4gdGhpcy5fb3B0aW9ucy5kZWZhdWx0UXVlcnl9dmFsaWRhdGVIZWFkZXJzKHt2YWx1ZXM6ZSxudWxsczp0fSl7aWYoIWUuZ2V0KCJ4LWFwaS1rZXkiKSYmIWUuZ2V0KCJhdXRob3JpemF0aW9uIikmJiEodGhpcy5hcGlLZXkmJmUuZ2V0KCJ4LWFwaS1rZXkiKXx8dC5oYXMoIngtYXBpLWtleSIpfHx0aGlzLmF1dGhUb2tlbiYmZS5nZXQoImF1dGhvcml6YXRpb24iKXx8dC5oYXMoImF1dGhvcml6YXRpb24iKSkpdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgcmVzb2x2ZSBhdXRoZW50aWNhdGlvbiBtZXRob2QuIEV4cGVjdGVkIGVpdGhlciBhcGlLZXkgb3IgYXV0aFRva2VuIHRvIGJlIHNldC4gT3IgZm9yIG9uZSBvZiB0aGUgIlgtQXBpLUtleSIgb3IgIkF1dGhvcml6YXRpb24iIGhlYWRlcnMgdG8gYmUgZXhwbGljaXRseSBvbWl0dGVkJyl9YXN5bmMgYXV0aEhlYWRlcnMoZSl7cmV0dXJuIF9lKFthd2FpdCB0aGlzLmFwaUtleUF1dGgoZSksYXdhaXQgdGhpcy5iZWFyZXJBdXRoKGUpXSl9YXN5bmMgYXBpS2V5QXV0aChlKXtpZihudWxsIT10aGlzLmFwaUtleSlyZXR1cm4gX2UoW3siWC1BcGktS2V5Ijp0aGlzLmFwaUtleX1dKX1hc3luYyBiZWFyZXJBdXRoKGUpe2lmKG51bGwhPXRoaXMuYXV0aFRva2VuKXJldHVybiBfZShbe0F1dGhvcml6YXRpb246YEJlYXJlciAke3RoaXMuYXV0aFRva2VufWB9XSl9c3RyaW5naWZ5UXVlcnkoZSl7cmV0dXJuIE9iamVjdC5lbnRyaWVzKGUpLmZpbHRlcigoW2UsdF0pPT52b2lkIDAhPT10KS5tYXAoKFtlLHRdKT0+e2lmKCJzdHJpbmciPT10eXBlb2YgdHx8Im51bWJlciI9PXR5cGVvZiB0fHwiYm9vbGVhbiI9PXR5cGVvZiB0KXJldHVybmAke2VuY29kZVVSSUNvbXBvbmVudChlKX09JHtlbmNvZGVVUklDb21wb25lbnQodCl9YDtpZihudWxsPT09dClyZXR1cm5gJHtlbmNvZGVVUklDb21wb25lbnQoZSl9PWA7dGhyb3cgbmV3IG8oYENhbm5vdCBzdHJpbmdpZnkgdHlwZSAke3R5cGVvZiB0fTsgRXhwZWN0ZWQgc3RyaW5nLCBudW1iZXIsIGJvb2xlYW4sIG9yIG51bGwuIElmIHlvdSBuZWVkIHRvIHBhc3MgbmVzdGVkIHF1ZXJ5IHBhcmFtZXRlcnMsIHlvdSBjYW4gbWFudWFsbHkgZW5jb2RlIHRoZW0sIGUuZy4geyBxdWVyeTogeyAnZm9vW2tleTFdJzogdmFsdWUxLCAnZm9vW2tleTJdJzogdmFsdWUyIH0gfSwgYW5kIHBsZWFzZSBvcGVuIGEgR2l0SHViIGlzc3VlIHJlcXVlc3RpbmcgYmV0dGVyIHN1cHBvcnQgZm9yIHlvdXIgdXNlIGNhc2UuYCl9KS5qb2luKCImIil9Z2V0VXNlckFnZW50KCl7cmV0dXJuYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfS9KUyAke019YH1kZWZhdWx0SWRlbXBvdGVuY3lLZXkoKXtyZXR1cm5gc3RhaW5sZXNzLW5vZGUtcmV0cnktJHtyKCl9YH1tYWtlU3RhdHVzRXJyb3IoZSx0LHMscil7cmV0dXJuIGkuZ2VuZXJhdGUoZSx0LHMscil9YnVpbGRVUkwoZSx0LHIpe2NvbnN0IG49IXModGhpcyxzcywibSIsYXMpLmNhbGwodGhpcykmJnJ8fHRoaXMuYmFzZVVSTCxhPShlPT5iLnRlc3QoZSkpKGUpP25ldyBVUkwoZSk6bmV3IFVSTChuKyhuLmVuZHNXaXRoKCIvIikmJmUuc3RhcnRzV2l0aCgiLyIpP2Uuc2xpY2UoMSk6ZSkpLG89dGhpcy5kZWZhdWx0UXVlcnkoKTtyZXR1cm4gZnVuY3Rpb24oZSl7aWYoIWUpcmV0dXJuITA7Zm9yKGNvbnN0IHQgaW4gZSlyZXR1cm4hMTtyZXR1cm4hMH0obyl8fCh0PXsuLi5vLC4uLnR9KSwib2JqZWN0Ij09dHlwZW9mIHQmJnQmJiFBcnJheS5pc0FycmF5KHQpJiYoYS5zZWFyY2g9dGhpcy5zdHJpbmdpZnlRdWVyeSh0KSksYS50b1N0cmluZygpfV9jYWxjdWxhdGVOb25zdHJlYW1pbmdUaW1lb3V0KGUpe2lmKDM2MDAqZS8xMjhlMz42MDApdGhyb3cgbmV3IG8oIlN0cmVhbWluZyBpcyByZXF1aXJlZCBmb3Igb3BlcmF0aW9ucyB0aGF0IG1heSB0YWtlIGxvbmdlciB0aGFuIDEwIG1pbnV0ZXMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYW50aHJvcGljcy9hbnRocm9waWMtc2RrLXR5cGVzY3JpcHQjc3RyZWFtaW5nLXJlc3BvbnNlcyBmb3IgbW9yZSBkZXRhaWxzIik7cmV0dXJuIDZlNX1hc3luYyBwcmVwYXJlT3B0aW9ucyhlKXt9YXN5bmMgcHJlcGFyZVJlcXVlc3QoZSx7dXJsOnQsb3B0aW9uczpzfSl7fWdldChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoImdldCIsZSx0KX1wb3N0KGUsdCl7cmV0dXJuIHRoaXMubWV0aG9kUmVxdWVzdCgicG9zdCIsZSx0KX1wYXRjaChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoInBhdGNoIixlLHQpfXB1dChlLHQpe3JldHVybiB0aGlzLm1ldGhvZFJlcXVlc3QoInB1dCIsZSx0KX1kZWxldGUoZSx0KXtyZXR1cm4gdGhpcy5tZXRob2RSZXF1ZXN0KCJkZWxldGUiLGUsdCl9bWV0aG9kUmVxdWVzdChlLHQscyl7cmV0dXJuIHRoaXMucmVxdWVzdChQcm9taXNlLnJlc29sdmUocykudGhlbihzPT4oe21ldGhvZDplLHBhdGg6dCwuLi5zfSkpKX1yZXF1ZXN0KGUsdD1udWxsKXtyZXR1cm4gbmV3IHJlKHRoaXMsdGhpcy5tYWtlUmVxdWVzdChlLHQsdm9pZCAwKSl9YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe2NvbnN0IHI9YXdhaXQgZSxvPXIubWF4UmV0cmllcz8/dGhpcy5tYXhSZXRyaWVzO251bGw9PXQmJih0PW8pLGF3YWl0IHRoaXMucHJlcGFyZU9wdGlvbnMocik7Y29uc3R7cmVxOmksdXJsOmgsdGltZW91dDp1fT1hd2FpdCB0aGlzLmJ1aWxkUmVxdWVzdChyLHtyZXRyeUNvdW50Om8tdH0pO2F3YWl0IHRoaXMucHJlcGFyZVJlcXVlc3QoaSx7dXJsOmgsb3B0aW9uczpyfSk7Y29uc3QgcD0ibG9nXyIrKE1hdGgucmFuZG9tKCkqKDE8PDI0KXwwKS50b1N0cmluZygxNikucGFkU3RhcnQoNiwiMCIpLGY9dm9pZCAwPT09cz8iIjpgLCByZXRyeU9mOiAke3N9YCxtPURhdGUubm93KCk7aWYoVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIHNlbmRpbmcgcmVxdWVzdGAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpzLG1ldGhvZDpyLm1ldGhvZCx1cmw6aCxvcHRpb25zOnIsaGVhZGVyczppLmhlYWRlcnN9KSksci5zaWduYWw/LmFib3J0ZWQpdGhyb3cgbmV3IGM7Y29uc3QgZz1uZXcgQWJvcnRDb250cm9sbGVyLHc9YXdhaXQgdGhpcy5mZXRjaFdpdGhUaW1lb3V0KGgsaSx1LGcpLmNhdGNoKGEpLHk9RGF0ZS5ub3coKTtpZih3IGluc3RhbmNlb2YgZ2xvYmFsVGhpcy5FcnJvcil7Y29uc3QgZT1gcmV0cnlpbmcsICR7dH0gYXR0ZW1wdHMgcmVtYWluaW5nYDtpZihyLnNpZ25hbD8uYWJvcnRlZCl0aHJvdyBuZXcgYztjb25zdCBhPW4odyl8fC90aW1lZD8gP291dC9pLnRlc3QoU3RyaW5nKHcpKygiY2F1c2UiaW4gdz9TdHJpbmcody5jYXVzZSk6IiIpKTtpZih0KXJldHVybiBWKHRoaXMpLmluZm8oYFske3B9XSBjb25uZWN0aW9uICR7YT8idGltZWQgb3V0IjoiZmFpbGVkIn0gLSAke2V9YCksVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIGNvbm5lY3Rpb24gJHthPyJ0aW1lZCBvdXQiOiJmYWlsZWQifSAoJHtlfSlgLFgoe3JldHJ5T2ZSZXF1ZXN0TG9nSUQ6cyx1cmw6aCxkdXJhdGlvbk1zOnktbSxtZXNzYWdlOncubWVzc2FnZX0pKSx0aGlzLnJldHJ5UmVxdWVzdChyLHQscz8/cCk7aWYoVih0aGlzKS5pbmZvKGBbJHtwfV0gY29ubmVjdGlvbiAke2E/InRpbWVkIG91dCI6ImZhaWxlZCJ9IC0gZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0YCksVih0aGlzKS5kZWJ1ZyhgWyR7cH1dIGNvbm5lY3Rpb24gJHthPyJ0aW1lZCBvdXQiOiJmYWlsZWQifSAoZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0KWAsWCh7cmV0cnlPZlJlcXVlc3RMb2dJRDpzLHVybDpoLGR1cmF0aW9uTXM6eS1tLG1lc3NhZ2U6dy5tZXNzYWdlfSkpLGEpdGhyb3cgbmV3IGQ7dGhyb3cgbmV3IGwoe2NhdXNlOnd9KX1jb25zdCBiPWBbJHtwfSR7Zn0ke1suLi53LmhlYWRlcnMuZW50cmllcygpXS5maWx0ZXIoKFtlXSk9PiJyZXF1ZXN0LWlkIj09PWUpLm1hcCgoW2UsdF0pPT4iLCAiK2UrIjogIitKU09OLnN0cmluZ2lmeSh0KSkuam9pbigiIil9XSAke2kubWV0aG9kfSAke2h9ICR7dy5vaz8ic3VjY2VlZGVkIjoiZmFpbGVkIn0gd2l0aCBzdGF0dXMgJHt3LnN0YXR1c30gaW4gJHt5LW19bXNgO2lmKCF3Lm9rKXtjb25zdCBlPWF3YWl0IHRoaXMuc2hvdWxkUmV0cnkodyk7aWYodCYmZSl7Y29uc3QgZT1gcmV0cnlpbmcsICR7dH0gYXR0ZW1wdHMgcmVtYWluaW5nYDtyZXR1cm4gYXdhaXQgYXN5bmMgZnVuY3Rpb24oZSl7aWYobnVsbD09PWV8fCJvYmplY3QiIT10eXBlb2YgZSlyZXR1cm47aWYoZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0pcmV0dXJuIHZvaWQgYXdhaXQoZVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKS5yZXR1cm4/LigpKTtjb25zdCB0PWUuZ2V0UmVhZGVyKCkscz10LmNhbmNlbCgpO3QucmVsZWFzZUxvY2soKSxhd2FpdCBzfSh3LmJvZHkpLFYodGhpcykuaW5mbyhgJHtifSAtICR7ZX1gKSxWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2UgZXJyb3IgKCR7ZX0pYCxYKHtyZXRyeU9mUmVxdWVzdExvZ0lEOnMsdXJsOncudXJsLHN0YXR1czp3LnN0YXR1cyxoZWFkZXJzOncuaGVhZGVycyxkdXJhdGlvbk1zOnktbX0pKSx0aGlzLnJldHJ5UmVxdWVzdChyLHQscz8/cCx3LmhlYWRlcnMpfWNvbnN0IG49ZT8iZXJyb3I7IG5vIG1vcmUgcmV0cmllcyBsZWZ0IjoiZXJyb3I7IG5vdCByZXRyeWFibGUiO1YodGhpcykuaW5mbyhgJHtifSAtICR7bn1gKTtjb25zdCBvPWF3YWl0IHcudGV4dCgpLmNhdGNoKGU9PmEoZSkubWVzc2FnZSksaT1TKG8pLGM9aT92b2lkIDA6bzt0aHJvdyBWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2UgZXJyb3IgKCR7bn0pYCxYKHtyZXRyeU9mUmVxdWVzdExvZ0lEOnMsdXJsOncudXJsLHN0YXR1czp3LnN0YXR1cyxoZWFkZXJzOncuaGVhZGVycyxtZXNzYWdlOmMsZHVyYXRpb25NczpEYXRlLm5vdygpLW19KSksdGhpcy5tYWtlU3RhdHVzRXJyb3Iody5zdGF0dXMsaSxjLHcuaGVhZGVycyl9cmV0dXJuIFYodGhpcykuaW5mbyhiKSxWKHRoaXMpLmRlYnVnKGBbJHtwfV0gcmVzcG9uc2Ugc3RhcnRgLFgoe3JldHJ5T2ZSZXF1ZXN0TG9nSUQ6cyx1cmw6dy51cmwsc3RhdHVzOncuc3RhdHVzLGhlYWRlcnM6dy5oZWFkZXJzLGR1cmF0aW9uTXM6eS1tfSkpLHtyZXNwb25zZTp3LG9wdGlvbnM6cixjb250cm9sbGVyOmcscmVxdWVzdExvZ0lEOnAscmV0cnlPZlJlcXVlc3RMb2dJRDpzLHN0YXJ0VGltZTptfX1nZXRBUElMaXN0KGUsdCxzKXtyZXR1cm4gdGhpcy5yZXF1ZXN0QVBJTGlzdCh0LHttZXRob2Q6ImdldCIscGF0aDplLC4uLnN9KX1yZXF1ZXN0QVBJTGlzdChlLHQpe2NvbnN0IHM9dGhpcy5tYWtlUmVxdWVzdCh0LG51bGwsdm9pZCAwKTtyZXR1cm4gbmV3IGFlKHRoaXMscyxlKX1hc3luYyBmZXRjaFdpdGhUaW1lb3V0KGUsdCxzLHIpe2NvbnN0e3NpZ25hbDpuLG1ldGhvZDphLC4uLm99PXR8fHt9O24mJm4uYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLCgpPT5yLmFib3J0KCkpO2NvbnN0IGk9c2V0VGltZW91dCgoKT0+ci5hYm9ydCgpLHMpLGM9Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbSYmby5ib2R5IGluc3RhbmNlb2YgZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbXx8Im9iamVjdCI9PXR5cGVvZiBvLmJvZHkmJm51bGwhPT1vLmJvZHkmJlN5bWJvbC5hc3luY0l0ZXJhdG9yIGluIG8uYm9keSxsPXtzaWduYWw6ci5zaWduYWwsLi4uYz97ZHVwbGV4OiJoYWxmIn06e30sbWV0aG9kOiJHRVQiLC4uLm99O2EmJihsLm1ldGhvZD1hLnRvVXBwZXJDYXNlKCkpO3RyeXtyZXR1cm4gYXdhaXQgdGhpcy5mZXRjaC5jYWxsKHZvaWQgMCxlLGwpfWZpbmFsbHl7Y2xlYXJUaW1lb3V0KGkpfX1hc3luYyBzaG91bGRSZXRyeShlKXtjb25zdCB0PWUuaGVhZGVycy5nZXQoIngtc2hvdWxkLXJldHJ5Iik7cmV0dXJuInRydWUiPT09dHx8ImZhbHNlIiE9PXQmJig0MDg9PT1lLnN0YXR1c3x8NDA5PT09ZS5zdGF0dXN8fDQyOT09PWUuc3RhdHVzfHxlLnN0YXR1cz49NTAwKX1hc3luYyByZXRyeVJlcXVlc3QoZSx0LHMscil7bGV0IG47Y29uc3QgYT1yPy5nZXQoInJldHJ5LWFmdGVyLW1zIik7aWYoYSl7Y29uc3QgZT1wYXJzZUZsb2F0KGEpO051bWJlci5pc05hTihlKXx8KG49ZSl9Y29uc3Qgbz1yPy5nZXQoInJldHJ5LWFmdGVyIik7aWYobyYmIW4pe2NvbnN0IGU9cGFyc2VGbG9hdChvKTtuPU51bWJlci5pc05hTihlKT9EYXRlLnBhcnNlKG8pLURhdGUubm93KCk6MWUzKmV9aWYoIShuJiYwPD1uJiZuPDZlNCkpe2NvbnN0IHM9ZS5tYXhSZXRyaWVzPz90aGlzLm1heFJldHJpZXM7bj10aGlzLmNhbGN1bGF0ZURlZmF1bHRSZXRyeVRpbWVvdXRNaWxsaXModCxzKX12YXIgaTtyZXR1cm4gYXdhaXQoaT1uLG5ldyBQcm9taXNlKGU9PnNldFRpbWVvdXQoZSxpKSkpLHRoaXMubWFrZVJlcXVlc3QoZSx0LTEscyl9Y2FsY3VsYXRlRGVmYXVsdFJldHJ5VGltZW91dE1pbGxpcyhlLHQpe2NvbnN0IHM9dC1lO3JldHVybiBNYXRoLm1pbiguNSpNYXRoLnBvdygyLHMpLDgpKigxLS4yNSpNYXRoLnJhbmRvbSgpKSoxZTN9Y2FsY3VsYXRlTm9uc3RyZWFtaW5nVGltZW91dChlLHQpe2NvbnN0IHM9NmU1O2lmKDM2ZTUqZS8xMjhlMz5zfHxudWxsIT10JiZlPnQpdGhyb3cgbmV3IG8oIlN0cmVhbWluZyBpcyByZXF1aXJlZCBmb3Igb3BlcmF0aW9ucyB0aGF0IG1heSB0YWtlIGxvbmdlciB0aGFuIDEwIG1pbnV0ZXMuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYW50aHJvcGljcy9hbnRocm9waWMtc2RrLXR5cGVzY3JpcHQjbG9uZy1yZXF1ZXN0cyBmb3IgbW9yZSBkZXRhaWxzIik7cmV0dXJuIHN9YXN5bmMgYnVpbGRSZXF1ZXN0KGUse3JldHJ5Q291bnQ6dD0wfT17fSl7Y29uc3Qgcz17Li4uZX0se21ldGhvZDpyLHBhdGg6bixxdWVyeTphLGRlZmF1bHRCYXNlVVJMOml9PXMsYz10aGlzLmJ1aWxkVVJMKG4sYSxpKTsidGltZW91dCJpbiBzJiYoKGUsdCk9PntpZigibnVtYmVyIiE9dHlwZW9mIHR8fCFOdW1iZXIuaXNJbnRlZ2VyKHQpKXRocm93IG5ldyBvKGAke2V9IG11c3QgYmUgYW4gaW50ZWdlcmApO2lmKHQ8MCl0aHJvdyBuZXcgbyhgJHtlfSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlcmApfSkoInRpbWVvdXQiLHMudGltZW91dCkscy50aW1lb3V0PXMudGltZW91dD8/dGhpcy50aW1lb3V0O2NvbnN0e2JvZHlIZWFkZXJzOmwsYm9keTpkfT10aGlzLmJ1aWxkQm9keSh7b3B0aW9uczpzfSk7cmV0dXJue3JlcTp7bWV0aG9kOnIsaGVhZGVyczphd2FpdCB0aGlzLmJ1aWxkSGVhZGVycyh7b3B0aW9uczplLG1ldGhvZDpyLGJvZHlIZWFkZXJzOmwscmV0cnlDb3VudDp0fSksLi4ucy5zaWduYWwmJntzaWduYWw6cy5zaWduYWx9LC4uLmdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0mJmQgaW5zdGFuY2VvZiBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtJiZ7ZHVwbGV4OiJoYWxmIn0sLi4uZCYme2JvZHk6ZH0sLi4udGhpcy5mZXRjaE9wdGlvbnM/P3t9LC4uLnMuZmV0Y2hPcHRpb25zPz97fX0sdXJsOmMsdGltZW91dDpzLnRpbWVvdXR9fWFzeW5jIGJ1aWxkSGVhZGVycyh7b3B0aW9uczplLG1ldGhvZDp0LGJvZHlIZWFkZXJzOnMscmV0cnlDb3VudDpyfSl7bGV0IG49e307dGhpcy5pZGVtcG90ZW5jeUhlYWRlciYmImdldCIhPT10JiYoZS5pZGVtcG90ZW5jeUtleXx8KGUuaWRlbXBvdGVuY3lLZXk9dGhpcy5kZWZhdWx0SWRlbXBvdGVuY3lLZXkoKSksblt0aGlzLmlkZW1wb3RlbmN5SGVhZGVyXT1lLmlkZW1wb3RlbmN5S2V5KTtjb25zdCBhPV9lKFtuLHtBY2NlcHQ6ImFwcGxpY2F0aW9uL2pzb24iLCJVc2VyLUFnZW50Ijp0aGlzLmdldFVzZXJBZ2VudCgpLCJYLVN0YWlubGVzcy1SZXRyeS1Db3VudCI6U3RyaW5nKHIpLC4uLmUudGltZW91dD97IlgtU3RhaW5sZXNzLVRpbWVvdXQiOlN0cmluZyhNYXRoLnRydW5jKGUudGltZW91dC8xZTMpKX06e30sLi4ueD8/KHg9UCgpKSwuLi50aGlzLl9vcHRpb25zLmRhbmdlcm91c2x5QWxsb3dCcm93c2VyP3siYW50aHJvcGljLWRhbmdlcm91cy1kaXJlY3QtYnJvd3Nlci1hY2Nlc3MiOiJ0cnVlIn06dm9pZCAwLCJhbnRocm9waWMtdmVyc2lvbiI6IjIwMjMtMDYtMDEifSxhd2FpdCB0aGlzLmF1dGhIZWFkZXJzKGUpLHRoaXMuX29wdGlvbnMuZGVmYXVsdEhlYWRlcnMscyxlLmhlYWRlcnNdKTtyZXR1cm4gdGhpcy52YWxpZGF0ZUhlYWRlcnMoYSksYS52YWx1ZXN9YnVpbGRCb2R5KHtvcHRpb25zOntib2R5OmUsaGVhZGVyczp0fX0pe2lmKCFlKXJldHVybntib2R5SGVhZGVyczp2b2lkIDAsYm9keTp2b2lkIDB9O2NvbnN0IHI9X2UoW3RdKTtyZXR1cm4gQXJyYXlCdWZmZXIuaXNWaWV3KGUpfHxlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXJ8fGUgaW5zdGFuY2VvZiBEYXRhVmlld3x8InN0cmluZyI9PXR5cGVvZiBlJiZyLnZhbHVlcy5oYXMoImNvbnRlbnQtdHlwZSIpfHxnbG9iYWxUaGlzLkJsb2ImJmUgaW5zdGFuY2VvZiBnbG9iYWxUaGlzLkJsb2J8fGUgaW5zdGFuY2VvZiBGb3JtRGF0YXx8ZSBpbnN0YW5jZW9mIFVSTFNlYXJjaFBhcmFtc3x8Z2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbSYmZSBpbnN0YW5jZW9mIGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0/e2JvZHlIZWFkZXJzOnZvaWQgMCxib2R5OmV9OiJvYmplY3QiPT10eXBlb2YgZSYmKFN5bWJvbC5hc3luY0l0ZXJhdG9yIGluIGV8fFN5bWJvbC5pdGVyYXRvciBpbiBlJiYibmV4dCJpbiBlJiYiZnVuY3Rpb24iPT10eXBlb2YgZS5uZXh0KT97Ym9keUhlYWRlcnM6dm9pZCAwLGJvZHk6QShlKX06cyh0aGlzLG5zLCJmIikuY2FsbCh0aGlzLHtib2R5OmUsaGVhZGVyczpyfSl9fXJzPWNzLG5zPW5ldyBXZWFrTWFwLHNzPW5ldyBXZWFrU2V0LGFzPWZ1bmN0aW9uKCl7cmV0dXJuImh0dHBzOi8vYXBpLmFudGhyb3BpYy5jb20iIT09dGhpcy5iYXNlVVJMfSxjcy5BbnRocm9waWM9cnMsY3MuSFVNQU5fUFJPTVBUPSJcXG5cXG5IdW1hbjoiLGNzLkFJX1BST01QVD0iXFxuXFxuQXNzaXN0YW50OiIsY3MuREVGQVVMVF9USU1FT1VUPTZlNSxjcy5BbnRocm9waWNFcnJvcj1vLGNzLkFQSUVycm9yPWksY3MuQVBJQ29ubmVjdGlvbkVycm9yPWwsY3MuQVBJQ29ubmVjdGlvblRpbWVvdXRFcnJvcj1kLGNzLkFQSVVzZXJBYm9ydEVycm9yPWMsY3MuTm90Rm91bmRFcnJvcj1mLGNzLkNvbmZsaWN0RXJyb3I9bSxjcy5SYXRlTGltaXRFcnJvcj13LGNzLkJhZFJlcXVlc3RFcnJvcj1oLGNzLkF1dGhlbnRpY2F0aW9uRXJyb3I9dSxjcy5JbnRlcm5hbFNlcnZlckVycm9yPXksY3MuUGVybWlzc2lvbkRlbmllZEVycm9yPXAsY3MuVW5wcm9jZXNzYWJsZUVudGl0eUVycm9yPWcsY3MudG9GaWxlPWFzeW5jIGZ1bmN0aW9uKGUsdCxzKXtpZihjZSgpLGU9YXdhaXQgZSx0fHwodD1kZShlKSksKGU9Pm51bGwhPWUmJiJvYmplY3QiPT10eXBlb2YgZSYmInN0cmluZyI9PXR5cGVvZiBlLm5hbWUmJiJudW1iZXIiPT10eXBlb2YgZS5sYXN0TW9kaWZpZWQmJmdlKGUpKShlKSlyZXR1cm4gZSBpbnN0YW5jZW9mIEZpbGUmJm51bGw9PXQmJm51bGw9PXM/ZTpsZShbYXdhaXQgZS5hcnJheUJ1ZmZlcigpXSx0Pz9lLm5hbWUse3R5cGU6ZS50eXBlLGxhc3RNb2RpZmllZDplLmxhc3RNb2RpZmllZCwuLi5zfSk7aWYoKGU9Pm51bGwhPWUmJiJvYmplY3QiPT10eXBlb2YgZSYmInN0cmluZyI9PXR5cGVvZiBlLnVybCYmImZ1bmN0aW9uIj09dHlwZW9mIGUuYmxvYikoZSkpe2NvbnN0IHI9YXdhaXQgZS5ibG9iKCk7cmV0dXJuIHR8fCh0PW5ldyBVUkwoZS51cmwpLnBhdGhuYW1lLnNwbGl0KC9bXFwvXS8pLnBvcCgpKSxsZShhd2FpdCB3ZShyKSx0LHMpfWNvbnN0IHI9YXdhaXQgd2UoZSk7aWYoIXM/LnR5cGUpe2NvbnN0IGU9ci5maW5kKGU9PiJvYmplY3QiPT10eXBlb2YgZSYmInR5cGUiaW4gZSYmZS50eXBlKTsic3RyaW5nIj09dHlwZW9mIGUmJihzPXsuLi5zLHR5cGU6ZX0pfXJldHVybiBsZShyLHQscyl9O2NsYXNzIGxzIGV4dGVuZHMgY3N7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMuY29tcGxldGlvbnM9bmV3IFB0KHRoaXMpLHRoaXMubWVzc2FnZXM9bmV3IFF0KHRoaXMpLHRoaXMubW9kZWxzPW5ldyBlcyh0aGlzKSx0aGlzLmJldGE9bmV3IE10KHRoaXMpfX1scy5Db21wbGV0aW9ucz1QdCxscy5NZXNzYWdlcz1RdCxscy5Nb2RlbHM9ZXMsbHMuQmV0YT1NdDtjbGFzcyBkc3t2YWxpZGF0ZU1vZGVsKGUpe2lmKG51bGw9PT10aGlzLmF2YWlsYWJsZU1vZGVsc3x8MD09PXRoaXMuYXZhaWxhYmxlTW9kZWxzLmxlbmd0aClyZXR1cm4hMDtpZighdGhpcy5hdmFpbGFibGVNb2RlbHMuaW5jbHVkZXMoZSkpdGhyb3cgbmV3IEVycm9yKGBNb2RlbCAnJHtlfScgaXMgbm90IGF2YWlsYWJsZSBmb3IgcHJvdmlkZXIgJyR7dGhpcy5uYW1lfScuIEF2YWlsYWJsZSBtb2RlbHM6ICR7dGhpcy5hdmFpbGFibGVNb2RlbHMuam9pbigiLCAiKX1gKTtyZXR1cm4hMH12YWxpZGF0ZVJlcXVlc3QoZSl7aWYoIWUubW9kZWx8fDA9PT1lLm1vZGVsLnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJNb2RlbCBpcyByZXF1aXJlZCIpO2lmKCFlLm1lc3NhZ2VzfHwwPT09ZS5tZXNzYWdlcy5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJNZXNzYWdlcyBhcnJheSBpcyByZXF1aXJlZCBhbmQgbXVzdCBub3QgYmUgZW1wdHkiKTtpZih2b2lkIDAhPT1lLm1heF90b2tlbnMmJmUubWF4X3Rva2Vuczw9MCl0aHJvdyBuZXcgRXJyb3IoIm1heF90b2tlbnMgbXVzdCBiZSBwb3NpdGl2ZSIpO2lmKHZvaWQgMCE9PWUudGVtcGVyYXR1cmUmJihlLnRlbXBlcmF0dXJlPDB8fGUudGVtcGVyYXR1cmU+MikpdGhyb3cgbmV3IEVycm9yKCJ0ZW1wZXJhdHVyZSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMiIpO3RoaXMudmFsaWRhdGVNb2RlbChlLm1vZGVsKX12YWxpZGF0ZUNyZWRlbnRpYWxzU3RydWN0dXJlKGUpe2lmKCFlfHwhZS5hcGlLZXkpdGhyb3cgbmV3IEVycm9yKCJBUEkga2V5IGlzIHJlcXVpcmVkIik7aWYoInN0cmluZyIhPXR5cGVvZiBlLmFwaUtleXx8MD09PWUuYXBpS2V5LnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJBUEkga2V5IG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nIil9fWNsYXNzIGhzIGV4dGVuZHMgZHN7Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMubmFtZT0iYW50aHJvcGljIix0aGlzLl9hdmFpbGFibGVNb2RlbHM9bnVsbCx0aGlzLmRlZmF1bHRNb2RlbHM9bnVsbH1nZXQgYXZhaWxhYmxlTW9kZWxzKCl7cmV0dXJuIHRoaXMuX2F2YWlsYWJsZU1vZGVsc31hc3luYyBmZXRjaEF2YWlsYWJsZU1vZGVscyhlKXt0aGlzLnZhbGlkYXRlQ3JlZGVudGlhbHNTdHJ1Y3R1cmUoZSk7dHJ5e2NvbnN0IHQ9bmV3IGxzKHthcGlLZXk6ZS5hcGlLZXksZGFuZ2Vyb3VzbHlBbGxvd0Jyb3dzZXI6ITB9KSxzPShhd2FpdCB0Lm1vZGVscy5saXN0KCkpLmRhdGE7cmV0dXJuIHRoaXMuX2F2YWlsYWJsZU1vZGVscz1zLm1hcChlPT5lLmlkKSxzfWNhdGNoKGUpe3Rocm93IGNvbnNvbGUuZXJyb3IoIkZhaWxlZCB0byBmZXRjaCBtb2RlbHMgZnJvbSBBbnRocm9waWMgQVBJOiIsZSksbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggYXZhaWxhYmxlIG1vZGVsczogJHtlPy5tZXNzYWdlfHwiVW5rbm93biBlcnJvciJ9YCl9fWdldExhdGVzdE1vZGVsQnlGYW1pbHkoZSx0KXtjb25zdCBzPWUuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0LnRvTG93ZXJDYXNlKCkpKTtpZigwIT09cy5sZW5ndGgpcmV0dXJuIHMuc29ydCgoZSx0KT0+e2NvbnN0IHM9bmV3IERhdGUoZS5jcmVhdGVkX2F0KS5nZXRUaW1lKCk7cmV0dXJuIG5ldyBEYXRlKHQuY3JlYXRlZF9hdCkuZ2V0VGltZSgpLXN9KSxzWzBdLmlkfWFzeW5jIHZhbGlkYXRlQ3JlZGVudGlhbHMoZSl7dGhpcy52YWxpZGF0ZUNyZWRlbnRpYWxzU3RydWN0dXJlKGUpO3RyeXtyZXR1cm4gYXdhaXQgdGhpcy5mZXRjaEF2YWlsYWJsZU1vZGVscyhlKSwhMH1jYXRjaChlKXtpZig0MDE9PT1lPy5zdGF0dXN8fGU/Lm1lc3NhZ2U/LmluY2x1ZGVzKCJhdXRoZW50aWNhdGlvbiIpKXRocm93IG5ldyBFcnJvcigiSW52YWxpZCBBUEkga2V5Iik7dGhyb3cgbmV3IEVycm9yKGBDcmVkZW50aWFsIHZhbGlkYXRpb24gZmFpbGVkOiAke2U/Lm1lc3NhZ2V8fCJVbmtub3duIGVycm9yIn1gKX19YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe3RoaXMudmFsaWRhdGVSZXF1ZXN0KGUpLHRoaXMudmFsaWRhdGVDcmVkZW50aWFsc1N0cnVjdHVyZSh0KTtjb25zdCByPW5ldyBscyh7YXBpS2V5OnQuYXBpS2V5LGRhbmdlcm91c2x5QWxsb3dCcm93c2VyOiEwfSk7dHJ5e3JldHVybiBlLnN0cmVhbSYmcz9hd2FpdCB0aGlzLmhhbmRsZVN0cmVhbWluZ1JlcXVlc3QocixlLHMpOmF3YWl0IHRoaXMuaGFuZGxlTm9uU3RyZWFtaW5nUmVxdWVzdChyLGUpfWNhdGNoKGUpe3Rocm93IHRoaXMuaGFuZGxlRXJyb3IoZSl9fWFzeW5jIGhhbmRsZU5vblN0cmVhbWluZ1JlcXVlc3QoZSx0KXtjb25zdCBzPWF3YWl0IGUubWVzc2FnZXMuY3JlYXRlKHttb2RlbDp0Lm1vZGVsLG1heF90b2tlbnM6dC5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOnQudGVtcGVyYXR1cmUsc3lzdGVtOnQuc3lzdGVtLG1lc3NhZ2VzOnQubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKX0pLHI9cy5jb250ZW50LmZpbmQoZT0+InRleHQiPT09ZS50eXBlKTtyZXR1cm57Y29udGVudDpyJiYidGV4dCJpbiByP3IudGV4dDoiIixtb2RlbDpzLm1vZGVsLHByb3ZpZGVyOiJhbnRocm9waWMiLHVzYWdlOntpbnB1dF90b2tlbnM6cy51c2FnZS5pbnB1dF90b2tlbnMsb3V0cHV0X3Rva2VuczpzLnVzYWdlLm91dHB1dF90b2tlbnN9LHN0b3BfcmVhc29uOnMuc3RvcF9yZWFzb24/P3ZvaWQgMH19YXN5bmMgaGFuZGxlU3RyZWFtaW5nUmVxdWVzdChlLHQscyl7Y29uc3Qgcj1hd2FpdCBlLm1lc3NhZ2VzLmNyZWF0ZSh7bW9kZWw6dC5tb2RlbCxtYXhfdG9rZW5zOnQubWF4X3Rva2Vucz8/NDA5Nix0ZW1wZXJhdHVyZTp0LnRlbXBlcmF0dXJlLHN5c3RlbTp0LnN5c3RlbSxtZXNzYWdlczp0Lm1lc3NhZ2VzLmZpbHRlcihlPT4ic3lzdGVtIiE9PWUucm9sZSkubWFwKGU9Pih7cm9sZTplLnJvbGUsY29udGVudDplLmNvbnRlbnR9KSksc3RyZWFtOiEwfSk7bGV0IG4sYT0iIixvPXQubW9kZWwsaT0wLGM9MDtmb3IgYXdhaXQoY29uc3QgZSBvZiByKWlmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSlvPWUubWVzc2FnZS5tb2RlbCxpPWUubWVzc2FnZS51c2FnZS5pbnB1dF90b2tlbnM7ZWxzZSBpZigiY29udGVudF9ibG9ja19kZWx0YSI9PT1lLnR5cGUpe2lmKCJ0ZXh0X2RlbHRhIj09PWUuZGVsdGEudHlwZSl7Y29uc3QgdD1lLmRlbHRhLnRleHQ7YSs9dCxzKHQpfX1lbHNlIm1lc3NhZ2VfZGVsdGEiPT09ZS50eXBlJiYoYz1lLnVzYWdlLm91dHB1dF90b2tlbnMsbj1lLmRlbHRhLnN0b3BfcmVhc29uPz92b2lkIDApO3JldHVybntjb250ZW50OmEsbW9kZWw6byxwcm92aWRlcjoiYW50aHJvcGljIix1c2FnZTp7aW5wdXRfdG9rZW5zOmksb3V0cHV0X3Rva2VuczpjfSxzdG9wX3JlYXNvbjpufX1oYW5kbGVFcnJvcihlKXtyZXR1cm4gNDAxPT09ZT8uc3RhdHVzP25ldyBFcnJvcigiSW52YWxpZCBBUEkga2V5IG9yIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCIpOjQyOT09PWU/LnN0YXR1cz9uZXcgRXJyb3IoIlJhdGUgbGltaXQgZXhjZWVkZWQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuIik6NDAwPT09ZT8uc3RhdHVzP25ldyBFcnJvcihgQmFkIHJlcXVlc3Q6ICR7ZT8ubWVzc2FnZXx8IkludmFsaWQgcGFyYW1ldGVycyJ9YCk6NTAwPT09ZT8uc3RhdHVzP25ldyBFcnJvcigiQW50aHJvcGljIEFQSSBlcnJvci4gUGxlYXNlIHRyeSBhZ2Fpbi4iKTpuZXcgRXJyb3IoYEFQSSByZXF1ZXN0IGZhaWxlZDogJHtlPy5tZXNzYWdlfHwiVW5rbm93biBlcnJvciJ9YCl9fWNsYXNzIHVzIGV4dGVuZHMgZHN7Y29uc3RydWN0b3IoZSl7c3VwZXIoKSx0aGlzLm5hbWU9ImFudGhyb3BpYyIsdGhpcy5fYXZhaWxhYmxlTW9kZWxzPW51bGwsdGhpcy5kZWZhdWx0TW9kZWxzPW51bGwsdGhpcy5zZXJ2ZXJVcmw9ZS5jcmVkZW50aWFsU2VydmVyVXJsLnJlcGxhY2UoL1wvJC8sIiIpfWdldCBhdmFpbGFibGVNb2RlbHMoKXtyZXR1cm4gdGhpcy5fYXZhaWxhYmxlTW9kZWxzfWFzeW5jIGNoZWNrQXV0aFN0YXR1cygpe3JldHVybihhd2FpdCBmZXRjaChgJHt0aGlzLnNlcnZlclVybH0vc3RhdHVzYCx7bWV0aG9kOiJHRVQiLGNyZWRlbnRpYWxzOiJpbmNsdWRlIn0pKS5qc29uKCl9Z2V0U2V0dXBVcmwoKXtyZXR1cm5gJHt0aGlzLnNlcnZlclVybH0vc2V0dXBgfWFzeW5jIGZldGNoQXZhaWxhYmxlTW9kZWxzKGUpe3RyeXtjb25zdCBlPWF3YWl0IGZldGNoKGAke3RoaXMuc2VydmVyVXJsfS9wcm94eT9wYXRoPS92MS9tb2RlbHNgLHttZXRob2Q6IkdFVCIsY3JlZGVudGlhbHM6ImluY2x1ZGUifSk7aWYoIWUub2spdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggbW9kZWxzOiBIVFRQICR7ZS5zdGF0dXN9YCk7Y29uc3QgdD0oKGF3YWl0IGUuanNvbigpKS5kYXRhfHxbXSkubWFwKGU9Pih7aWQ6ZS5pZCxkaXNwbGF5X25hbWU6ZS5kaXNwbGF5X25hbWV8fGUuaWQsY3JlYXRlZF9hdDplLmNyZWF0ZWRfYXR8fChuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSx0eXBlOmUudHlwZXx8Im1vZGVsIn0pKTtyZXR1cm4gdGhpcy5fYXZhaWxhYmxlTW9kZWxzPXQubWFwKGU9PmUuaWQpLHR9Y2F0Y2goZSl7dGhyb3cgY29uc29sZS5lcnJvcigiW1Byb3hpZWRBbnRocm9waWNQcm92aWRlcl0gRmFpbGVkIHRvIGZldGNoIG1vZGVscyBmcm9tIEFQSToiLGUubWVzc2FnZSksbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggYXZhaWxhYmxlIG1vZGVsczogJHtlLm1lc3NhZ2V9YCl9fWdldExhdGVzdE1vZGVsQnlGYW1pbHkoZSx0KXtjb25zdCBzPWUuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0LnRvTG93ZXJDYXNlKCkpKTtpZigwIT09cy5sZW5ndGgpcmV0dXJuIHMuc29ydCgoZSx0KT0+e2NvbnN0IHM9bmV3IERhdGUoZS5jcmVhdGVkX2F0KS5nZXRUaW1lKCk7cmV0dXJuIG5ldyBEYXRlKHQuY3JlYXRlZF9hdCkuZ2V0VGltZSgpLXN9KSxzWzBdLmlkfWFzeW5jIHZhbGlkYXRlQ3JlZGVudGlhbHMoZSl7cmV0dXJuKGF3YWl0IHRoaXMuY2hlY2tBdXRoU3RhdHVzKCkpLmF1dGhlbnRpY2F0ZWR9YXN5bmMgbWFrZVJlcXVlc3QoZSx0LHMpe2lmKHRoaXMudmFsaWRhdGVSZXF1ZXN0KGUpLCEoYXdhaXQgdGhpcy5jaGVja0F1dGhTdGF0dXMoKSkuYXV0aGVudGljYXRlZCl0aHJvdyBuZXcgRXJyb3IoYE5vdCBhdXRoZW50aWNhdGVkLiBQbGVhc2UgdmlzaXQgJHt0aGlzLmdldFNldHVwVXJsKCl9IHRvIHNldCB1cCB5b3VyIEFQSSBrZXkuYCk7dHJ5e3JldHVybiBlLnN0cmVhbSYmcz9hd2FpdCB0aGlzLmhhbmRsZVN0cmVhbWluZ1JlcXVlc3QoZSxzKTphd2FpdCB0aGlzLmhhbmRsZU5vblN0cmVhbWluZ1JlcXVlc3QoZSl9Y2F0Y2goZSl7dGhyb3cgdGhpcy5oYW5kbGVFcnJvcihlKX19YXN5bmMgaGFuZGxlTm9uU3RyZWFtaW5nUmVxdWVzdChlKXtjb25zdCB0PXttb2RlbDplLm1vZGVsLG1heF90b2tlbnM6ZS5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOmUudGVtcGVyYXR1cmUsc3lzdGVtOmUuc3lzdGVtLG1lc3NhZ2VzOmUubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKX0scz1hd2FpdCBmZXRjaChgJHt0aGlzLnNlcnZlclVybH0vcHJveHk/cGF0aD0vdjEvbWVzc2FnZXNgLHttZXRob2Q6IlBPU1QiLGhlYWRlcnM6eyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIn0sY3JlZGVudGlhbHM6ImluY2x1ZGUiLGJvZHk6SlNPTi5zdHJpbmdpZnkodCl9KTtpZighcy5vayl7Y29uc3QgZT1hd2FpdCBzLmpzb24oKS5jYXRjaCgoKT0+KHtlcnJvcjoiVW5rbm93biBlcnJvciJ9KSk7dGhyb3cgbmV3IEVycm9yKGUuZXJyb3I/Lm1lc3NhZ2V8fGUuZXJyb3J8fGBIVFRQICR7cy5zdGF0dXN9YCl9Y29uc3Qgcj1hd2FpdCBzLmpzb24oKSxuPXIuY29udGVudD8uZmluZChlPT4idGV4dCI9PT1lLnR5cGUpO3JldHVybntjb250ZW50Om4mJiJ0ZXh0ImluIG4/bi50ZXh0OiIiLG1vZGVsOnIubW9kZWwscHJvdmlkZXI6ImFudGhyb3BpYyIsdXNhZ2U6e2lucHV0X3Rva2VuczpyLnVzYWdlPy5pbnB1dF90b2tlbnN8fDAsb3V0cHV0X3Rva2VuczpyLnVzYWdlPy5vdXRwdXRfdG9rZW5zfHwwfSxzdG9wX3JlYXNvbjpyLnN0b3BfcmVhc29uPz92b2lkIDB9fWFzeW5jIGhhbmRsZVN0cmVhbWluZ1JlcXVlc3QoZSx0KXtjb25zdCBzPXttb2RlbDplLm1vZGVsLG1heF90b2tlbnM6ZS5tYXhfdG9rZW5zPz80MDk2LHRlbXBlcmF0dXJlOmUudGVtcGVyYXR1cmUsc3lzdGVtOmUuc3lzdGVtLG1lc3NhZ2VzOmUubWVzc2FnZXMuZmlsdGVyKGU9PiJzeXN0ZW0iIT09ZS5yb2xlKS5tYXAoZT0+KHtyb2xlOmUucm9sZSxjb250ZW50OmUuY29udGVudH0pKSxzdHJlYW06ITB9LHI9YXdhaXQgZmV0Y2goYCR7dGhpcy5zZXJ2ZXJVcmx9L3Byb3h5P3BhdGg9L3YxL21lc3NhZ2VzYCx7bWV0aG9kOiJQT1NUIixoZWFkZXJzOnsiQ29udGVudC1UeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LGNyZWRlbnRpYWxzOiJpbmNsdWRlIixib2R5OkpTT04uc3RyaW5naWZ5KHMpfSk7aWYoIXIub2spe2NvbnN0IGU9YXdhaXQgci5qc29uKCkuY2F0Y2goKCk9Pih7ZXJyb3I6IlVua25vd24gZXJyb3IifSkpO3Rocm93IG5ldyBFcnJvcihlLmVycm9yPy5tZXNzYWdlfHxlLmVycm9yfHxgSFRUUCAke3Iuc3RhdHVzfWApfWNvbnN0IG49ci5ib2R5Py5nZXRSZWFkZXIoKTtpZighbil0aHJvdyBuZXcgRXJyb3IoIlN0cmVhbWluZyBub3Qgc3VwcG9ydGVkIik7Y29uc3QgYT1uZXcgVGV4dERlY29kZXI7bGV0IG8saT0iIixjPWUubW9kZWwsbD0wLGQ9MDt0cnl7Zm9yKDs7KXtjb25zdHtkb25lOmUsdmFsdWU6c309YXdhaXQgbi5yZWFkKCk7aWYoZSlicmVhaztjb25zdCByPWEuZGVjb2RlKHMse3N0cmVhbTohMH0pLnNwbGl0KCJcbiIpO2Zvcihjb25zdCBlIG9mIHIpaWYoZS5zdGFydHNXaXRoKCJkYXRhOiAiKSl7Y29uc3Qgcz1lLnNsaWNlKDYpO2lmKCJbRE9ORV0iPT09cyljb250aW51ZTt0cnl7Y29uc3QgZT1KU09OLnBhcnNlKHMpO2lmKCJtZXNzYWdlX3N0YXJ0Ij09PWUudHlwZSljPWUubWVzc2FnZS5tb2RlbCxsPWUubWVzc2FnZS51c2FnZT8uaW5wdXRfdG9rZW5zfHwwO2Vsc2UgaWYoImNvbnRlbnRfYmxvY2tfZGVsdGEiPT09ZS50eXBlKXtpZigidGV4dF9kZWx0YSI9PT1lLmRlbHRhPy50eXBlKXtjb25zdCBzPWUuZGVsdGEudGV4dDtpKz1zLHQocyl9fWVsc2UibWVzc2FnZV9kZWx0YSI9PT1lLnR5cGUmJihkPWUudXNhZ2U/Lm91dHB1dF90b2tlbnN8fDAsbz1lLmRlbHRhPy5zdG9wX3JlYXNvbj8/dm9pZCAwKX1jYXRjaHt9fX19ZmluYWxseXtuLnJlbGVhc2VMb2NrKCl9cmV0dXJue2NvbnRlbnQ6aSxtb2RlbDpjLHByb3ZpZGVyOiJhbnRocm9waWMiLHVzYWdlOntpbnB1dF90b2tlbnM6bCxvdXRwdXRfdG9rZW5zOmR9LHN0b3BfcmVhc29uOm99fWhhbmRsZUVycm9yKGUpe2NvbnN0IHQ9ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IiO3JldHVybiB0LmluY2x1ZGVzKCI0MDEiKXx8dC5pbmNsdWRlcygiYXV0aGVudGljYXRpb24iKT9uZXcgRXJyb3IoYE5vdCBhdXRoZW50aWNhdGVkLiBQbGVhc2UgdmlzaXQgJHt0aGlzLmdldFNldHVwVXJsKCl9IHRvIHNldCB1cCB5b3VyIEFQSSBrZXkuYCk6dC5pbmNsdWRlcygiNDI5Iik/bmV3IEVycm9yKCJSYXRlIGxpbWl0IGV4Y2VlZGVkLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLiIpOnQuaW5jbHVkZXMoIjQwMCIpP25ldyBFcnJvcihgQmFkIHJlcXVlc3Q6ICR7dH1gKTpuZXcgRXJyb3IoYEFQSSByZXF1ZXN0IGZhaWxlZDogJHt0fWApfX1jbGFzcyBwc3tjb25zdHJ1Y3RvcihlLHQscyl7dGhpcy5pc0luaXRpYWxpemVkPSExLHRoaXMuZm9yY2VMb2NhbE1vZGU9ITEsdGhpcy5jb25maWdNYW5hZ2VyPWUsdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsPXQsdGhpcy5hbGxvd0xvY2FsTW9kZT1zPz8hMX1zZXRQcm9tcHRIYW5kbGVyKGUpe3RoaXMucHJvbXB0SGFuZGxlcj1lfXN0YXRpYyBnZXRJbnN0YW5jZShlLHQscyl7aWYoIXBzLmluc3RhbmNlKXtpZighZSl0aHJvdyBuZXcgRXJyb3IoIkNvbmZpZ01hbmFnZXIgcmVxdWlyZWQgZm9yIGZpcnN0IGluaXRpYWxpemF0aW9uIik7cHMuaW5zdGFuY2U9bmV3IHBzKGUsdCxzKX1yZXR1cm4gcHMuaW5zdGFuY2V9aXNQcm94aWVkTW9kZSgpe3JldHVybiEhdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsJiYhdGhpcy5mb3JjZUxvY2FsTW9kZX1pc0xvY2FsTW9kZUFsbG93ZWQoKXtyZXR1cm4gdGhpcy5hbGxvd0xvY2FsTW9kZX1pc0xvY2FsTW9kZUZvcmNlZCgpe3JldHVybiB0aGlzLmZvcmNlTG9jYWxNb2RlfWFzeW5jIHNldEZvcmNlTG9jYWxNb2RlKGUpe2lmKHRoaXMuZm9yY2VMb2NhbE1vZGUhPT1lKXtpZih0aGlzLmZvcmNlTG9jYWxNb2RlPWUsYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnNldEZvcmNlTG9jYWxNb2RlKGUpLHRoaXMuY3JlZGVudGlhbHM9dm9pZCAwLHRoaXMud2VpZ2h0TWFwcGVyKXtjb25zdCBlPXRoaXMud2VpZ2h0TWFwcGVyLmdldFByb3ZpZGVyKCk7dGhpcy5wcm92aWRlcj10aGlzLmNyZWF0ZVByb3ZpZGVyKGUpfWNvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIFN3aXRjaGVkIG1vZGUiLHtmb3JjZUxvY2FsTW9kZTplLGlzUHJveGllZE1vZGU6dGhpcy5pc1Byb3hpZWRNb2RlKCl9KX19YXN5bmMgY29uZmlndXJlTG9jYWwodCxzLHI9ITApe3RoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCksdGhpcy5mb3JjZUxvY2FsTW9kZT0hMCxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuc2F2ZUxvY2FsKHQscyxyKSx0aGlzLnByb3ZpZGVyPXRoaXMuY3JlYXRlUHJvdmlkZXIodC5wcm92aWRlciksdGhpcy53ZWlnaHRNYXBwZXI9bmV3IGUodC5wcm92aWRlcix0Lm1vZGVscyksdC5jcmVkZW50aWFscyYmKHRoaXMuY3JlZGVudGlhbHM9dC5jcmVkZW50aWFscyksY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gQ29uZmlndXJlZCBsb2NhbCBtb2RlIix7cHJvdmlkZXI6dC5wcm92aWRlcixoYXNQYXNzd29yZDohIXN9KX1nZXRDcmVkZW50aWFsU2VydmVyU2V0dXBVcmwoKXtyZXR1cm4gdGhpcy5jcmVkZW50aWFsU2VydmVyVXJsP2Ake3RoaXMuY3JlZGVudGlhbFNlcnZlclVybH0vc2V0dXBgOm51bGx9YXN5bmMgZmV0Y2hBdmFpbGFibGVNb2RlbHMoKXtpZihhd2FpdCB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCksIXRoaXMucHJvdmlkZXIpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBub3QgY29uZmlndXJlZCIpO2NvbnN0IGU9dGhpcy5jcmVkZW50aWFsc3x8e2FwaUtleToicHJveGllZCJ9O2NvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIEZldGNoaW5nIGF2YWlsYWJsZSBtb2RlbHMgZnJvbSBwcm92aWRlciIpO2NvbnN0IHQ9YXdhaXQgdGhpcy5wcm92aWRlci5mZXRjaEF2YWlsYWJsZU1vZGVscyhlKTtyZXR1cm4gY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gRmV0Y2hlZCBtb2RlbHM6Iix0Lm1hcChlPT5lLmlkKSksdH1hc3luYyBlbnN1cmVJbml0aWFsaXplZCgpe3RoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCl9YXN5bmMgaW5pdGlhbGl6ZSgpe2lmKHRoaXMuaXNJbml0aWFsaXplZClyZXR1cm4gdm9pZCBjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBBbHJlYWR5IGluaXRpYWxpemVkLCBza2lwcGluZyIpO3RoaXMuZm9yY2VMb2NhbE1vZGU9YXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLmdldEZvcmNlTG9jYWxNb2RlKCksY29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gSW5pdGlhbGl6aW5nLi4uIix7aXNQcm94aWVkTW9kZTp0aGlzLmlzUHJveGllZE1vZGUoKSxjcmVkZW50aWFsU2VydmVyVXJsOnRoaXMuY3JlZGVudGlhbFNlcnZlclVybCxmb3JjZUxvY2FsTW9kZTp0aGlzLmZvcmNlTG9jYWxNb2RlLGFsbG93TG9jYWxNb2RlOnRoaXMuYWxsb3dMb2NhbE1vZGV9KTtjb25zdCB0PWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5sb2FkTWV0YWRhdGEoKTtpZihjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBMb2FkZWQgbWV0YWRhdGE6Iix0KSx0KXtjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBVc2luZyBleGlzdGluZyBtZXRhZGF0YSIpLHRoaXMucHJvdmlkZXI9dGhpcy5jcmVhdGVQcm92aWRlcih0LnByb3ZpZGVyKSx0aGlzLndlaWdodE1hcHBlcj1uZXcgZSh0LnByb3ZpZGVyLHQubW9kZWxzKTtjb25zdCBzPWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5nZXRQbGFpbnRleHRDcmVkZW50aWFscygpO3M/KGNvbnNvbGUubG9nKCJbQWlEZWxlZ2F0ZUNvcmVdIFVzaW5nIHBsYWludGV4dCBjcmVkZW50aWFscyAobG9jYWwgZGV2IG1vZGUpIiksdGhpcy5jcmVkZW50aWFscz1zKTp0aGlzLmlzUHJveGllZE1vZGUoKSYmKHRoaXMuY3JlZGVudGlhbHM9e2FwaUtleToicHJveGllZCJ9KX1lbHNlIHRoaXMuaXNQcm94aWVkTW9kZSgpPyhjb25zb2xlLmxvZygiW0FpRGVsZWdhdGVDb3JlXSBObyBtZXRhZGF0YSwgaW5pdGlhbGl6aW5nIHByb3hpZWQgZGVmYXVsdHMiKSxhd2FpdCB0aGlzLmluaXRpYWxpemVQcm94aWVkRGVmYXVsdHMoKSk6Y29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gTm8gbWV0YWRhdGEgYW5kIG5vdCBwcm94aWVkIG1vZGUgLSB1bmluaXRpYWxpemVkIik7Y29uc29sZS5sb2coIltBaURlbGVnYXRlQ29yZV0gSW5pdGlhbGl6YXRpb24gY29tcGxldGUiLHtwcm92aWRlcjohIXRoaXMucHJvdmlkZXIsd2VpZ2h0TWFwcGVyOiEhdGhpcy53ZWlnaHRNYXBwZXIsY3JlZGVudGlhbHM6ISF0aGlzLmNyZWRlbnRpYWxzfSksdGhpcy5pc0luaXRpYWxpemVkPSEwfWFzeW5jIGluaXRpYWxpemVQcm94aWVkRGVmYXVsdHMoKXt0aGlzLnByb3ZpZGVyPXRoaXMuY3JlYXRlUHJvdmlkZXIoImFudGhyb3BpYyIpLHRoaXMud2VpZ2h0TWFwcGVyPW5ldyBlKCJhbnRocm9waWMiLHt9KSx0aGlzLmNyZWRlbnRpYWxzPXthcGlLZXk6InByb3hpZWQifSxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuc2F2ZU1ldGFkYXRhKCJhbnRocm9waWMiLHt9LCEwKX1hc3luYyBjb25maWd1cmUoZSx0LHM9ITEpe2F3YWl0IHRoaXMuYXBwbHlDb25maWcoZSksYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnNhdmUoZSx0LHMpfWFzeW5jIGFwcGx5Q29uZmlnKHQpe2lmKHRoaXMucHJvdmlkZXI9dGhpcy5jcmVhdGVQcm92aWRlcih0LnByb3ZpZGVyKSx0aGlzLndlaWdodE1hcHBlcj1uZXcgZSh0LnByb3ZpZGVyLHQubW9kZWxzKSx0LmNyZWRlbnRpYWxzKXt0aGlzLmNyZWRlbnRpYWxzPXQuY3JlZGVudGlhbHM7dHJ5e2F3YWl0IHRoaXMucHJvdmlkZXIudmFsaWRhdGVDcmVkZW50aWFscyh0LmNyZWRlbnRpYWxzKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYENyZWRlbnRpYWwgdmFsaWRhdGlvbiBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApfX19YXN5bmMgbWFrZVJlcXVlc3QoZSl7dGhpcy5pc0luaXRpYWxpemVkfHxhd2FpdCB0aGlzLmluaXRpYWxpemUoKTtjb25zdCB0PWF3YWl0IHRoaXMuZ2V0U3RhdGUoKTtpZigidW5pbml0aWFsaXplZCI9PT10P2F3YWl0IHRoaXMucHJvbXB0Rm9yQ29uZmlndXJhdGlvbklmTmVlZGVkKCk6ImxvY2tlZCI9PT10JiZhd2FpdCB0aGlzLnByb21wdEZvclVubG9jaygpLCF0aGlzLnByb3ZpZGVyfHwhdGhpcy53ZWlnaHRNYXBwZXIpdGhyb3cgbmV3IEVycm9yKCJBaURlbGVnYXRlIGlzIG5vdCBjb25maWd1cmVkLiBQbGVhc2UgY2FsbCBjb25maWd1cmUoKSB3aXRoIHByb3ZpZGVyIGFuZCBjcmVkZW50aWFscy4iKTtpZighdGhpcy5jcmVkZW50aWFscyl0aHJvdyBuZXcgRXJyb3IoIk5vIGNyZWRlbnRpYWxzIGF2YWlsYWJsZS4gUGxlYXNlIHByb3ZpZGUgcGFzc3dvcmQgdG8gdW5sb2NrLiIpO2xldCBzPXRoaXMud2VpZ2h0TWFwcGVyLmdldE1vZGVsKGUud2VpZ2h0KTtjb25zb2xlLmxvZyhgW0FpRGVsZWdhdGVDb3JlXSBtYWtlUmVxdWVzdCB3ZWlnaHQ9JHtlLndlaWdodH0sIG1hcHBlZCBtb2RlbD0ke3N9YCksc3x8KGNvbnNvbGUubG9nKGBbQWlEZWxlZ2F0ZUNvcmVdIE5vIG1vZGVsIGZvciB3ZWlnaHQgJHtlLndlaWdodH0sIGF1dG8tc2VsZWN0aW5nLi4uYCkscz1hd2FpdCB0aGlzLmVuc3VyZU1vZGVsRm9yV2VpZ2h0KGUud2VpZ2h0KSxjb25zb2xlLmxvZyhgW0FpRGVsZWdhdGVDb3JlXSBBdXRvLXNlbGVjdGVkIG1vZGVsOiAke3N9YCkpO2NvbnN0IHI9e21vZGVsOnMsbWVzc2FnZXM6ZS5tZXNzYWdlcyxtYXhfdG9rZW5zOmUubWF4X3Rva2Vucyx0ZW1wZXJhdHVyZTplLnRlbXBlcmF0dXJlLHN0cmVhbTplLnN0cmVhbSxzeXN0ZW06ZS5zeXN0ZW19O2lmKGUuc3RyZWFtJiYhZS5vblN0cmVhbSl0aHJvdyBuZXcgRXJyb3IoIm9uU3RyZWFtIGNhbGxiYWNrIGlzIHJlcXVpcmVkIHdoZW4gc3RyZWFtPXRydWUiKTt0cnl7cmV0dXJuIGF3YWl0IHRoaXMucHJvdmlkZXIubWFrZVJlcXVlc3Qocix0aGlzLmNyZWRlbnRpYWxzLGUub25TdHJlYW0pfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcihgQUkgcmVxdWVzdCBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApfX1hc3luYyBlbnN1cmVNb2RlbEZvcldlaWdodChlKXtpZighdGhpcy5wcm92aWRlcnx8IXRoaXMuY3JlZGVudGlhbHMpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBhbmQgY3JlZGVudGlhbHMgbXVzdCBiZSBjb25maWd1cmVkIGZpcnN0Iik7Y29uc3QgdD1hd2FpdCB0aGlzLnByb3ZpZGVyLmZldGNoQXZhaWxhYmxlTW9kZWxzKHRoaXMuY3JlZGVudGlhbHMpO2lmKDA9PT10Lmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIk5vIG1vZGVscyBhdmFpbGFibGUgZnJvbSBwcm92aWRlciIpO2xldCBzO2lmKGF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5nZXRVc2VEZWZhdWx0TW9kZWxzKCkpcz1hd2FpdCB0aGlzLmF1dG9TZWxlY3RNb2RlbEZvcldlaWdodChlLHQpO2Vsc2V7aWYoIXRoaXMucHJvbXB0SGFuZGxlcil0aHJvdyBuZXcgRXJyb3IoIk1vZGVsIHNlbGVjdGlvbiByZXF1aXJlZCBidXQgcHJvbXB0IGhhbmRsZXIgbm90IHNldCIpO3M9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvck1vZGVsU2VsZWN0aW9uKGUsdCl9cmV0dXJuIGF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5zZXRNb2RlbEZvcldlaWdodChlLHMpLHRoaXMud2VpZ2h0TWFwcGVyJiZ0aGlzLndlaWdodE1hcHBlci5zZXRNb2RlbChlLHMpLHN9YXN5bmMgYXV0b1NlbGVjdE1vZGVsRm9yV2VpZ2h0KGUsdCl7aWYoIXRoaXMucHJvdmlkZXIpdGhyb3cgbmV3IEVycm9yKCJQcm92aWRlciBub3QgY29uZmlndXJlZCIpO2NvbnN0IHM9e2xpZ2h0OiJoYWlrdSIsbW9kZXJhdGU6InNvbm5ldCIsaGVhdnk6Im9wdXMifVtlXTtpZih0aGlzLnByb3ZpZGVyIGluc3RhbmNlb2YgaHMpe2NvbnN0IGU9dGhpcy5wcm92aWRlci5nZXRMYXRlc3RNb2RlbEJ5RmFtaWx5KHQscyk7aWYoZSlyZXR1cm4gZX1jb25zdCByPXQuZmlsdGVyKGU9PmUuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhzLnRvTG93ZXJDYXNlKCkpfHxlLmRpc3BsYXlfbmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHMudG9Mb3dlckNhc2UoKSkpO2lmKDA9PT1yLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYE5vICR7c30gbW9kZWxzIGZvdW5kIGZvciAke2V9IHdlaWdodGApO3JldHVybiByLnNvcnQoKGUsdCk9Pntjb25zdCBzPW5ldyBEYXRlKGUuY3JlYXRlZF9hdCkuZ2V0VGltZSgpO3JldHVybiBuZXcgRGF0ZSh0LmNyZWF0ZWRfYXQpLmdldFRpbWUoKS1zfSksclswXS5pZH1hc3luYyBnZXRTdGF0dXMoKXt0aGlzLmlzSW5pdGlhbGl6ZWR8fGF3YWl0IHRoaXMuaW5pdGlhbGl6ZSgpO2NvbnN0IGU9YXdhaXQgdGhpcy5nZXRTdGF0ZSgpO2xldCB0PWF3YWl0IHRoaXMuY29uZmlnTWFuYWdlci5oYXNDcmVkZW50aWFscygpO2lmKHRoaXMuaXNQcm94aWVkTW9kZSgpKXtjb25zdCBlPXRoaXMucHJvdmlkZXI7aWYoZSYmImZ1bmN0aW9uIj09dHlwZW9mIGUuY2hlY2tBdXRoU3RhdHVzKXRyeXt0PShhd2FpdCBlLmNoZWNrQXV0aFN0YXR1cygpKS5hdXRoZW50aWNhdGVkfWNhdGNoe319cmV0dXJue3N0YXRlOmUsY29uZmlndXJlZDohIXRoaXMucHJvdmlkZXImJiEhdGhpcy53ZWlnaHRNYXBwZXIsaGFzQ3JlZGVudGlhbHM6dCxwcm92aWRlcjp0aGlzLnByb3ZpZGVyPy5uYW1lLG1vZGVsczp0aGlzLndlaWdodE1hcHBlcj8uZ2V0TWFwcGluZygpLGNhY2hlRW5hYmxlZDohMSx0cmFja2luZ0VuYWJsZWQ6ITF9fWFzeW5jIGxvY2soKXt0aGlzLmNyZWRlbnRpYWxzPXZvaWQgMCxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuY2xlYXJDcmVkZW50aWFscygpfWFzeW5jIHJlc2V0KCl7dGhpcy5wcm92aWRlcj12b2lkIDAsdGhpcy53ZWlnaHRNYXBwZXI9dm9pZCAwLHRoaXMuY3JlZGVudGlhbHM9dm9pZCAwLHRoaXMuaXNJbml0aWFsaXplZD0hMSxhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuY2xlYXIoKX1jcmVhdGVQcm92aWRlcihlKXtzd2l0Y2goZSl7Y2FzZSJhbnRocm9waWMiOnJldHVybiB0aGlzLmlzUHJveGllZE1vZGUoKT9uZXcgdXMoe2NyZWRlbnRpYWxTZXJ2ZXJVcmw6dGhpcy5jcmVkZW50aWFsU2VydmVyVXJsfSk6bmV3IGhzO2Nhc2Uib3BlbmFpIjp0aHJvdyBuZXcgRXJyb3IoIk9wZW5BSSBwcm92aWRlciBub3QgeWV0IGltcGxlbWVudGVkIik7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gcHJvdmlkZXI6ICR7ZX1gKX19YXN5bmMgdXBkYXRlQ3JlZGVudGlhbHMoZSx0KXtpZighdGhpcy5wcm92aWRlcil0aHJvdyBuZXcgRXJyb3IoIlByb3ZpZGVyIG5vdCBjb25maWd1cmVkLiBDYWxsIGNvbmZpZ3VyZSgpIGZpcnN0LiIpO2F3YWl0IHRoaXMucHJvdmlkZXIudmFsaWRhdGVDcmVkZW50aWFscyhlKSx0aGlzLmNyZWRlbnRpYWxzPWUsYXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnVwZGF0ZUNyZWRlbnRpYWxzKGUsdCl9YXN5bmMgaXNSZWFkeSgpe2lmKHRoaXMuaXNJbml0aWFsaXplZHx8YXdhaXQgdGhpcy5pbml0aWFsaXplKCksdGhpcy5pc1Byb3hpZWRNb2RlKCkpe2NvbnN0IGU9dGhpcy5wcm92aWRlcjtpZihlJiYiZnVuY3Rpb24iPT10eXBlb2YgZS5jaGVja0F1dGhTdGF0dXMpdHJ5e2NvbnN0IHQ9YXdhaXQgZS5jaGVja0F1dGhTdGF0dXMoKTtyZXR1cm4hIXRoaXMucHJvdmlkZXImJiEhdGhpcy53ZWlnaHRNYXBwZXImJnQuYXV0aGVudGljYXRlZH1jYXRjaHtyZXR1cm4hMX19cmV0dXJuISF0aGlzLnByb3ZpZGVyJiYhIXRoaXMud2VpZ2h0TWFwcGVyJiYhIXRoaXMuY3JlZGVudGlhbHN9YXN5bmMgZ2V0U3RhdGUoKXtpZih0aGlzLmlzUHJveGllZE1vZGUoKSl7Y29uc3QgZT10aGlzLnByb3ZpZGVyO2lmKGUmJiJmdW5jdGlvbiI9PXR5cGVvZiBlLmNoZWNrQXV0aFN0YXR1cyl0cnl7aWYoKGF3YWl0IGUuY2hlY2tBdXRoU3RhdHVzKCkpLmF1dGhlbnRpY2F0ZWQpcmV0dXJuInVubG9ja2VkIn1jYXRjaHt9cmV0dXJuInVuaW5pdGlhbGl6ZWQifXJldHVybiBhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuaGFzQ29uZmlnKCk/dGhpcy5jcmVkZW50aWFscz8idW5sb2NrZWQiOiJsb2NrZWQiOiJ1bmluaXRpYWxpemVkIn1hc3luYyBwcm9tcHRGb3JDb25maWd1cmF0aW9uSWZOZWVkZWQoKXtpZighdGhpcy5wcm9tcHRIYW5kbGVyKXRocm93IG5ldyBFcnJvcigiQ29uZmlndXJhdGlvbiByZXF1aXJlZC4gUHJvbXB0IGhhbmRsZXIgbm90IHNldC4gVGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3b3JrZXIgY29udGV4dCB3aXRoIGEgcHJvbXB0IGhhbmRsZXIuIik7dHJ5e2NvbnN0IGU9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvckNvbmZpZ3VyYXRpb24oKTthd2FpdCB0aGlzLmNvbmZpZ3VyZShlLmNvbmZpZyxlLnBhc3N3b3JkLGUudXNlRGVmYXVsdE1vZGVscyl9Y2F0Y2goZSl7dGhyb3cgbmV3IEVycm9yKGBDb25maWd1cmF0aW9uIHJlcXVpcmVkOiAke2UubWVzc2FnZX1gKX19YXN5bmMgcHJvbXB0Rm9yVW5sb2NrKCl7aWYoIXRoaXMucHJvbXB0SGFuZGxlcil0aHJvdyBuZXcgRXJyb3IoIlBhc3N3b3JkIHJlcXVpcmVkIHRvIHVubG9jay4gUHJvbXB0IGhhbmRsZXIgbm90IHNldC4gVGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3b3JrZXIgY29udGV4dCB3aXRoIGEgcHJvbXB0IGhhbmRsZXIuIik7dHJ5e2NvbnN0IGU9YXdhaXQgdGhpcy5wcm9tcHRIYW5kbGVyLnByb21wdEZvclVubG9jaygpO2F3YWl0IHRoaXMudW5sb2NrKGUpfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcihgVW5sb2NrIHJlcXVpcmVkOiAke2UubWVzc2FnZX1gKX19YXN5bmMgdW5sb2NrKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5jb25maWdNYW5hZ2VyLnVubG9jayhlKTthd2FpdCB0aGlzLmFwcGx5Q29uZmlnKHQpfX0hZnVuY3Rpb24oZSl7ZS5JTklUPSJpbml0IixlLkNPTkZJR1VSRT0iY29uZmlndXJlIixlLk1BS0VfUkVRVUVTVD0ibWFrZVJlcXVlc3QiLGUuR0VUX1NUQVRVUz0iZ2V0U3RhdHVzIixlLkxPQ0s9ImxvY2siLGUuUkVTRVQ9InJlc2V0IixlLlVQREFURV9DUkVERU5USUFMUz0idXBkYXRlQ3JlZGVudGlhbHMiLGUuSVNfUkVBRFk9ImlzUmVhZHkiLGUuVU5MT0NLPSJ1bmxvY2siLGUuR0VUX1NFVFVQX1VSTD0iZ2V0U2V0dXBVcmwiLGUuU0VUX0xPQ0FMX01PREU9InNldExvY2FsTW9kZSIsZS5JU19MT0NBTF9NT0RFX0FMTE9XRUQ9ImlzTG9jYWxNb2RlQWxsb3dlZCIsZS5JU19MT0NBTF9NT0RFX0ZPUkNFRD0iaXNMb2NhbE1vZGVGb3JjZWQiLGUuQ09ORklHVVJFX0xPQ0FMPSJjb25maWd1cmVMb2NhbCIsZS5GRVRDSF9NT0RFTFM9ImZldGNoTW9kZWxzIixlLlJFR0lTVEVSX1BST01QVD0icmVnaXN0ZXJQcm9tcHQiLGUuUkVHSVNURVJfUFJPTVBUUz0icmVnaXN0ZXJQcm9tcHRzIixlLkdFVF9QUk9NUFQ9ImdldFByb21wdCIsZS5MSVNUX1BST01QVFM9Imxpc3RQcm9tcHRzIixlLlVQREFURV9QUk9NUFQ9InVwZGF0ZVByb21wdCIsZS5ERUxFVEVfUFJPTVBUPSJkZWxldGVQcm9tcHQiLGUuUkVTRVRfUFJPTVBUPSJyZXNldFByb21wdCIsZS5SRVNPTFZFX0NPTkZMSUNUPSJyZXNvbHZlQ29uZmxpY3QiLGUuUkVOREVSX1BST01QVD0icmVuZGVyUHJvbXB0In0ob3N8fChvcz17fSkpLGZ1bmN0aW9uKGUpe2UuQ09ORklHVVJFPSJjb25maWd1cmUiLGUuVU5MT0NLPSJ1bmxvY2siLGUuTU9ERUxfU0VMRUNUPSJtb2RlbFNlbGVjdCIsZS5QUk9NUFRfQ09ORkxJQ1Q9InByb21wdENvbmZsaWN0In0oaXN8fChpcz17fSkpO2NsYXNzIGZze3N0YXRpYyB2YWxpZGF0ZU1lc3NhZ2UoZSl7cmV0dXJuISghZXx8Im9iamVjdCIhPXR5cGVvZiBlfHwic3RyaW5nIiE9dHlwZW9mIGUuaWR8fDA9PT1lLmlkLmxlbmd0aHx8IU9iamVjdC52YWx1ZXMob3MpLmluY2x1ZGVzKGUuY29tbWFuZCkpfXN0YXRpYyBjcmVhdGVTdWNjZXNzUmVzcG9uc2UoZSx0KXtyZXR1cm57aWQ6ZSxzdWNjZXNzOiEwLGRhdGE6dH19c3RhdGljIGNyZWF0ZUVycm9yUmVzcG9uc2UoZSx0KXtjb25zdCBzPSJzdHJpbmciPT10eXBlb2YgdD90OnQubWVzc2FnZTtyZXR1cm57aWQ6ZSxzdWNjZXNzOiExLGVycm9yOnttZXNzYWdlOnRoaXMuc2FuaXRpemVFcnJvck1lc3NhZ2Uocyl9fX1zdGF0aWMgc2FuaXRpemVFcnJvck1lc3NhZ2UoZSl7cmV0dXJuIGUucmVwbGFjZSgvc2stYW50LVthLXpBLVowLTlfLV0rL2csIltBUElfS0VZX1JFREFDVEVEXSIpLnJlcGxhY2UoL3NrLVthLXpBLVowLTlfLV17NDgsfS9nLCJbQVBJX0tFWV9SRURBQ1RFRF0iKS5yZXBsYWNlKC8oYXBpW18tXT9rZXl8dG9rZW58cGFzc3dvcmR8c2VjcmV0KVs6XHM9XStbXlxzXSsvZ2ksIiQxOiBbUkVEQUNURURdIil9c3RhdGljIGdlbmVyYXRlSWQoKXtyZXR1cm5gJHtEYXRlLm5vdygpfS0ke01hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyLDExKX1gfX1jb25zdCBtcz0iQUVTLUdDTSI7YXN5bmMgZnVuY3Rpb24gZ3MoZSx0KXtjb25zdCBzPW5ldyBUZXh0RW5jb2RlcixyPWF3YWl0IGNyeXB0by5zdWJ0bGUuaW1wb3J0S2V5KCJyYXciLHMuZW5jb2RlKGUpLCJQQktERjIiLCExLFsiZGVyaXZlS2V5Il0pO3JldHVybiBjcnlwdG8uc3VidGxlLmRlcml2ZUtleSh7bmFtZToiUEJLREYyIixzYWx0OnQsaXRlcmF0aW9uczoxZTUsaGFzaDoiU0hBLTI1NiJ9LHIse25hbWU6bXMsbGVuZ3RoOjI1Nn0sITEsWyJlbmNyeXB0IiwiZGVjcnlwdCJdKX1jb25zdCB3cz0iMC4xLjAiLHlzPSJhaS1kZWxlZ2F0ZS1jb25maWciLGJzPTNlNSx2cz0icHJvbXB0cyI7Y2xhc3MgX3N7Y29uc3RydWN0b3IoKXt0aGlzLmRiPW51bGx9YXN5bmMgaW5pdERCKCl7cmV0dXJuIHRoaXMuZGI/dGhpcy5kYjpuZXcgUHJvbWlzZSgoZSx0KT0+e2NvbnN0IHM9aW5kZXhlZERCLm9wZW4oImFpLWRlbGVnYXRlLXByb21wdHMiLDEpO3Mub25lcnJvcj0oKT0+e3QobmV3IEVycm9yKGBGYWlsZWQgdG8gb3BlbiBJbmRleGVkREI6ICR7cy5lcnJvcn1gKSl9LHMub25zdWNjZXNzPSgpPT57dGhpcy5kYj1zLnJlc3VsdCxlKHRoaXMuZGIpfSxzLm9udXBncmFkZW5lZWRlZD1lPT57Y29uc3QgdD1lLnRhcmdldC5yZXN1bHQ7aWYoIXQub2JqZWN0U3RvcmVOYW1lcy5jb250YWlucyh2cykpe2NvbnN0IGU9dC5jcmVhdGVPYmplY3RTdG9yZSh2cyx7a2V5UGF0aDoibmFtZSJ9KTtlLmNyZWF0ZUluZGV4KCJ2ZXJzaW9uIiwidmVyc2lvbiIse3VuaXF1ZTohMX0pLGUuY3JlYXRlSW5kZXgoImxvY2FsbHlNb2RpZmllZCIsImxvY2FsbHlNb2RpZmllZCIse3VuaXF1ZTohMX0pfX19KX1hc3luYyBnZXQoZSl7dHJ5e2NvbnN0IHQ9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pntjb25zdCBuPXQudHJhbnNhY3Rpb24oW3ZzXSwicmVhZG9ubHkiKS5vYmplY3RTdG9yZSh2cykuZ2V0KGUpO24ub25zdWNjZXNzPSgpPT57cyhuLnJlc3VsdD8/bnVsbCl9LG4ub25lcnJvcj0oKT0+e3IobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IHByb21wdDogJHtuLmVycm9yfWApKX19KX1jYXRjaChlKXtyZXR1cm4gY29uc29sZS5lcnJvcigiW1Byb21wdFN0b3JlXSBnZXQgZXJyb3I6IixlKSxudWxsfX1hc3luYyBwdXQoZSl7Y29uc3QgdD1hd2FpdCB0aGlzLmluaXREQigpO3JldHVybiBuZXcgUHJvbWlzZSgocyxyKT0+e2NvbnN0IG49dC50cmFuc2FjdGlvbihbdnNdLCJyZWFkd3JpdGUiKS5vYmplY3RTdG9yZSh2cykucHV0KGUpO24ub25zdWNjZXNzPSgpPT57cygpfSxuLm9uZXJyb3I9KCk9PntyKG5ldyBFcnJvcihgRmFpbGVkIHRvIHNhdmUgcHJvbXB0OiAke24uZXJyb3J9YCkpfX0pfWFzeW5jIGRlbGV0ZShlKXtjb25zdCB0PWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChzLHIpPT57Y29uc3Qgbj10LnRyYW5zYWN0aW9uKFt2c10sInJlYWR3cml0ZSIpLm9iamVjdFN0b3JlKHZzKS5kZWxldGUoZSk7bi5vbnN1Y2Nlc3M9KCk9PntzKCl9LG4ub25lcnJvcj0oKT0+e3IobmV3IEVycm9yKGBGYWlsZWQgdG8gZGVsZXRlIHByb21wdDogJHtuLmVycm9yfWApKX19KX1hc3luYyBsaXN0KCl7Y29uc3QgZT1hd2FpdCB0aGlzLmluaXREQigpO3JldHVybiBuZXcgUHJvbWlzZSgodCxzKT0+e2NvbnN0IHI9ZS50cmFuc2FjdGlvbihbdnNdLCJyZWFkb25seSIpLm9iamVjdFN0b3JlKHZzKS5nZXRBbGwoKTtyLm9uc3VjY2Vzcz0oKT0+e3Qoci5yZXN1bHQ/P1tdKX0sci5vbmVycm9yPSgpPT57cyhuZXcgRXJyb3IoYEZhaWxlZCB0byBsaXN0IHByb21wdHM6ICR7ci5lcnJvcn1gKSl9fSl9YXN5bmMgZXhpc3RzKGUpe3JldHVybiBudWxsIT09YXdhaXQgdGhpcy5nZXQoZSl9YXN5bmMgZ2V0TW9kaWZpZWQoKXtjb25zdCBlPWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKCh0LHMpPT57Y29uc3Qgcj1lLnRyYW5zYWN0aW9uKFt2c10sInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodnMpLmluZGV4KCJsb2NhbGx5TW9kaWZpZWQiKS5nZXRBbGwoSURCS2V5UmFuZ2Uub25seSghMCkpO3Iub25zdWNjZXNzPSgpPT57dChyLnJlc3VsdD8/W10pfSxyLm9uZXJyb3I9KCk9PntzKG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBtb2RpZmllZCBwcm9tcHRzOiAke3IuZXJyb3J9YCkpfX0pfXN0YXRpYyBjcmVhdGVTdG9yZWRQcm9tcHQoZSx0LHMpe2NvbnN0IHI9KG5ldyBEYXRlKS50b0lTT1N0cmluZygpO3JldHVybnsuLi5zLG5hbWU6ZSx2ZXJzaW9uOnQsbG9jYWxseU1vZGlmaWVkOiExLGNyZWF0ZWRBdDpyLHVwZGF0ZWRBdDpyfX1hc3luYyBjbGVhcigpe2NvbnN0IGU9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHQscyk9Pntjb25zdCByPWUudHJhbnNhY3Rpb24oW3ZzXSwicmVhZHdyaXRlIikub2JqZWN0U3RvcmUodnMpLmNsZWFyKCk7ci5vbnN1Y2Nlc3M9KCk9Pnt0KCl9LHIub25lcnJvcj0oKT0+e3MobmV3IEVycm9yKGBGYWlsZWQgdG8gY2xlYXIgcHJvbXB0czogJHtyLmVycm9yfWApKX19KX19Y2xhc3Mga3MgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGBVbmRlZmluZWQgcGFyYW1ldGVyOiAke2V9JHt0P2AgaW4gcHJvbXB0ICIke3R9ImA6IiJ9YCksdGhpcy5wYXJhbU5hbWU9ZSx0aGlzLnByb21wdE5hbWU9dCx0aGlzLm5hbWU9IlVuZGVmaW5lZFBhcmFtRXJyb3IifX1jbGFzcyBTcyBleHRlbmRzIEVycm9ye2NvbnN0cnVjdG9yKGUsdCl7c3VwZXIoYFVucmVmZXJlbmNlZCBwYXJhbWV0ZXI6ICR7ZX0ke3Q/YCBpbiBwcm9tcHQgIiR7dH0iYDoiIn1gKSx0aGlzLnBhcmFtTmFtZT1lLHRoaXMucHJvbXB0TmFtZT10LHRoaXMubmFtZT0iVW5yZWZlcmVuY2VkUGFyYW1FcnJvciJ9fWNsYXNzIE1zIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihgTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXI6ICR7ZX0ke3Q/YCBmb3IgcHJvbXB0ICIke3R9ImA6IiJ9YCksdGhpcy5wYXJhbU5hbWU9ZSx0aGlzLnByb21wdE5hbWU9dCx0aGlzLm5hbWU9Ik1pc3NpbmdQYXJhbUVycm9yIn19Y2xhc3MgUHMgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGBVbmtub3duIHBhcmFtZXRlcjogJHtlfSR7dD9gIGZvciBwcm9tcHQgIiR7dH0iYDoiIn1gKSx0aGlzLnBhcmFtTmFtZT1lLHRoaXMucHJvbXB0TmFtZT10LHRoaXMubmFtZT0iVW5rbm93blBhcmFtRXJyb3IifX1jb25zdCBFcz0vXHsoW2EtekEtWl9dW2EtekEtWjAtOV9dKilcfS9nO2NsYXNzIFJze2V4dHJhY3RQYXJhbXMoZSl7Y29uc3QgdD1bXTtsZXQgcztmb3IoRXMubGFzdEluZGV4PTA7bnVsbCE9PShzPUVzLmV4ZWMoZSkpOyl7Y29uc3QgZT1zWzFdO3QuaW5jbHVkZXMoZSl8fHQucHVzaChlKX1yZXR1cm4gdH12YWxpZGF0ZURlZmluaXRpb24oZSx0KXtjb25zdCBzPXRoaXMuZXh0cmFjdFBhcmFtcyhlLnRlbXBsYXRlKSxyPU9iamVjdC5rZXlzKGUucGFyYW1zPz97fSk7Zm9yKGNvbnN0IGUgb2YgcylpZighci5pbmNsdWRlcyhlKSl0aHJvdyBuZXcga3MoZSx0KTtmb3IoY29uc3QgZSBvZiByKWlmKCFzLmluY2x1ZGVzKGUpKXRocm93IG5ldyBTcyhlLHQpO2lmKGUucm9sZSYmIVsidXNlciIsImFzc2lzdGFudCIsInN5c3RlbSJdLmluY2x1ZGVzKGUucm9sZSkpdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJvbGUgIiR7ZS5yb2xlfSIgZm9yIHByb21wdCR7dD9gICIke3R9ImA6IiJ9YCl9cmVuZGVyKGUsdCxzKXtjb25zdCByPXRoaXMuZXh0cmFjdFBhcmFtcyhlKSxuPXt9O2Zvcihjb25zdCBlIG9mIHIpaWYoZSBpbiBzKW5bZV09c1tlXTtlbHNle2lmKCEoZSBpbiB0KXx8dm9pZCAwPT09dFtlXS5kZWZhdWx0KXRocm93IG5ldyBNcyhlKTtuW2VdPXRbZV0uZGVmYXVsdH1mb3IoY29uc3QgZSBvZiBPYmplY3Qua2V5cyhzKSlpZighci5pbmNsdWRlcyhlKSl0aHJvdyBuZXcgUHMoZSk7cmV0dXJuIGUucmVwbGFjZShFcywoZSx0KT0+blt0XSl9cmVuZGVyV2l0aFNpbmdsZVBhcmFtKGUsdCxzKXtsZXQgcj17fTtpZih2b2lkIDA9PT1zKXI9e307ZWxzZSBpZigic3RyaW5nIj09dHlwZW9mIHMpe2NvbnN0IG49dGhpcy5leHRyYWN0UGFyYW1zKGUpLGE9bi5maWx0ZXIoZT0+IShlIGluIHQpfHx2b2lkIDA9PT10W2VdLmRlZmF1bHQpLG89bi5maWx0ZXIoZT0+ZSBpbiB0JiZ2b2lkIDAhPT10W2VdLmRlZmF1bHQpO2lmKDE9PT1hLmxlbmd0aClyW2FbMF1dPXM7ZWxzZXtpZihhLmxlbmd0aD4xKXRocm93IG5ldyBFcnJvcihgQW1iaWd1b3VzIHNpbmdsZSBwYXJhbWV0ZXI6IG11bHRpcGxlIHJlcXVpcmVkIHBhcmFtcyAoJHthLmpvaW4oIiwgIil9KWApO2lmKDEhPT1vLmxlbmd0aCl0aHJvdyBvLmxlbmd0aD4xP25ldyBFcnJvcihgQW1iaWd1b3VzIHNpbmdsZSBwYXJhbWV0ZXI6IG11bHRpcGxlIG9wdGlvbmFsIHBhcmFtcyAoJHtvLmpvaW4oIiwgIil9KWApOm5ldyBFcnJvcigiUHJvbXB0IHRha2VzIG5vIHBhcmFtZXRlcnMiKTtyW29bMF1dPXN9fWVsc2Ugcj1zO3JldHVybiB0aGlzLnJlbmRlcihlLHQscil9fWNvbnNvbGUubG9nKCJbQUkgRGVsZWdhdGUgV29ya2VyXSBWZXJzaW9uOiAwLjMuNCIpO2NvbnN0IHhzPW5ldyBjbGFzc3tjb25zdHJ1Y3Rvcigpe3RoaXMuZGJOYW1lPSJhaS1kZWxlZ2F0ZS1zdG9yYWdlIix0aGlzLnN0b3JlTmFtZT0iY29uZmlnIix0aGlzLmRiPW51bGx9YXN5bmMgaW5pdERCKCl7cmV0dXJuIHRoaXMuZGI/dGhpcy5kYjpuZXcgUHJvbWlzZSgoZSx0KT0+e2NvbnN0IHM9aW5kZXhlZERCLm9wZW4odGhpcy5kYk5hbWUsMSk7cy5vbmVycm9yPSgpPT57dChuZXcgRXJyb3IoYEZhaWxlZCB0byBvcGVuIEluZGV4ZWREQjogJHtzLmVycm9yfWApKX0scy5vbnN1Y2Nlc3M9KCk9Pnt0aGlzLmRiPXMucmVzdWx0LGUodGhpcy5kYil9LHMub251cGdyYWRlbmVlZGVkPWU9Pntjb25zdCB0PWUudGFyZ2V0LnJlc3VsdDt0Lm9iamVjdFN0b3JlTmFtZXMuY29udGFpbnModGhpcy5zdG9yZU5hbWUpfHx0LmNyZWF0ZU9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKX19KX1hc3luYyBnZXRJdGVtKGUpe3RyeXtjb25zdCB0PWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChzLHIpPT57Y29uc3Qgbj10LnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sInJlYWRvbmx5Iikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmdldChlKTtuLm9uc3VjY2Vzcz0oKT0+e3Mobi5yZXN1bHQ/P251bGwpfSxuLm9uZXJyb3I9KCk9PntyKG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBpdGVtOiAke24uZXJyb3J9YCkpfX0pfWNhdGNoKGUpe3JldHVybiBjb25zb2xlLmVycm9yKCJbSW5kZXhlZERCQWRhcHRlcl0gZ2V0SXRlbSBlcnJvcjoiLGUpLG51bGx9fWFzeW5jIHNldEl0ZW0oZSx0KXtjb25zdCBzPWF3YWl0IHRoaXMuaW5pdERCKCk7cmV0dXJuIG5ldyBQcm9taXNlKChyLG4pPT57Y29uc3QgYT1zLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sInJlYWR3cml0ZSIpLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKS5wdXQodCxlKTthLm9uc3VjY2Vzcz0oKT0+e3IoKX0sYS5vbmVycm9yPSgpPT57bihuZXcgRXJyb3IoYEZhaWxlZCB0byBzZXQgaXRlbTogJHthLmVycm9yfWApKX19KX1hc3luYyByZW1vdmVJdGVtKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5pbml0REIoKTtyZXR1cm4gbmV3IFByb21pc2UoKHMscik9Pntjb25zdCBuPXQudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwicmVhZHdyaXRlIikub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpLmRlbGV0ZShlKTtuLm9uc3VjY2Vzcz0oKT0+e3MoKX0sbi5vbmVycm9yPSgpPT57cihuZXcgRXJyb3IoYEZhaWxlZCB0byByZW1vdmUgaXRlbTogJHtuLmVycm9yfWApKX19KX1hc3luYyBoYXNJdGVtKGUpe3RyeXtyZXR1cm4gbnVsbCE9PWF3YWl0IHRoaXMuZ2V0SXRlbShlKX1jYXRjaChlKXtyZXR1cm4hMX19fSxUcz1uZXcgY2xhc3N7Y29uc3RydWN0b3IoZSl7aWYoInVuZGVmaW5lZCI9PXR5cGVvZiBjcnlwdG98fHZvaWQgMD09PWNyeXB0by5zdWJ0bGV8fCJmdW5jdGlvbiIhPXR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKXRocm93IG5ldyBFcnJvcigiV2ViIENyeXB0byBBUEkgbm90IGF2YWlsYWJsZS4gVGhpcyBsaWJyYXJ5IHJlcXVpcmVzIGEgbW9kZXJuIGJyb3dzZXIgd2l0aCBjcnlwdG8gc3VwcG9ydC4iKTt0aGlzLnN0b3JhZ2U9ZX1hc3luYyBzYXZlKGUsdCxzPSExKXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3N3b3JkIGlzIHJlcXVpcmVkIHRvIHNhdmUgY29uZmlndXJhdGlvbiIpO2NvbnN0IHI9e3Byb3ZpZGVyOmUucHJvdmlkZXIsbW9kZWxzOmUubW9kZWxzLHVzZURlZmF1bHRNb2RlbHM6cyxlbmFibGVDYWNoZTplLmVuYWJsZUNhY2hlPz8hMSxjYWNoZVRUTDplLmNhY2hlVFRMPz9icyx0cmFja1VzYWdlOmUudHJhY2tVc2FnZT8/ITEsdmVyc2lvbjp3c307ZS5jcmVkZW50aWFscyYmKHIuZW5jcnlwdGVkQ3JlZGVudGlhbHM9YXdhaXQgdGhpcy5lbmNyeXB0Q3JlZGVudGlhbHMoZS5jcmVkZW50aWFscyx0KSk7dHJ5e2F3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHIpKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIGNvbmZpZ3VyYXRpb246ICR7ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IifWApfX1hc3luYyBsb2FkTWV0YWRhdGEoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuIG51bGw7Y29uc3QgdD1KU09OLnBhcnNlKGUpO3JldHVybiB0LnZlcnNpb24hPT13cyYmY29uc29sZS53YXJuKGBDb25maWd1cmF0aW9uIHZlcnNpb24gbWlzbWF0Y2guIEV4cGVjdGVkICR7d3N9LCBnb3QgJHt0LnZlcnNpb259YCkse3Byb3ZpZGVyOnQucHJvdmlkZXIsbW9kZWxzOnQubW9kZWxzLGVuYWJsZUNhY2hlOnQuZW5hYmxlQ2FjaGUsY2FjaGVUVEw6dC5jYWNoZVRUTCx0cmFja1VzYWdlOnQudHJhY2tVc2FnZX19Y2F0Y2goZSl7cmV0dXJuIGNvbnNvbGUuZXJyb3IoIkZhaWxlZCB0byBsb2FkIGNvbmZpZ3VyYXRpb246IixlKSxudWxsfX1hc3luYyB1bmxvY2soZSl7aWYoIWV8fDA9PT1lLnRyaW0oKS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJQYXNzd29yZCBpcyByZXF1aXJlZCB0byB1bmxvY2sgY3JlZGVudGlhbHMiKTtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighdCl0aHJvdyBuZXcgRXJyb3IoIk5vIGNvbmZpZ3VyYXRpb24gZm91bmQiKTtjb25zdCBzPUpTT04ucGFyc2UodCk7aWYoIXMuZW5jcnlwdGVkQ3JlZGVudGlhbHMpdGhyb3cgbmV3IEVycm9yKCJObyBlbmNyeXB0ZWQgY3JlZGVudGlhbHMgZm91bmQiKTtjb25zdCByPWF3YWl0IHRoaXMuZGVjcnlwdENyZWRlbnRpYWxzKHMuZW5jcnlwdGVkQ3JlZGVudGlhbHMsZSk7cmV0dXJue3Byb3ZpZGVyOnMucHJvdmlkZXIsbW9kZWxzOnMubW9kZWxzLGVuYWJsZUNhY2hlOnMuZW5hYmxlQ2FjaGUsY2FjaGVUVEw6cy5jYWNoZVRUTCx0cmFja1VzYWdlOnMudHJhY2tVc2FnZSxjcmVkZW50aWFsczpyfX1hc3luYyBjbGVhcigpe2F3YWl0IHRoaXMuc3RvcmFnZS5yZW1vdmVJdGVtKHlzKX1hc3luYyBoYXNDb25maWcoKXtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yYWdlLmhhc0l0ZW0oeXMpfWFzeW5jIHVwZGF0ZUNyZWRlbnRpYWxzKGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLmxvYWRNZXRhZGF0YSgpO2lmKCFzKXRocm93IG5ldyBFcnJvcigiTm8gY29uZmlndXJhdGlvbiBmb3VuZC4gUGxlYXNlIGNvbmZpZ3VyZSB0aGUgcHJvdmlkZXIgZmlyc3QuIik7Y29uc3Qgcj17Li4ucyxjcmVkZW50aWFsczplfTthd2FpdCB0aGlzLnNhdmUocix0KX1hc3luYyBjbGVhckNyZWRlbnRpYWxzKCl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuO2NvbnN0IHQ9SlNPTi5wYXJzZShlKTtkZWxldGUgdC5lbmNyeXB0ZWRDcmVkZW50aWFscyxhd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeSh0KSl9YXN5bmMgaGFzQ3JlZGVudGlhbHMoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIWUpcmV0dXJuITE7Y29uc3QgdD1KU09OLnBhcnNlKGUpO3JldHVybiEhdC5lbmNyeXB0ZWRDcmVkZW50aWFsc3x8ISF0LnBsYWludGV4dENyZWRlbnRpYWxzfWNhdGNoe3JldHVybiExfX1hc3luYyBlbmNyeXB0Q3JlZGVudGlhbHMoZSx0KXtyZXR1cm4gYXN5bmMgZnVuY3Rpb24oZSx0KXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIGVuY3J5cHRpb24iKTtjb25zdCBzPShuZXcgVGV4dEVuY29kZXIpLmVuY29kZShlKSxyPWNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoMTYpKSxuPWNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoMTIpKSxhPWF3YWl0IGdzKHQsciksbz1hd2FpdCBjcnlwdG8uc3VidGxlLmVuY3J5cHQoe25hbWU6bXMsaXY6bn0sYSxzKSxpPW5ldyBVaW50OEFycmF5KDI4K28uYnl0ZUxlbmd0aCk7cmV0dXJuIGkuc2V0KHIsMCksaS5zZXQobiwxNiksaS5zZXQobmV3IFVpbnQ4QXJyYXkobyksMjgpLGJ0b2EoU3RyaW5nLmZyb21DaGFyQ29kZSguLi5pKSl9KEpTT04uc3RyaW5naWZ5KGUpLHQpfWFzeW5jIGRlY3J5cHRDcmVkZW50aWFscyhlLHQpe2NvbnN0IHM9YXdhaXQgYXN5bmMgZnVuY3Rpb24oZSx0KXtpZighdHx8MD09PXQudHJpbSgpLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIlBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIGRlY3J5cHRpb24iKTtjb25zdCBzPVVpbnQ4QXJyYXkuZnJvbShhdG9iKGUpLGU9PmUuY2hhckNvZGVBdCgwKSk7aWYocy5sZW5ndGg8MjgpdGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIGVuY3J5cHRlZCBkYXRhIGZvcm1hdCIpO2NvbnN0IHI9cy5zbGljZSgwLDE2KSxuPXMuc2xpY2UoMTYsMjgpLGE9cy5zbGljZSgyOCksbz1hd2FpdCBncyh0LHIpO3RyeXtjb25zdCBlPWF3YWl0IGNyeXB0by5zdWJ0bGUuZGVjcnlwdCh7bmFtZTptcyxpdjpufSxvLGEpO3JldHVybihuZXcgVGV4dERlY29kZXIpLmRlY29kZShlKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoIkRlY3J5cHRpb24gZmFpbGVkLiBJbnZhbGlkIHBhc3NwaHJhc2Ugb3IgY29ycnVwdGVkIGRhdGEuIil9fShlLHQpO3JldHVybiBKU09OLnBhcnNlKHMpfWFzeW5jIHNldE1vZGVsRm9yV2VpZ2h0KGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIXMpdGhyb3cgbmV3IEVycm9yKCJObyBjb25maWd1cmF0aW9uIGZvdW5kLiBQbGVhc2UgY29uZmlndXJlIHRoZSBwcm92aWRlciBmaXJzdC4iKTtjb25zdCByPUpTT04ucGFyc2Uocyk7ci5tb2RlbHN8fChyLm1vZGVscz17fSksci5tb2RlbHNbZV09dCxhd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeShyKSl9YXN5bmMgZ2V0TW9kZWxGb3JXZWlnaHQoZSl7Y29uc3QgdD1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7aWYoIXQpcmV0dXJuO2NvbnN0IHM9SlNPTi5wYXJzZSh0KTtyZXR1cm4gcy5tb2RlbHM/LltlXX1hc3luYyBzZXRVc2VEZWZhdWx0TW9kZWxzKGUpe2NvbnN0IHQ9YXdhaXQgdGhpcy5zdG9yYWdlLmdldEl0ZW0oeXMpO2lmKCF0KXRocm93IG5ldyBFcnJvcigiTm8gY29uZmlndXJhdGlvbiBmb3VuZC4gUGxlYXNlIGNvbmZpZ3VyZSB0aGUgcHJvdmlkZXIgZmlyc3QuIik7Y29uc3Qgcz1KU09OLnBhcnNlKHQpO3MudXNlRGVmYXVsdE1vZGVscz1lLGF3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHMpKX1hc3luYyBnZXRVc2VEZWZhdWx0TW9kZWxzKCl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7cmV0dXJuISFlJiYoSlNPTi5wYXJzZShlKS51c2VEZWZhdWx0TW9kZWxzPz8hMSl9YXN5bmMgc2F2ZU1ldGFkYXRhKGUsdCxzPSEwKXtjb25zdCByPXtwcm92aWRlcjplLG1vZGVsczp0LHVzZURlZmF1bHRNb2RlbHM6cyxlbmFibGVDYWNoZTohMSxjYWNoZVRUTDpicyx0cmFja1VzYWdlOiExLHZlcnNpb246d3N9O3RyeXthd2FpdCB0aGlzLnN0b3JhZ2Uuc2V0SXRlbSh5cyxKU09OLnN0cmluZ2lmeShyKSl9Y2F0Y2goZSl7dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gc2F2ZSBjb25maWd1cmF0aW9uOiAke2U/Lm1lc3NhZ2V8fCJVbmtub3duIGVycm9yIn1gKX19YXN5bmMgc2F2ZUxvY2FsKGUsdCxzPSExKXtjb25zdCByPXtwcm92aWRlcjplLnByb3ZpZGVyLG1vZGVsczplLm1vZGVscyx1c2VEZWZhdWx0TW9kZWxzOnMsZW5hYmxlQ2FjaGU6ZS5lbmFibGVDYWNoZT8/ITEsY2FjaGVUVEw6ZS5jYWNoZVRUTD8/YnMsdHJhY2tVc2FnZTplLnRyYWNrVXNhZ2U/PyExLGZvcmNlTG9jYWxNb2RlOiEwLHZlcnNpb246d3N9O2UuY3JlZGVudGlhbHMmJih0JiZ0LnRyaW0oKS5sZW5ndGg+MD9yLmVuY3J5cHRlZENyZWRlbnRpYWxzPWF3YWl0IHRoaXMuZW5jcnlwdENyZWRlbnRpYWxzKGUuY3JlZGVudGlhbHMsdCk6ci5wbGFpbnRleHRDcmVkZW50aWFscz1KU09OLnN0cmluZ2lmeShlLmNyZWRlbnRpYWxzKSk7dHJ5e2F3YWl0IHRoaXMuc3RvcmFnZS5zZXRJdGVtKHlzLEpTT04uc3RyaW5naWZ5KHIpKX1jYXRjaChlKXt0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIGNvbmZpZ3VyYXRpb246ICR7ZT8ubWVzc2FnZXx8IlVua25vd24gZXJyb3IifWApfX1hc3luYyBnZXRQbGFpbnRleHRDcmVkZW50aWFscygpe3RyeXtjb25zdCBlPWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighZSlyZXR1cm4gbnVsbDtjb25zdCB0PUpTT04ucGFyc2UoZSk7cmV0dXJuIHQucGxhaW50ZXh0Q3JlZGVudGlhbHM/SlNPTi5wYXJzZSh0LnBsYWludGV4dENyZWRlbnRpYWxzKTpudWxsfWNhdGNoe3JldHVybiBudWxsfX1hc3luYyBoYXNQbGFpbnRleHRDcmVkZW50aWFscygpe3RyeXtjb25zdCBlPWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtyZXR1cm4hIWUmJiEhSlNPTi5wYXJzZShlKS5wbGFpbnRleHRDcmVkZW50aWFsc31jYXRjaHtyZXR1cm4hMX19YXN5bmMgZ2V0Rm9yY2VMb2NhbE1vZGUoKXt0cnl7Y29uc3QgZT1hd2FpdCB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh5cyk7cmV0dXJuISFlJiYoSlNPTi5wYXJzZShlKS5mb3JjZUxvY2FsTW9kZT8/ITEpfWNhdGNoe3JldHVybiExfX1hc3luYyBzZXRGb3JjZUxvY2FsTW9kZShlKXtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHlzKTtpZighdCl7Y29uc3QgdD17cHJvdmlkZXI6ImFudGhyb3BpYyIsdXNlRGVmYXVsdE1vZGVsczohMCxlbmFibGVDYWNoZTohMSxjYWNoZVRUTDpicyx0cmFja1VzYWdlOiExLGZvcmNlTG9jYWxNb2RlOmUsdmVyc2lvbjp3c307cmV0dXJuIHZvaWQgYXdhaXQgdGhpcy5zdG9yYWdlLnNldEl0ZW0oeXMsSlNPTi5zdHJpbmdpZnkodCkpfWNvbnN0IHM9SlNPTi5wYXJzZSh0KTtzLmZvcmNlTG9jYWxNb2RlPWUsYXdhaXQgdGhpcy5zdG9yYWdlLnNldEl0ZW0oeXMsSlNPTi5zdHJpbmdpZnkocykpfX0oeHMpLEFzPW5ldyBjbGFzc3tjb25zdHJ1Y3RvcihlKXt0aGlzLnBlbmRpbmdDb25mbGljdHM9bmV3IE1hcCx0aGlzLnN0b3JlPWU/P25ldyBfcyx0aGlzLnRlbXBsYXRlRW5naW5lPW5ldyBSc31hc3luYyByZWdpc3RlclByb21wdChlKXtjb25zdHtuYW1lOnQsdmVyc2lvbjpzLHByb21wdDpyfT1lO3RoaXMudGVtcGxhdGVFbmdpbmUudmFsaWRhdGVEZWZpbml0aW9uKHIpO2NvbnN0IG49YXdhaXQgdGhpcy5zdG9yZS5nZXQodCk7aWYoIW4pe2NvbnN0IGU9X3MuY3JlYXRlU3RvcmVkUHJvbXB0KHQscyxyKTtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yZS5wdXQoZSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBDcmVhdGVkIHByb21wdCAiJHt0fSIgdiR7c31gKSx7c3RhdHVzOiJjcmVhdGVkIixwcm9tcHQ6ZX19Y29uc3QgYT1mdW5jdGlvbihlLHQpe2NvbnN0IHM9ZS5zcGxpdCgiLiIpLm1hcChOdW1iZXIpLHI9dC5zcGxpdCgiLiIpLm1hcChOdW1iZXIpO2ZvcihsZXQgZT0wO2U8TWF0aC5tYXgocy5sZW5ndGgsci5sZW5ndGgpO2UrKyl7Y29uc3QgdD1zW2VdPz8wLG49cltlXT8/MDtpZih0PG4pcmV0dXJuLTE7aWYodD5uKXJldHVybiAxfXJldHVybiAwfShzLG4udmVyc2lvbik7aWYoMD09PWEpcmV0dXJuIGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gUHJvbXB0ICIke3R9IiB1bmNoYW5nZWQgKHYke3N9KWApLHtzdGF0dXM6InVuY2hhbmdlZCIscHJvbXB0Om59O2lmKGE8MClyZXR1cm4gY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBQcm9tcHQgIiR7dH0iIG5vdCBkb3duZ3JhZGVkICh2JHtuLnZlcnNpb259ID4gdiR7c30pYCkse3N0YXR1czoidW5jaGFuZ2VkIixwcm9tcHQ6bn07aWYoIW4ubG9jYWxseU1vZGlmaWVkKXtjb25zdCBlPW4udmVyc2lvbixhPXsuLi5yLG5hbWU6dCx2ZXJzaW9uOnMsbG9jYWxseU1vZGlmaWVkOiExLGNyZWF0ZWRBdDpuLmNyZWF0ZWRBdCx1cGRhdGVkQXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpfTtyZXR1cm4gYXdhaXQgdGhpcy5zdG9yZS5wdXQoYSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBBdXRvLXVwZGF0ZWQgIiR7dH0iIHYke2V9IC0+IHYke3N9YCkse3N0YXR1czoidXBkYXRlZCIscHJvbXB0OmEscHJldmlvdXNWZXJzaW9uOmV9fWNvbnN0IG89e25hbWU6dCxsb2NhbFZlcnNpb246bi52ZXJzaW9uLHVwc3RyZWFtVmVyc2lvbjpzLGxvY2FsUHJvbXB0Om4sdXBzdHJlYW1Qcm9tcHQ6cn07cmV0dXJuIHRoaXMucGVuZGluZ0NvbmZsaWN0cy5zZXQodCxvKSxjb25zb2xlLmxvZyhgW1Byb21wdE1hbmFnZXJdIFZlcnNpb24gY29uZmxpY3QgZm9yICIke3R9IjogbG9jYWwgdiR7bi52ZXJzaW9ufSAobW9kaWZpZWQpIHZzIHVwc3RyZWFtIHYke3N9YCkse3N0YXR1czoiY29uZmxpY3QiLGNvbmZsaWN0Om99fWFzeW5jIHJlZ2lzdGVyUHJvbXB0cyhlKXtjb25zdCB0PVtdO2Zvcihjb25zdCBzIG9mIGUpe2NvbnN0IGU9YXdhaXQgdGhpcy5yZWdpc3RlclByb21wdChzKTt0LnB1c2goZSl9cmV0dXJuIHR9YXN5bmMgZ2V0UHJvbXB0KGUpe3JldHVybiB0aGlzLnN0b3JlLmdldChlKX1hc3luYyBsaXN0UHJvbXB0cygpe3JldHVybiB0aGlzLnN0b3JlLmxpc3QoKX1hc3luYyB1cGRhdGVQcm9tcHQoZSx0KXt0aGlzLnRlbXBsYXRlRW5naW5lLnZhbGlkYXRlRGVmaW5pdGlvbih0KTtjb25zdCBzPWF3YWl0IHRoaXMuc3RvcmUuZ2V0KGUpO2lmKCFzKXRocm93IG5ldyBFcnJvcihgUHJvbXB0ICIke2V9IiBub3QgZm91bmRgKTtjb25zdCByPXsuLi50LG5hbWU6ZSx2ZXJzaW9uOnMudmVyc2lvbixsb2NhbGx5TW9kaWZpZWQ6ITAsdXBzdHJlYW1WZXJzaW9uOnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1WZXJzaW9uOnMudmVyc2lvbix1cHN0cmVhbVRlbXBsYXRlOnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1UZW1wbGF0ZTpzLnRlbXBsYXRlLHVwc3RyZWFtV2VpZ2h0OnMubG9jYWxseU1vZGlmaWVkP3MudXBzdHJlYW1XZWlnaHQ6cy53ZWlnaHQsY3JlYXRlZEF0OnMuY3JlYXRlZEF0LHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHIpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gVXNlciBtb2RpZmllZCBwcm9tcHQgIiR7ZX0iYCl9YXN5bmMgZGVsZXRlUHJvbXB0KGUpe2F3YWl0IHRoaXMuc3RvcmUuZGVsZXRlKGUpLHRoaXMucGVuZGluZ0NvbmZsaWN0cy5kZWxldGUoZSksY29uc29sZS5sb2coYFtQcm9tcHRNYW5hZ2VyXSBEZWxldGVkIHByb21wdCAiJHtlfSJgKX1hc3luYyByZXNvbHZlQ29uZmxpY3QoZSx0LHMscil7Y29uc3Qgbj1hd2FpdCB0aGlzLnN0b3JlLmdldChlKTtpZighbil0aHJvdyBuZXcgRXJyb3IoYFByb21wdCAiJHtlfSIgbm90IGZvdW5kYCk7aWYoImxvY2FsIj09PXQpe2NvbnN0IHQ9ey4uLm4sdXBzdHJlYW1WZXJzaW9uOnIsdXBzdHJlYW1UZW1wbGF0ZTpzLnRlbXBsYXRlLHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHQpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gQ29uZmxpY3QgcmVzb2x2ZWQgZm9yICIke2V9Ijoga2VwdCBsb2NhbCB2ZXJzaW9uYCl9ZWxzZXtjb25zdCB0PXsuLi5zLG5hbWU6ZSx2ZXJzaW9uOnIsbG9jYWxseU1vZGlmaWVkOiExLHVwc3RyZWFtVmVyc2lvbjp2b2lkIDAsdXBzdHJlYW1UZW1wbGF0ZTp2b2lkIDAsY3JlYXRlZEF0Om4uY3JlYXRlZEF0LHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHQpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gQ29uZmxpY3QgcmVzb2x2ZWQgZm9yICIke2V9IjogYWNjZXB0ZWQgdXBzdHJlYW0gdiR7cn1gKX10aGlzLnBlbmRpbmdDb25mbGljdHMuZGVsZXRlKGUpfWFzeW5jIHJlc2V0VG9VcHN0cmVhbShlKXtjb25zdCB0PWF3YWl0IHRoaXMuc3RvcmUuZ2V0KGUpO2lmKCF0KXRocm93IG5ldyBFcnJvcihgUHJvbXB0ICIke2V9IiBub3QgZm91bmRgKTtpZighdC5sb2NhbGx5TW9kaWZpZWR8fCF0LnVwc3RyZWFtVGVtcGxhdGUpdGhyb3cgbmV3IEVycm9yKGBQcm9tcHQgIiR7ZX0iIGhhcyBubyBvcmlnaW5hbCB2ZXJzaW9uIHRvIHJlc2V0IHRvYCk7Y29uc3Qgcz17Li4udCx0ZW1wbGF0ZTp0LnVwc3RyZWFtVGVtcGxhdGUsd2VpZ2h0OnQudXBzdHJlYW1XZWlnaHQsbG9jYWxseU1vZGlmaWVkOiExLHVwc3RyZWFtVmVyc2lvbjp2b2lkIDAsdXBzdHJlYW1UZW1wbGF0ZTp2b2lkIDAsdXBzdHJlYW1XZWlnaHQ6dm9pZCAwLHVwZGF0ZWRBdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCl9O2F3YWl0IHRoaXMuc3RvcmUucHV0KHMpLGNvbnNvbGUubG9nKGBbUHJvbXB0TWFuYWdlcl0gUmVzZXQgcHJvbXB0ICIke2V9IiB0byB1cHN0cmVhbSB2ZXJzaW9uYCl9YXN5bmMgcmVuZGVyUHJvbXB0KGUsdCl7Y29uc3Qgcz1hd2FpdCB0aGlzLnN0b3JlLmdldChlKTtpZighcyl0aHJvdyBuZXcgRXJyb3IoYFByb21wdCAiJHtlfSIgbm90IGZvdW5kYCk7Y29uc3Qgcj10aGlzLnRlbXBsYXRlRW5naW5lLnJlbmRlcihzLnRlbXBsYXRlLHMucGFyYW1zPz97fSx0Pz97fSk7cmV0dXJue3JvbGU6cy5yb2xlPz8idXNlciIsY29udGVudDpyLGV4cGVjdF90YWdzOnMuZXhwZWN0X3RhZ3Msd2VpZ2h0OnMud2VpZ2h0LHByb21wdE5hbWU6ZX19Z2V0UGVuZGluZ0NvbmZsaWN0KGUpe3JldHVybiB0aGlzLnBlbmRpbmdDb25mbGljdHMuZ2V0KGUpfWhhc1BlbmRpbmdDb25mbGljdHMoKXtyZXR1cm4gdGhpcy5wZW5kaW5nQ29uZmxpY3RzLnNpemU+MH1nZXRQZW5kaW5nQ29uZmxpY3RzKCl7cmV0dXJuIEFycmF5LmZyb20odGhpcy5wZW5kaW5nQ29uZmxpY3RzLnZhbHVlcygpKX19O2xldCBDcz1udWxsLElzPSExO2Z1bmN0aW9uIE9zKGUsdCl7SXN8fChDcz1wcy5nZXRJbnN0YW5jZShUcyxlLHQpLENzLnNldFByb21wdEhhbmRsZXIoRHMpLElzPSEwLGNvbnNvbGUubG9nKCJbQUkgRGVsZWdhdGUgV29ya2VyXSBJbml0aWFsaXplZCB3aXRoIGNyZWRlbnRpYWwgc2VydmVyOiIsZXx8Iihub3QgY29uZmlndXJlZCkiLCJhbGxvd0xvY2FsTW9kZToiLHQpKX1mdW5jdGlvbiAkcygpe3JldHVybiBDc3x8T3MoKSxDc31jb25zdCBMcz1uZXcgTWFwO2FzeW5jIGZ1bmN0aW9uIE5zKGUsdCl7Y29uc3Qgcz1mcy5nZW5lcmF0ZUlkKCk7cmV0dXJuIG5ldyBQcm9taXNlKChyLG4pPT57THMuc2V0KHMse3Jlc29sdmU6cixyZWplY3Q6bn0pO2NvbnN0IGE9e3R5cGU6InByb21wdCIscHJvbXB0VHlwZTplLHJlcXVlc3RJZDpzLGRhdGE6dH07c2VsZi5wb3N0TWVzc2FnZShhKSxzZXRUaW1lb3V0KCgpPT57THMuaGFzKHMpJiYoTHMuZGVsZXRlKHMpLG4obmV3IEVycm9yKCJQcm9tcHQgdGltZW91dCAtIHVzZXIgZGlkIG5vdCByZXNwb25kIikpKX0sM2U1KX0pfWNvbnN0IERzPXthc3luYyBwcm9tcHRGb3JDb25maWd1cmF0aW9uKCl7Y29uc3QgZT1hd2FpdCBOcyhpcy5DT05GSUdVUkUpLHtwYXNzd29yZDp0LHVzZURlZmF1bHRNb2RlbHM6cywuLi5yfT1lO3JldHVybntjb25maWc6cixwYXNzd29yZDp0LHVzZURlZmF1bHRNb2RlbHM6cz8/ITF9fSxwcm9tcHRGb3JVbmxvY2s6YXN5bmMoKT0+YXdhaXQgTnMoaXMuVU5MT0NLKSxwcm9tcHRGb3JNb2RlbFNlbGVjdGlvbjphc3luYyhlLHQpPT5hd2FpdCBOcyhpcy5NT0RFTF9TRUxFQ1Qse3dlaWdodDplLGF2YWlsYWJsZU1vZGVsczp0fSkscHJvbXB0Rm9yQ29uZmxpY3RSZXNvbHV0aW9uOmFzeW5jIGU9PmF3YWl0IE5zKGlzLlBST01QVF9DT05GTElDVCxlKX07c2VsZi5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIixhc3luYyBlPT57Y29uc3QgdD1lLmRhdGE7aWYoInByb21wdFJlc3BvbnNlIj09PXQudHlwZSl7Y29uc3QgZT10LHM9THMuZ2V0KGUucmVxdWVzdElkKTtyZXR1cm4gdm9pZChzJiYoTHMuZGVsZXRlKGUucmVxdWVzdElkKSxlLnN1Y2Nlc3M/cy5yZXNvbHZlKGUuZGF0YSk6cy5yZWplY3QobmV3IEVycm9yKGUuZXJyb3J8fCJQcm9tcHQgZmFpbGVkIikpKSl9aWYoIWZzLnZhbGlkYXRlTWVzc2FnZSh0KSl7Y29uc3QgZT1mcy5jcmVhdGVFcnJvclJlc3BvbnNlKHQ/LmlkfHwidW5rbm93biIsIkludmFsaWQgbWVzc2FnZSBmb3JtYXQiKTtyZXR1cm4gdm9pZCBzZWxmLnBvc3RNZXNzYWdlKGUpfXRyeXtjb25zdCBlPWF3YWl0IGFzeW5jIGZ1bmN0aW9uKGUpe2NvbnN0e2lkOnQsY29tbWFuZDpzLHBheWxvYWQ6cn09ZTtzd2l0Y2gocyl7Y2FzZSBvcy5JTklUOnJldHVybiBPcyhyLmNyZWRlbnRpYWxTZXJ2ZXJVcmwsci5hbGxvd0xvY2FsTW9kZSksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQpO2Nhc2Ugb3MuQ09ORklHVVJFOnJldHVybiBhd2FpdCAkcygpLmNvbmZpZ3VyZShyLmNvbmZpZyxyLnBhc3N3b3JkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5NQUtFX1JFUVVFU1Q6ci5vcHRpb25zLnN0cmVhbSYmKHIub3B0aW9ucy5vblN0cmVhbT1lPT57Y29uc3Qgcz17dHlwZToic3RyZWFtQ2h1bmsiLHJlcXVlc3RJZDp0LGNodW5rOmV9O3NlbGYucG9zdE1lc3NhZ2Uocyl9KTtjb25zdCBlPWF3YWl0ICRzKCkubWFrZVJlcXVlc3Qoci5vcHRpb25zKTtpZihyLm9wdGlvbnMuc3RyZWFtKXtjb25zdCBlPXt0eXBlOiJzdHJlYW1Db21wbGV0ZSIscmVxdWVzdElkOnR9O3NlbGYucG9zdE1lc3NhZ2UoZSl9cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGUpO2Nhc2Ugb3MuR0VUX1NUQVRVUzpjb25zb2xlLmxvZygiW1dvcmtlcl0gR0VUX1NUQVRVUyBjYWxsZWQsIGRlbGVnYXRlIGluaXRpYWxpemVkOiIsSXMpO2NvbnN0IG49YXdhaXQgJHMoKS5nZXRTdGF0dXMoKTtyZXR1cm4gY29uc29sZS5sb2coIltXb3JrZXJdIEdFVF9TVEFUVVMgcmVzdWx0OiIsbiksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsbik7Y2FzZSBvcy5MT0NLOnJldHVybiBhd2FpdCAkcygpLmxvY2soKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5SRVNFVDpyZXR1cm4gYXdhaXQgJHMoKS5yZXNldCgpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLlVQREFURV9DUkVERU5USUFMUzpyZXR1cm4gYXdhaXQgJHMoKS51cGRhdGVDcmVkZW50aWFscyhyLmNyZWRlbnRpYWxzLHIucGFzc3dvcmQpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLklTX1JFQURZOmNvbnN0IGE9YXdhaXQgJHMoKS5pc1JlYWR5KCk7cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGEpO2Nhc2Ugb3MuVU5MT0NLOnJldHVybiBhd2FpdCAkcygpLnVubG9jayhyLnBhc3N3b3JkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5HRVRfU0VUVVBfVVJMOmNvbnN0IG89JHMoKS5nZXRDcmVkZW50aWFsU2VydmVyU2V0dXBVcmwoKTtyZXR1cm4gZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsbyk7Y2FzZSBvcy5GRVRDSF9NT0RFTFM6Y29uc3QgaT1hd2FpdCAkcygpLmZldGNoQXZhaWxhYmxlTW9kZWxzKCk7cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGkpO2Nhc2Ugb3MuU0VUX0xPQ0FMX01PREU6cmV0dXJuIGF3YWl0ICRzKCkuc2V0Rm9yY2VMb2NhbE1vZGUoci5lbmFibGVkKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5JU19MT0NBTF9NT0RFX0FMTE9XRUQ6Y29uc3QgYz0kcygpLmlzTG9jYWxNb2RlQWxsb3dlZCgpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxjKTtjYXNlIG9zLklTX0xPQ0FMX01PREVfRk9SQ0VEOmNvbnN0IGw9JHMoKS5pc0xvY2FsTW9kZUZvcmNlZCgpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxsKTtjYXNlIG9zLkNPTkZJR1VSRV9MT0NBTDpjb25zb2xlLmxvZygiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIHJlY2VpdmVkOiIse2NvbmZpZzpyLmNvbmZpZyxoYXNQYXNzd29yZDohIXIucGFzc3dvcmQsdXNlRGVmYXVsdE1vZGVsczpyLnVzZURlZmF1bHRNb2RlbHN9KTt0cnl7cmV0dXJuIGF3YWl0ICRzKCkuY29uZmlndXJlTG9jYWwoci5jb25maWcsci5wYXNzd29yZCxyLnVzZURlZmF1bHRNb2RlbHM/PyEwKSxjb25zb2xlLmxvZygiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkiKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCl9Y2F0Y2goZSl7dGhyb3cgY29uc29sZS5lcnJvcigiW1dvcmtlcl0gQ09ORklHVVJFX0xPQ0FMIGVycm9yOiIsZSxlLm1lc3NhZ2UsZS5zdGFjayksZX1jYXNlIG9zLlJFR0lTVEVSX1BST01QVDp7Y29uc3QgZT1hd2FpdCBBcy5yZWdpc3RlclByb21wdChyLnJlZ2lzdHJhdGlvbik7aWYoImNvbmZsaWN0Ij09PWUuc3RhdHVzKXtjb25zdCBzPWF3YWl0IERzLnByb21wdEZvckNvbmZsaWN0UmVzb2x1dGlvbihlLmNvbmZsaWN0KTthd2FpdCBBcy5yZXNvbHZlQ29uZmxpY3QoZS5jb25mbGljdC5uYW1lLHMsZS5jb25mbGljdC51cHN0cmVhbVByb21wdCxlLmNvbmZsaWN0LnVwc3RyZWFtVmVyc2lvbik7Y29uc3Qgcj1hd2FpdCBBcy5nZXRQcm9tcHQoZS5jb25mbGljdC5uYW1lKTtyZXR1cm4idXBzdHJlYW0iPT09cz9mcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCx7c3RhdHVzOiJ1cGRhdGVkIixwcm9tcHQ6cixwcmV2aW91c1ZlcnNpb246ZS5jb25mbGljdC5sb2NhbFZlcnNpb259KTpmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCx7c3RhdHVzOiJ1bmNoYW5nZWQiLHByb21wdDpyfSl9cmV0dXJuIGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0LGUpfWNhc2Ugb3MuUkVHSVNURVJfUFJPTVBUUzp7Y29uc3QgZT1bXTtmb3IoY29uc3QgdCBvZiByLnJlZ2lzdHJhdGlvbnMpe2NvbnN0IHM9YXdhaXQgQXMucmVnaXN0ZXJQcm9tcHQodCk7aWYoImNvbmZsaWN0Ij09PXMuc3RhdHVzKXtjb25zdCB0PWF3YWl0IERzLnByb21wdEZvckNvbmZsaWN0UmVzb2x1dGlvbihzLmNvbmZsaWN0KTthd2FpdCBBcy5yZXNvbHZlQ29uZmxpY3Qocy5jb25mbGljdC5uYW1lLHQscy5jb25mbGljdC51cHN0cmVhbVByb21wdCxzLmNvbmZsaWN0LnVwc3RyZWFtVmVyc2lvbik7Y29uc3Qgcj1hd2FpdCBBcy5nZXRQcm9tcHQocy5jb25mbGljdC5uYW1lKTsidXBzdHJlYW0iPT09dD9lLnB1c2goe3N0YXR1czoidXBkYXRlZCIscHJvbXB0OnIscHJldmlvdXNWZXJzaW9uOnMuY29uZmxpY3QubG9jYWxWZXJzaW9ufSk6ZS5wdXNoKHtzdGF0dXM6InVuY2hhbmdlZCIscHJvbXB0OnJ9KX1lbHNlIGUucHVzaChzKX1yZXR1cm4gZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQsZSl9Y2FzZSBvcy5HRVRfUFJPTVBUOntjb25zdCBlPWF3YWl0IEFzLmdldFByb21wdChyLm5hbWUpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1jYXNlIG9zLkxJU1RfUFJPTVBUUzp7Y29uc3QgZT1hd2FpdCBBcy5saXN0UHJvbXB0cygpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1jYXNlIG9zLlVQREFURV9QUk9NUFQ6cmV0dXJuIGF3YWl0IEFzLnVwZGF0ZVByb21wdChyLm5hbWUsci5wcm9tcHQpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLkRFTEVURV9QUk9NUFQ6cmV0dXJuIGF3YWl0IEFzLmRlbGV0ZVByb21wdChyLm5hbWUpLGZzLmNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh0KTtjYXNlIG9zLlJFU0VUX1BST01QVDpyZXR1cm4gYXdhaXQgQXMucmVzZXRUb1Vwc3RyZWFtKHIubmFtZSksZnMuY3JlYXRlU3VjY2Vzc1Jlc3BvbnNlKHQpO2Nhc2Ugb3MuUkVTT0xWRV9DT05GTElDVDpyZXR1cm4gYXdhaXQgQXMucmVzb2x2ZUNvbmZsaWN0KHIubmFtZSxyLmNob2ljZSxyLnVwc3RyZWFtUHJvbXB0LHIudXBzdHJlYW1WZXJzaW9uKSxmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCk7Y2FzZSBvcy5SRU5ERVJfUFJPTVBUOntjb25zdCBlPWF3YWl0IEFzLnJlbmRlclByb21wdChyLm5hbWUsci5wYXJhbXMpO3JldHVybiBmcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UodCxlKX1kZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVW5rbm93biBjb21tYW5kOiAke3N9YCl9fSh0KTtzZWxmLnBvc3RNZXNzYWdlKGUpfWNhdGNoKGUpe2NvbnN0IHM9ZnMuY3JlYXRlRXJyb3JSZXNwb25zZSh0LmlkLGUpO3NlbGYucG9zdE1lc3NhZ2Uocyl9fSksY29uc29sZS5sb2coIltBSSBEZWxlZ2F0ZSBXb3JrZXJdIFJlYWR5IHRvIHJlY2VpdmUgY29tbWFuZHMiKX0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPWFpLWRlbGVnYXRlLXdvcmtlci5qcy5tYXA='; - -/** - * Decode the base64-encoded worker source. - */ -function decodeWorkerSource(): string { - // Use atob for browser environment - if (typeof atob === 'function') { - return atob(EMBEDDED_WORKER_BASE64); - } - // Fallback for Node.js environment (for testing) - return Buffer.from(EMBEDDED_WORKER_BASE64, 'base64').toString('utf8'); -} - -/** - * The worker source code as a string. - * Lazily decoded on first access. - */ -let _cachedSource: string | null = null; -export function getWorkerSource(): string { - if (_cachedSource === null) { - _cachedSource = decodeWorkerSource(); - } - return _cachedSource; -} - -/** - * Creates a Blob URL for the embedded worker. - * The URL should be revoked with URL.revokeObjectURL() when no longer needed. - */ -export function createWorkerBlobUrl(): string { - const source = getWorkerSource(); - const blob = new Blob([source], { type: 'application/javascript' }); - return URL.createObjectURL(blob); -} - -/** - * Version marker to help with debugging cache issues. - * This is extracted from the worker bundle if present. - */ -export const EMBEDDED_WORKER_VERSION: string = '0.3.4'; -- GitLab From 076729ea043300aedf379fa461bfa807ca7df4c2 Mon Sep 17 00:00:00 2001 From: Lembot Date: Fri, 9 Jan 2026 17:54:12 -0500 Subject: [PATCH 3/3] fix: create embedded-worker stub before build Add a prebuild script that creates a placeholder embedded-worker.ts if it doesn't exist. This fixes CI builds that fail because TypeScript can't find the module that gets generated during the build. Co-Authored-By: Claude Opus 4.5 --- package.json | 3 ++- scripts/ensure-embedded-stub.js | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 scripts/ensure-embedded-stub.js diff --git a/package.json b/package.json index c16c13c..38a7c1f 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,9 @@ "dist" ], "scripts": { + "prebuild": "node scripts/ensure-embedded-stub.js", "build": "npm run build:worker && npm run embed-worker && npm run build:main && npm run build:types", - "build:dev": "npm run build:worker:dev && npm run embed-worker && npm run build:main:dev && npm run build:types", + "build:dev": "node scripts/ensure-embedded-stub.js && npm run build:worker:dev && npm run embed-worker && npm run build:main:dev && npm run build:types", "build:worker": "webpack --mode production --config webpack.worker.config.js", "build:worker:dev": "webpack --mode development --config webpack.worker.config.js", "build:main": "webpack --mode production --config webpack.main.config.js", diff --git a/scripts/ensure-embedded-stub.js b/scripts/ensure-embedded-stub.js new file mode 100644 index 0000000..223e0d3 --- /dev/null +++ b/scripts/ensure-embedded-stub.js @@ -0,0 +1,37 @@ +#!/usr/bin/env node +/** + * Creates a stub embedded-worker.ts if it doesn't exist. + * This allows the TypeScript compilation to succeed before the + * real embedded worker is generated. + */ + +const fs = require('fs'); +const path = require('path'); + +const OUTPUT_PATH = path.resolve(__dirname, '../src/worker/embedded-worker.ts'); + +if (fs.existsSync(OUTPUT_PATH)) { + console.log('[ensure-embedded-stub] embedded-worker.ts already exists, skipping.'); + process.exit(0); +} + +const stub = `/** + * PLACEHOLDER - AUTO-GENERATED + * This stub is created before the build and will be replaced + * by the real embedded worker after build:worker completes. + */ + +export const EMBEDDED_WORKER_VERSION: string = '0.0.0-stub'; + +export function createWorkerBlobUrl(): string { + throw new Error('Worker not yet embedded - this is a build-time stub'); +} + +export function getWorkerSource(): string { + throw new Error('Worker not yet embedded - this is a build-time stub'); +} +`; + +console.log('[ensure-embedded-stub] Creating placeholder embedded-worker.ts...'); +fs.writeFileSync(OUTPUT_PATH, stub, 'utf8'); +console.log('[ensure-embedded-stub] Done.'); -- GitLab