From 2f606c85467182f6e75be47c295ceda86a523023 Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Wed, 21 Feb 2024 20:46:18 +1000 Subject: [PATCH 001/195] init --- esbuild.config.mjs | 20 +- main.ts | 134 -- manifest.json | 4 +- package-lock.json | 2809 ++++++++++++++++++++++++++++ package.json | 24 +- src/brand.ts | 1 + src/entry.ts | 33 + src/ui/columns/columns.ts | 33 + src/ui/components/column.svelte | 82 + src/ui/components/task.svelte | 34 + src/ui/components/task_menu.svelte | 77 + src/ui/entry.ts | 34 + src/ui/main.svelte | 92 + src/ui/tasks/actions.ts | 79 + src/ui/tasks/store.ts | 103 + src/ui/tasks/task.ts | 111 ++ src/ui/tasks/tasks.ts | 63 + tsconfig.json | 39 +- 18 files changed, 3601 insertions(+), 171 deletions(-) delete mode 100644 main.ts create mode 100644 package-lock.json create mode 100644 src/brand.ts create mode 100644 src/entry.ts create mode 100644 src/ui/columns/columns.ts create mode 100644 src/ui/components/column.svelte create mode 100644 src/ui/components/task.svelte create mode 100644 src/ui/components/task_menu.svelte create mode 100644 src/ui/entry.ts create mode 100644 src/ui/main.svelte create mode 100644 src/ui/tasks/actions.ts create mode 100644 src/ui/tasks/store.ts create mode 100644 src/ui/tasks/task.ts create mode 100644 src/ui/tasks/tasks.ts diff --git a/esbuild.config.mjs b/esbuild.config.mjs index b13282bae..12405173c 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -1,21 +1,22 @@ import esbuild from "esbuild"; import process from "process"; import builtins from "builtin-modules"; +import esbuildSvelte from "esbuild-svelte"; +import sveltePreprocess from "svelte-preprocess"; -const banner = -`/* +const banner = `/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ `; -const prod = (process.argv[2] === "production"); +const prod = process.argv[2] === "production"; const context = await esbuild.context({ banner: { js: banner, }, - entryPoints: ["main.ts"], + entryPoints: ["src/entry.ts"], bundle: true, external: [ "obsidian", @@ -31,13 +32,20 @@ const context = await esbuild.context({ "@lezer/common", "@lezer/highlight", "@lezer/lr", - ...builtins], + ...builtins, + ], format: "cjs", target: "es2018", logLevel: "info", sourcemap: prod ? false : "inline", treeShaking: true, outfile: "main.js", + plugins: [ + esbuildSvelte({ + compilerOptions: { css: "injected" }, + preprocess: sveltePreprocess(), + }), + ], }); if (prod) { @@ -45,4 +53,4 @@ if (prod) { process.exit(0); } else { await context.watch(); -} \ No newline at end of file +} diff --git a/main.ts b/main.ts deleted file mode 100644 index 2d0721299..000000000 --- a/main.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; - -// Remember to rename these classes and interfaces! - -interface MyPluginSettings { - mySetting: string; -} - -const DEFAULT_SETTINGS: MyPluginSettings = { - mySetting: 'default' -} - -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; - - async onload() { - await this.loadSettings(); - - // This creates an icon in the left ribbon. - const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => { - // Called when the user clicks the icon. - new Notice('This is a notice!'); - }); - // Perform additional things with the ribbon - ribbonIconEl.addClass('my-plugin-ribbon-class'); - - // This adds a status bar item to the bottom of the app. Does not work on mobile apps. - const statusBarItemEl = this.addStatusBarItem(); - statusBarItemEl.setText('Status Bar Text'); - - // This adds a simple command that can be triggered anywhere - this.addCommand({ - id: 'open-sample-modal-simple', - name: 'Open sample modal (simple)', - callback: () => { - new SampleModal(this.app).open(); - } - }); - // This adds an editor command that can perform some operation on the current editor instance - this.addCommand({ - id: 'sample-editor-command', - name: 'Sample editor command', - editorCallback: (editor: Editor, view: MarkdownView) => { - console.log(editor.getSelection()); - editor.replaceSelection('Sample Editor Command'); - } - }); - // This adds a complex command that can check whether the current state of the app allows execution of the command - this.addCommand({ - id: 'open-sample-modal-complex', - name: 'Open sample modal (complex)', - checkCallback: (checking: boolean) => { - // Conditions to check - const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView); - if (markdownView) { - // If checking is true, we're simply "checking" if the command can be run. - // If checking is false, then we want to actually perform the operation. - if (!checking) { - new SampleModal(this.app).open(); - } - - // This command will only show up in Command Palette when the check function returns true - return true; - } - } - }); - - // This adds a settings tab so the user can configure various aspects of the plugin - this.addSettingTab(new SampleSettingTab(this.app, this)); - - // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) - // Using this function will automatically remove the event listener when this plugin is disabled. - this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - console.log('click', evt); - }); - - // When registering intervals, this function will automatically clear the interval when the plugin is disabled. - this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); - } - - onunload() { - - } - - async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - - async saveSettings() { - await this.saveData(this.settings); - } -} - -class SampleModal extends Modal { - constructor(app: App) { - super(app); - } - - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - const {contentEl} = this; - contentEl.empty(); - } -} - -class SampleSettingTab extends PluginSettingTab { - plugin: MyPlugin; - - constructor(app: App, plugin: MyPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const {containerEl} = this; - - containerEl.empty(); - - new Setting(containerEl) - .setName('Setting #1') - .setDesc('It\'s a secret') - .addText(text => text - .setPlaceholder('Enter your secret') - .setValue(this.plugin.settings.mySetting) - .onChange(async (value) => { - this.plugin.settings.mySetting = value; - await this.plugin.saveSettings(); - })); - } -} diff --git a/manifest.json b/manifest.json index dfa940ed8..67d44a3e5 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { - "id": "sample-plugin", - "name": "Sample Plugin", + "id": "obsidian-project-kanban", + "name": "Project Kanban", "version": "1.0.0", "minAppVersion": "0.15.0", "description": "Demonstrates some of the capabilities of the Obsidian API.", diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..e6a1879db --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2809 @@ +{ + "name": "obsidian-sample-plugin", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "obsidian-sample-plugin", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.6.3", + "crypto-js": "^4.2.0", + "sass": "^1.71.1" + }, + "devDependencies": { + "@tsconfig/svelte": "^5.0.2", + "@types/crypto-js": "^4.2.2", + "@types/node": "^20.11.19", + "@typescript-eslint/eslint-plugin": "7.0.1", + "@typescript-eslint/parser": "7.0.1", + "builtin-modules": "3.3.0", + "esbuild": "0.20.0", + "esbuild-svelte": "^0.8.0", + "obsidian": "latest", + "svelte": "^4.2.11", + "svelte-preprocess": "^5.1.3", + "tslib": "2.6.2", + "typescript": "5.3.3" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", + "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==", + "dev": true, + "peer": true + }, + "node_modules/@codemirror/view": { + "version": "6.24.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.0.tgz", + "integrity": "sha512-zK6m5pNkdhdJl8idPP1gA4N8JKTiSsOz8U/Iw+C1ChMwyLG7+MLiNXnH/wFuAk6KeGEe33/adOiAh5jMqee03w==", + "dev": true, + "peer": true, + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz", + "integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz", + "integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz", + "integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz", + "integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz", + "integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz", + "integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz", + "integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz", + "integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz", + "integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz", + "integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz", + "integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz", + "integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz", + "integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz", + "integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz", + "integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz", + "integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz", + "integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz", + "integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz", + "integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz", + "integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz", + "integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz", + "integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz", + "integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "dependencies": { + "@floating-ui/utils": "^0.2.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true, + "peer": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tsconfig/svelte": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.2.tgz", + "integrity": "sha512-BRbo1fOtyVbhfLyuCWw6wAWp+U8UQle+ZXu84MYYWzYSEB28dyfnRBIE99eoG+qdAC0po6L2ScIEivcT07UaMA==", + "dev": true + }, + "node_modules/@types/codemirror": { + "version": "5.60.8", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", + "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", + "dev": true, + "dependencies": { + "@types/tern": "*" + } + }, + "node_modules/@types/crypto-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", + "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/pug": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", + "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", + "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "dev": true + }, + "node_modules/@types/tern": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", + "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/type-utils": "7.0.1", + "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", + "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", + "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/utils": "7.0.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "peer": true + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/code-red": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", + "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@types/estree": "^1.0.1", + "acorn": "^8.10.0", + "estree-walker": "^3.0.3", + "periscopic": "^3.1.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "peer": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz", + "integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.0", + "@esbuild/android-arm": "0.20.0", + "@esbuild/android-arm64": "0.20.0", + "@esbuild/android-x64": "0.20.0", + "@esbuild/darwin-arm64": "0.20.0", + "@esbuild/darwin-x64": "0.20.0", + "@esbuild/freebsd-arm64": "0.20.0", + "@esbuild/freebsd-x64": "0.20.0", + "@esbuild/linux-arm": "0.20.0", + "@esbuild/linux-arm64": "0.20.0", + "@esbuild/linux-ia32": "0.20.0", + "@esbuild/linux-loong64": "0.20.0", + "@esbuild/linux-mips64el": "0.20.0", + "@esbuild/linux-ppc64": "0.20.0", + "@esbuild/linux-riscv64": "0.20.0", + "@esbuild/linux-s390x": "0.20.0", + "@esbuild/linux-x64": "0.20.0", + "@esbuild/netbsd-x64": "0.20.0", + "@esbuild/openbsd-x64": "0.20.0", + "@esbuild/sunos-x64": "0.20.0", + "@esbuild/win32-arm64": "0.20.0", + "@esbuild/win32-ia32": "0.20.0", + "@esbuild/win32-x64": "0.20.0" + } + }, + "node_modules/esbuild-svelte": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.8.0.tgz", + "integrity": "sha512-uKcPf1kl2UGMjrfHChv4dLxGAvCNhf9s72mHo19ZhKP+LrVOuQkOM/g8GE7MiGpoqjpk8UHqL08uLRbSKXhmhw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.19" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "esbuild": ">=0.9.6", + "svelte": ">=3.43.0 <5" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "peer": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "peer": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "peer": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true, + "peer": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "peer": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "peer": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "peer": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "peer": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obsidian": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.4.11.tgz", + "integrity": "sha512-BCVYTvaXxElJMl6MMbDdY/CGK+aq18SdtDY/7vH8v6BxCBQ6KF4kKxL0vG9UZ0o5qh139KpUoJHNm+6O5dllKA==", + "dev": true, + "dependencies": { + "@types/codemirror": "5.60.8", + "moment": "2.29.4" + }, + "peerDependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sander": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", + "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", + "dev": true, + "dependencies": { + "es6-promise": "^3.1.2", + "graceful-fs": "^4.1.3", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2" + } + }, + "node_modules/sander/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/sass": { + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sorcery": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz", + "integrity": "sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.14", + "buffer-crc32": "^0.2.5", + "minimist": "^1.2.0", + "sander": "^0.5.0" + }, + "bin": { + "sorcery": "bin/sorcery" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-mod": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", + "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==", + "dev": true, + "peer": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/svelte": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.11.tgz", + "integrity": "sha512-YIQk3J4X89wOLhjsqIW8tqY3JHPuBdtdOIkASP2PZeAMcSW9RsIjQzMesCrxOF3gdWYC0mKknlKF7OqmLM+Zqg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/estree": "^1.0.1", + "acorn": "^8.9.0", + "aria-query": "^5.3.0", + "axobject-query": "^4.0.0", + "code-red": "^1.0.3", + "css-tree": "^2.3.1", + "estree-walker": "^3.0.3", + "is-reference": "^3.0.1", + "locate-character": "^3.0.0", + "magic-string": "^0.30.4", + "periscopic": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/svelte-preprocess": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.3.tgz", + "integrity": "sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/pug": "^2.0.6", + "detect-indent": "^6.1.0", + "magic-string": "^0.30.5", + "sorcery": "^0.11.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">= 16.0.0", + "pnpm": "^8.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.10.2", + "coffeescript": "^2.5.1", + "less": "^3.11.3 || ^4.0.0", + "postcss": "^7 || ^8", + "postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "pug": "^3.0.0", + "sass": "^1.26.8", + "stylus": "^0.55.0", + "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0", + "typescript": ">=3.9.5 || ^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "coffeescript": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "postcss-load-config": { + "optional": true + }, + "pug": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, + "peer": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 6a00766d9..0f997a025 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "obsidian-sample-plugin", + "name": "obsidian-project-kanban", "version": "1.0.0", "description": "This is a sample plugin for Obsidian (https://obsidian.md)", "main": "main.js", @@ -12,13 +12,23 @@ "author": "", "license": "MIT", "devDependencies": { - "@types/node": "^16.11.6", - "@typescript-eslint/eslint-plugin": "5.29.0", - "@typescript-eslint/parser": "5.29.0", + "@tsconfig/svelte": "^5.0.2", + "@types/crypto-js": "^4.2.2", + "@types/node": "^20.11.19", + "@typescript-eslint/eslint-plugin": "7.0.1", + "@typescript-eslint/parser": "7.0.1", "builtin-modules": "3.3.0", - "esbuild": "0.17.3", + "esbuild": "0.20.0", + "esbuild-svelte": "^0.8.0", "obsidian": "latest", - "tslib": "2.4.0", - "typescript": "4.7.4" + "svelte": "^4.2.11", + "svelte-preprocess": "^5.1.3", + "tslib": "2.6.2", + "typescript": "5.3.3" + }, + "dependencies": { + "@floating-ui/dom": "^1.6.3", + "crypto-js": "^4.2.0", + "sass": "^1.71.1" } } diff --git a/src/brand.ts b/src/brand.ts new file mode 100644 index 000000000..bccd6f9fc --- /dev/null +++ b/src/brand.ts @@ -0,0 +1 @@ +export type Brand = K & { __brand: T }; diff --git a/src/entry.ts b/src/entry.ts new file mode 100644 index 000000000..d85194609 --- /dev/null +++ b/src/entry.ts @@ -0,0 +1,33 @@ +import { Plugin, WorkspaceLeaf } from "obsidian"; +import { AppView, APP_VIEW_NAME } from "./ui/entry"; + +export default class Base extends Plugin { + async onload() { + this.registerView(APP_VIEW_NAME, (leaf) => new AppView(leaf)); + this.addRibbonIcon("kanban-square", "Open Kanban", () => + this.activateView() + ); + } + + onunload() {} + + async activateView() { + const { workspace } = this.app; + + let leaf: WorkspaceLeaf | undefined; + const leaves = workspace.getLeavesOfType(APP_VIEW_NAME); + + if (leaves.length > 0) { + // A leaf with our view already exists, use that + leaf = leaves[0]; + } else { + // Our view could not be found in the workspace, create a new leaf + // in the right sidebar for it + leaf = workspace.getLeaf("tab"); + await leaf.setViewState({ type: APP_VIEW_NAME, active: true }); + } + + // "Reveal" the leaf in case it is in a collapsed sidebar + leaf && workspace.revealLeaf(leaf); + } +} diff --git a/src/ui/columns/columns.ts b/src/ui/columns/columns.ts new file mode 100644 index 000000000..27ff891e7 --- /dev/null +++ b/src/ui/columns/columns.ts @@ -0,0 +1,33 @@ +import type { Brand } from "src/brand"; +import { writable } from "svelte/store"; + +export type ColumnConfig = { + columns: string[]; +}; + +export type DefaultColumns = "uncategorised" | "done"; +export type ColumnTag = Brand; + +export type ColumnTagTable = Record; + +export function createColumnTagTable({ + columns, +}: ColumnConfig): ColumnTagTable { + const output: ColumnTagTable = {}; + + for (const column of columns) { + output[kebab(column)] = column; + } + + return output; +} + +function kebab(input: string): ColumnTag { + return input + .toLowerCase() // all alphanumeric chars to lower case + .replaceAll(/\s/g, "-") // replace all whitespace with "-" + .replaceAll(/[^a-z0-9-]/g, "") // replace all other chars with "" + .replaceAll(/-+/g, "-") as ColumnTag; // collapse any consecutive "-" into a single "-" +} + +export const columnTagTableStore = writable({}); diff --git a/src/ui/components/column.svelte b/src/ui/components/column.svelte new file mode 100644 index 000000000..1a1c5c46a --- /dev/null +++ b/src/ui/components/column.svelte @@ -0,0 +1,82 @@ + + +{#if !hideOnEmpty || tasks.length} +
+

{columnTitle}

+
+
+ {#each sortedTasks as task} + + {/each} +
+
+{/if} + + diff --git a/src/ui/components/task.svelte b/src/ui/components/task.svelte new file mode 100644 index 000000000..025c968be --- /dev/null +++ b/src/ui/components/task.svelte @@ -0,0 +1,34 @@ + + +
+
+

{task.content}

+
+ +
+ + diff --git a/src/ui/components/task_menu.svelte b/src/ui/components/task_menu.svelte new file mode 100644 index 000000000..d8afe86cc --- /dev/null +++ b/src/ui/components/task_menu.svelte @@ -0,0 +1,77 @@ + + + + showMenu(e)} +> + + diff --git a/src/ui/entry.ts b/src/ui/entry.ts new file mode 100644 index 000000000..a3794120b --- /dev/null +++ b/src/ui/entry.ts @@ -0,0 +1,34 @@ +import { ItemView } from "obsidian"; + +import Main from "./main.svelte"; + +export const APP_VIEW_NAME = "project-plan"; + +export class AppView extends ItemView { + component: Main | undefined; + icon = "kanban-square"; + + getViewType() { + this.leaf.openFile; + return APP_VIEW_NAME; + } + + getDisplayText() { + return "Project Planner"; + } + + async onOpen() { + this.component = new Main({ + target: this.contentEl, + props: { + workspace: this.app.workspace, + vault: this.app.vault, + registerEvent: this.registerEvent.bind(this), + }, + }); + } + + async onClose() { + this.component?.$destroy(); + } +} diff --git a/src/ui/main.svelte b/src/ui/main.svelte new file mode 100644 index 000000000..c64e1c4ac --- /dev/null +++ b/src/ui/main.svelte @@ -0,0 +1,92 @@ + + +
+

Project Planner

+
+
+ + {#each columns as column} + + {/each} + +
+
+
+ + diff --git a/src/ui/tasks/actions.ts b/src/ui/tasks/actions.ts new file mode 100644 index 000000000..47d7bb94c --- /dev/null +++ b/src/ui/tasks/actions.ts @@ -0,0 +1,79 @@ +import { MarkdownView, type TFile, type Vault, type Workspace } from "obsidian"; +import type { Task } from "./task"; +import type { Metadata } from "./tasks"; +import type { ColumnTag, DefaultColumns } from "../columns/columns"; + +export type TaskActions = { + changeColumn: ( + id: string, + newColumn: ColumnTag | Exclude + ) => Promise; + viewFile: (id: string) => Promise; +}; + +export function createTaskActions({ + tasksByTaskId, + metadataByTaskId, + vault, + workspace, +}: { + tasksByTaskId: Map; + metadataByTaskId: Map; + vault: Vault; + workspace: Workspace; +}): TaskActions { + async function changeColumn( + id: string, + newColumn: ColumnTag | Exclude + ) { + const metadata = metadataByTaskId.get(id); + const task = tasksByTaskId.get(id); + + if (!metadata || !task) { + return; + } + + const newTaskString = task.serialise({ column: newColumn }); + await updateRow( + vault, + metadata.fileHandle, + metadata.rowIndex, + newTaskString + ); + } + + async function viewFile(id: string) { + const metadata = metadataByTaskId.get(id); + + if (!metadata) { + return; + } + + const { fileHandle, rowIndex } = metadata; + + const leaf = workspace.getLeaf("tab"); + await leaf.openFile(fileHandle); + const editorView = workspace.getActiveViewOfType(MarkdownView); + editorView?.editor.setCursor(rowIndex); + } + + return { changeColumn, viewFile }; +} + +async function updateRow( + vault: Vault, + fileHandle: TFile, + row: number, + newText: string +) { + const file = await vault.read(fileHandle); + const rows = file.split("\n"); + + if (rows.length < row) { + return; + } + + rows[row] = newText; + const newFile = rows.join("\n"); + await vault.modify(fileHandle, newFile); +} diff --git a/src/ui/tasks/store.ts b/src/ui/tasks/store.ts new file mode 100644 index 000000000..f1cf5fd00 --- /dev/null +++ b/src/ui/tasks/store.ts @@ -0,0 +1,103 @@ +import { TFile, Vault, type EventRef, Workspace } from "obsidian"; +import { updateMapsFromFile, type Metadata } from "./tasks"; +import { Task } from "./task"; +import { writable, type Writable } from "svelte/store"; +import type { ColumnTagTable } from "../columns/columns"; +import { createTaskActions, type TaskActions } from "./actions"; + +export function createTasksStore( + vault: Vault, + workspace: Workspace, + registerEvent: (eventRef: EventRef) => void, + columnTagTableStore: Writable +): { tasksStore: Writable; taskActions: TaskActions } { + const tasksStore = writable([]); + let timer: number | undefined; + + const tasksByTaskId = new Map(); + const metadataByTaskId = new Map(); + const taskIdsByFileHandle = new Map>(); + + const fileHandles = vault.getMarkdownFiles(); + + function debounceSetTasks() { + if (!timer) { + timer = window.setTimeout(() => { + timer = undefined; + tasksStore.set([...tasksByTaskId.values()]); + }, 50); + } + } + + for (const fileHandle of fileHandles) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore, + }).then(() => { + debounceSetTasks(); + }); + } + + registerEvent( + vault.on("modify", (fileHandle) => { + if (fileHandle instanceof TFile) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore, + }).then(() => { + debounceSetTasks(); + }); + } + }) + ); + + registerEvent( + vault.on("create", (fileHandle) => { + if (fileHandle instanceof TFile) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore, + }).then(() => { + debounceSetTasks(); + }); + } + }) + ); + + registerEvent( + vault.on("delete", (fileHandle) => { + if (fileHandle instanceof TFile) { + // TODO implement + } + }) + ); + + registerEvent( + vault.on("rename", (fileHandle) => { + if (fileHandle instanceof TFile) { + // TODO implement + } + }) + ); + + const taskActions = createTaskActions({ + tasksByTaskId, + metadataByTaskId, + vault, + workspace, + }); + + return { tasksStore, taskActions }; +} diff --git a/src/ui/tasks/task.ts b/src/ui/tasks/task.ts new file mode 100644 index 000000000..277861d95 --- /dev/null +++ b/src/ui/tasks/task.ts @@ -0,0 +1,111 @@ +import sha256 from "crypto-js/sha256"; +import type { Brand } from "src/brand"; +import type { + ColumnTag, + ColumnTagTable, + DefaultColumns, +} from "../columns/columns"; + +export class Task { + readonly id: string; + readonly content: string; + readonly done: boolean; + readonly path: string; + readonly rowIndex: number; + readonly column: + | ColumnTag + | Exclude + | undefined; + + constructor( + rawContent: TaskString, + fileHandle: { path: string }, + rowIndex: number, + columnTagTable: ColumnTagTable + ) { + const task = this._deserialise(rawContent, fileHandle, rowIndex); + this.id = task.id; + this.content = task.content; + this.done = task.done; + this.path = fileHandle.path; + this.rowIndex = rowIndex; + + let column: ColumnTag | undefined; + for (const tag of task.tags) { + if (tag in columnTagTable || tag === "done") { + column = tag as ColumnTag; + break; + } + } + + this.column = column; + } + + private _deserialise( + rawContent: TaskString, + fileHandle: { path: string }, + rowIndex: number + ): { + id: string; + content: string; + done: boolean; + tags: string[]; + } { + const [, remainder = ""] = rawContent.split("- ["); + const [status, content = ""] = remainder.split("] "); + + const { tags, cleanedContent } = getTags(content); + + return { + id: sha256(content + fileHandle.path + rowIndex).toString(), + done: status === "x", + content: cleanedContent, + tags, + }; + } + + serialise( + data: Partial<{ + column: ColumnTag | Exclude; + }> + ): string { + const done = data.column === "done" || this.done; + const column: + | ColumnTag + | Exclude + | undefined = data.column ?? this.column; + + return `- [${done ? "x" : " "}] ${this.content}${ + column ? ` #${column}` : "" + }`; + } +} + +type TaskString = Brand; + +export function isTaskString(input: string): input is TaskString { + return taskStringRegex.test(input); +} + +// begins with 0 or more whitespace chars +// then follows the pattern "- [ ]" OR "- [x]" +// then contains an additional whitespace before any trailing content +const taskStringRegex = /^\s*-\s\[[x\s]\]\s/; + +function getTags(content: string): { tags: string[]; cleanedContent: string } { + const tags = new Set(); + let cleanedContent = content; + + // starts with "#", ends with " ", only contains alphanumerics or "-" + const allMatches = content.matchAll(/#([\w-]+)/g); + for (const match of [...allMatches]) { + const maybeTag = match[1]; + if (maybeTag) { + tags.add(maybeTag); + + cleanedContent = cleanedContent.replaceAll(`#${maybeTag}`, ""); + } + } + + return { tags: [...tags], cleanedContent: cleanedContent.trim() }; +} diff --git a/src/ui/tasks/tasks.ts b/src/ui/tasks/tasks.ts new file mode 100644 index 000000000..e1da26c09 --- /dev/null +++ b/src/ui/tasks/tasks.ts @@ -0,0 +1,63 @@ +import type { TFile, Vault } from "obsidian"; +import { isTaskString, Task } from "./task"; +import type { ColumnTagTable } from "../columns/columns"; +import { get, type Writable } from "svelte/store"; + +export type Metadata = { + rowIndex: number; + fileHandle: TFile; +}; + +/** + * mutates the supplied Maps + */ +export async function updateMapsFromFile({ + fileHandle, + taskIdsByFileHandle, + tasksByTaskId, + metadataByTaskId, + vault, + columnTagTableStore, +}: { + fileHandle: TFile; + tasksByTaskId: Map; + metadataByTaskId: Map; + taskIdsByFileHandle: Map>; + vault: Vault; + columnTagTableStore: Writable; +}) { + try { + const previousTaskIds = + taskIdsByFileHandle.get(fileHandle) ?? new Set(); + const newTaskIds = new Set(); + + const contents = await vault.read(fileHandle); + const rows = contents.split("\n"); + const columnTagTable = get(columnTagTableStore); + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if (!row) { + continue; + } + + if (isTaskString(row)) { + const task = new Task(row, fileHandle, i, columnTagTable); + + newTaskIds.add(task.id); + tasksByTaskId.set(task.id, task); + metadataByTaskId.set(task.id, { rowIndex: i, fileHandle }); + previousTaskIds.delete(task.id); + } + } + + for (const prevId of previousTaskIds) { + tasksByTaskId.delete(prevId); + metadataByTaskId.delete(prevId); + } + + taskIdsByFileHandle.set(fileHandle, newTaskIds); + } catch { + // + } +} diff --git a/tsconfig.json b/tsconfig.json index 2d6fbdf36..9d60e9013 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,19 @@ { - "compilerOptions": { - "baseUrl": ".", - "inlineSourceMap": true, - "inlineSources": true, - "module": "ESNext", - "target": "ES6", - "allowJs": true, - "noImplicitAny": true, - "moduleResolution": "node", - "importHelpers": true, - "isolatedModules": true, - "strictNullChecks": true, - "lib": [ - "DOM", - "ES5", - "ES6", - "ES7" - ] - }, - "include": [ - "**/*.ts" - ] + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "types": ["svelte", "node"], + "baseUrl": ".", + "inlineSources": true, + "module": "ESNext", + "target": "ES2020", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "isolatedModules": true, + "strictNullChecks": true, + "lib": ["DOM", "es2021"], + "noUncheckedIndexedAccess": true + }, + "include": ["**/*.ts"] } From 0f53e23e7bcaded533f67f71b2b599e6ce8652ff Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Wed, 21 Feb 2024 20:54:37 +1000 Subject: [PATCH 002/195] added main.js --- .gitignore | 4 - main.js | 2660 +++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 4 +- 3 files changed, 2662 insertions(+), 6 deletions(-) create mode 100644 main.js diff --git a/.gitignore b/.gitignore index e09a007eb..18fe88c95 100644 --- a/.gitignore +++ b/.gitignore @@ -8,10 +8,6 @@ # npm node_modules -# Don't include the compiled main.js file in the repo. -# They should be uploaded to GitHub releases instead. -main.js - # Exclude sourcemaps *.map diff --git a/main.js b/main.js new file mode 100644 index 000000000..2267016f8 --- /dev/null +++ b/main.js @@ -0,0 +1,2660 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); +var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; +}; + +// node_modules/crypto-js/core.js +var require_core = __commonJS({ + "node_modules/crypto-js/core.js"(exports, module2) { + (function(root, factory) { + if (typeof exports === "object") { + module2.exports = exports = factory(); + } else if (typeof define === "function" && define.amd) { + define([], factory); + } else { + root.CryptoJS = factory(); + } + })(exports, function() { + var CryptoJS = CryptoJS || function(Math2, undefined2) { + var crypto; + if (typeof window !== "undefined" && window.crypto) { + crypto = window.crypto; + } + if (typeof self !== "undefined" && self.crypto) { + crypto = self.crypto; + } + if (typeof globalThis !== "undefined" && globalThis.crypto) { + crypto = globalThis.crypto; + } + if (!crypto && typeof window !== "undefined" && window.msCrypto) { + crypto = window.msCrypto; + } + if (!crypto && typeof global !== "undefined" && global.crypto) { + crypto = global.crypto; + } + if (!crypto && typeof require === "function") { + try { + crypto = require("crypto"); + } catch (err) { + } + } + var cryptoSecureRandomInt = function() { + if (crypto) { + if (typeof crypto.getRandomValues === "function") { + try { + return crypto.getRandomValues(new Uint32Array(1))[0]; + } catch (err) { + } + } + if (typeof crypto.randomBytes === "function") { + try { + return crypto.randomBytes(4).readInt32LE(); + } catch (err) { + } + } + } + throw new Error("Native crypto module could not be used to get secure random number."); + }; + var create = Object.create || /* @__PURE__ */ function() { + function F() { + } + return function(obj) { + var subtype; + F.prototype = obj; + subtype = new F(); + F.prototype = null; + return subtype; + }; + }(); + var C = {}; + var C_lib = C.lib = {}; + var Base2 = C_lib.Base = /* @__PURE__ */ function() { + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function(overrides) { + var subtype = create(this); + if (overrides) { + subtype.mixIn(overrides); + } + if (!subtype.hasOwnProperty("init") || this.init === subtype.init) { + subtype.init = function() { + subtype.$super.init.apply(this, arguments); + }; + } + subtype.init.prototype = subtype; + subtype.$super = this; + return subtype; + }, + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function() { + var instance5 = this.extend(); + instance5.init.apply(instance5, arguments); + return instance5; + }, + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function() { + }, + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function(properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + if (properties.hasOwnProperty("toString")) { + this.toString = properties.toString; + } + }, + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function() { + return this.init.prototype.extend(this); + } + }; + }(); + var WordArray = C_lib.WordArray = Base2.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function(words, sigBytes) { + words = this.words = words || []; + if (sigBytes != undefined2) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function(encoder) { + return (encoder || Hex).stringify(this); + }, + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function(wordArray) { + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + this.clamp(); + if (thisSigBytes % 4) { + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = thatWords[i >>> 2] >>> 24 - i % 4 * 8 & 255; + thisWords[thisSigBytes + i >>> 2] |= thatByte << 24 - (thisSigBytes + i) % 4 * 8; + } + } else { + for (var j = 0; j < thatSigBytes; j += 4) { + thisWords[thisSigBytes + j >>> 2] = thatWords[j >>> 2]; + } + } + this.sigBytes += thatSigBytes; + return this; + }, + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function() { + var words = this.words; + var sigBytes = this.sigBytes; + words[sigBytes >>> 2] &= 4294967295 << 32 - sigBytes % 4 * 8; + words.length = Math2.ceil(sigBytes / 4); + }, + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function() { + var clone = Base2.clone.call(this); + clone.words = this.words.slice(0); + return clone; + }, + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function(nBytes) { + var words = []; + for (var i = 0; i < nBytes; i += 4) { + words.push(cryptoSecureRandomInt()); + } + return new WordArray.init(words, nBytes); + } + }); + var C_enc = C.enc = {}; + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function(wordArray) { + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 15).toString(16)); + } + return hexChars.join(""); + }, + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function(hexStr) { + var hexStrLength = hexStr.length; + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << 24 - i % 8 * 4; + } + return new WordArray.init(words, hexStrLength / 2); + } + }; + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function(wordArray) { + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255; + latin1Chars.push(String.fromCharCode(bite)); + } + return latin1Chars.join(""); + }, + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function(latin1Str) { + var latin1StrLength = latin1Str.length; + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8; + } + return new WordArray.init(words, latin1StrLength); + } + }; + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function(wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error("Malformed UTF-8 data"); + } + }, + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function(utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base2.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function() { + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function(data) { + if (typeof data == "string") { + data = Utf8.parse(data); + } + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function(doFlush) { + var processedWords; + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + nBlocksReady = Math2.ceil(nBlocksReady); + } else { + nBlocksReady = Math2.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + var nWordsReady = nBlocksReady * blockSize; + var nBytesReady = Math2.min(nWordsReady * 4, dataSigBytes); + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + this._doProcessBlock(dataWords, offset); + } + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + return new WordArray.init(processedWords, nBytesReady); + }, + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function() { + var clone = Base2.clone.call(this); + clone._data = this._data.clone(); + return clone; + }, + _minBufferSize: 0 + }); + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base2.extend(), + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function(cfg) { + this.cfg = this.cfg.extend(cfg); + this.reset(); + }, + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function() { + BufferedBlockAlgorithm.reset.call(this); + this._doReset(); + }, + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function(messageUpdate) { + this._append(messageUpdate); + this._process(); + return this; + }, + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function(messageUpdate) { + if (messageUpdate) { + this._append(messageUpdate); + } + var hash = this._doFinalize(); + return hash; + }, + blockSize: 512 / 32, + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function(hasher) { + return function(message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function(hasher) { + return function(message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + var C_algo = C.algo = {}; + return C; + }(Math); + return CryptoJS; + }); + } +}); + +// node_modules/crypto-js/sha256.js +var require_sha256 = __commonJS({ + "node_modules/crypto-js/sha256.js"(exports, module2) { + (function(root, factory) { + if (typeof exports === "object") { + module2.exports = exports = factory(require_core()); + } else if (typeof define === "function" && define.amd) { + define(["./core"], factory); + } else { + factory(root.CryptoJS); + } + })(exports, function(CryptoJS) { + (function(Math2) { + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + var H = []; + var K = []; + (function() { + function isPrime(n2) { + var sqrtN = Math2.sqrt(n2); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n2 % factor)) { + return false; + } + } + return true; + } + function getFractionalBits(n2) { + return (n2 - (n2 | 0)) * 4294967296 | 0; + } + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math2.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math2.pow(n, 1 / 3)); + nPrime++; + } + n++; + } + })(); + var W = []; + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function() { + this._hash = new WordArray.init(H.slice(0)); + }, + _doProcessBlock: function(M, offset) { + var H2 = this._hash.words; + var a = H2[0]; + var b = H2[1]; + var c = H2[2]; + var d = H2[3]; + var e = H2[4]; + var f = H2[5]; + var g = H2[6]; + var h = H2[7]; + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = (gamma0x << 25 | gamma0x >>> 7) ^ (gamma0x << 14 | gamma0x >>> 18) ^ gamma0x >>> 3; + var gamma1x = W[i - 2]; + var gamma1 = (gamma1x << 15 | gamma1x >>> 17) ^ (gamma1x << 13 | gamma1x >>> 19) ^ gamma1x >>> 10; + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + var ch = e & f ^ ~e & g; + var maj = a & b ^ a & c ^ b & c; + var sigma0 = (a << 30 | a >>> 2) ^ (a << 19 | a >>> 13) ^ (a << 10 | a >>> 22); + var sigma1 = (e << 26 | e >>> 6) ^ (e << 21 | e >>> 11) ^ (e << 7 | e >>> 25); + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + h = g; + g = f; + f = e; + e = d + t1 | 0; + d = c; + c = b; + b = a; + a = t1 + t2 | 0; + } + H2[0] = H2[0] + a | 0; + H2[1] = H2[1] + b | 0; + H2[2] = H2[2] + c | 0; + H2[3] = H2[3] + d | 0; + H2[4] = H2[4] + e | 0; + H2[5] = H2[5] + f | 0; + H2[6] = H2[6] + g | 0; + H2[7] = H2[7] + h | 0; + }, + _doFinalize: function() { + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + dataWords[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32; + dataWords[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math2.floor(nBitsTotal / 4294967296); + dataWords[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + this._process(); + return this._hash; + }, + clone: function() { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + return clone; + } + }); + C.SHA256 = Hasher._createHelper(SHA256); + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + })(Math); + return CryptoJS.SHA256; + }); + } +}); + +// src/entry.ts +var entry_exports = {}; +__export(entry_exports, { + default: () => Base +}); +module.exports = __toCommonJS(entry_exports); +var import_obsidian6 = require("obsidian"); + +// src/ui/entry.ts +var import_obsidian5 = require("obsidian"); + +// node_modules/svelte/src/runtime/internal/utils.js +function noop() { +} +function run(fn) { + return fn(); +} +function blank_object() { + return /* @__PURE__ */ Object.create(null); +} +function run_all(fns) { + fns.forEach(run); +} +function is_function(thing) { + return typeof thing === "function"; +} +function safe_not_equal(a, b) { + return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function"; +} +function is_empty(obj) { + return Object.keys(obj).length === 0; +} +function subscribe(store, ...callbacks) { + if (store == null) { + for (const callback of callbacks) { + callback(void 0); + } + return noop; + } + const unsub = store.subscribe(...callbacks); + return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; +} +function get_store_value(store) { + let value; + subscribe(store, (_) => value = _)(); + return value; +} +function component_subscribe(component, store, callback) { + component.$$.on_destroy.push(subscribe(store, callback)); +} + +// node_modules/svelte/src/runtime/internal/globals.js +var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : ( + // @ts-ignore Node typings have this + global +); + +// node_modules/svelte/src/runtime/internal/ResizeObserverSingleton.js +var ResizeObserverSingleton = class _ResizeObserverSingleton { + /** @param {ResizeObserverOptions} options */ + constructor(options) { + /** + * @private + * @readonly + * @type {WeakMap} + */ + __publicField(this, "_listeners", "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0); + /** + * @private + * @type {ResizeObserver} + */ + __publicField(this, "_observer"); + /** @type {ResizeObserverOptions} */ + __publicField(this, "options"); + this.options = options; + } + /** + * @param {Element} element + * @param {import('./private.js').Listener} listener + * @returns {() => void} + */ + observe(element2, listener) { + this._listeners.set(element2, listener); + this._getObserver().observe(element2, this.options); + return () => { + this._listeners.delete(element2); + this._observer.unobserve(element2); + }; + } + /** + * @private + */ + _getObserver() { + var _a; + return (_a = this._observer) != null ? _a : this._observer = new ResizeObserver((entries) => { + var _a2; + for (const entry of entries) { + _ResizeObserverSingleton.entries.set(entry.target, entry); + (_a2 = this._listeners.get(entry.target)) == null ? void 0 : _a2(entry); + } + }); + } +}; +ResizeObserverSingleton.entries = "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0; + +// node_modules/svelte/src/runtime/internal/dom.js +var is_hydrating = false; +function start_hydrating() { + is_hydrating = true; +} +function end_hydrating() { + is_hydrating = false; +} +function append(target, node) { + target.appendChild(node); +} +function append_styles(target, style_sheet_id, styles) { + const append_styles_to = get_root_for_style(target); + if (!append_styles_to.getElementById(style_sheet_id)) { + const style = element("style"); + style.id = style_sheet_id; + style.textContent = styles; + append_stylesheet(append_styles_to, style); + } +} +function get_root_for_style(node) { + if (!node) + return document; + const root = node.getRootNode ? node.getRootNode() : node.ownerDocument; + if (root && /** @type {ShadowRoot} */ + root.host) { + return ( + /** @type {ShadowRoot} */ + root + ); + } + return node.ownerDocument; +} +function append_stylesheet(node, style) { + append( + /** @type {Document} */ + node.head || node, + style + ); + return style.sheet; +} +function insert(target, node, anchor) { + target.insertBefore(node, anchor || null); +} +function detach(node) { + if (node.parentNode) { + node.parentNode.removeChild(node); + } +} +function destroy_each(iterations, detaching) { + for (let i = 0; i < iterations.length; i += 1) { + if (iterations[i]) + iterations[i].d(detaching); + } +} +function element(name) { + return document.createElement(name); +} +function text(data) { + return document.createTextNode(data); +} +function space() { + return text(" "); +} +function empty() { + return text(""); +} +function listen(node, event, handler, options) { + node.addEventListener(event, handler, options); + return () => node.removeEventListener(event, handler, options); +} +function attr(node, attribute, value) { + if (value == null) + node.removeAttribute(attribute); + else if (node.getAttribute(attribute) !== value) + node.setAttribute(attribute, value); +} +function children(element2) { + return Array.from(element2.childNodes); +} +function set_data(text2, data) { + data = "" + data; + if (text2.data === data) + return; + text2.data = /** @type {string} */ + data; +} +function get_custom_elements_slots(element2) { + const result = {}; + element2.childNodes.forEach( + /** @param {Element} node */ + (node) => { + result[node.slot || "default"] = true; + } + ); + return result; +} + +// node_modules/svelte/src/runtime/internal/lifecycle.js +var current_component; +function set_current_component(component) { + current_component = component; +} + +// node_modules/svelte/src/runtime/internal/scheduler.js +var dirty_components = []; +var binding_callbacks = []; +var render_callbacks = []; +var flush_callbacks = []; +var resolved_promise = /* @__PURE__ */ Promise.resolve(); +var update_scheduled = false; +function schedule_update() { + if (!update_scheduled) { + update_scheduled = true; + resolved_promise.then(flush); + } +} +function add_render_callback(fn) { + render_callbacks.push(fn); +} +var seen_callbacks = /* @__PURE__ */ new Set(); +var flushidx = 0; +function flush() { + if (flushidx !== 0) { + return; + } + const saved_component = current_component; + do { + try { + while (flushidx < dirty_components.length) { + const component = dirty_components[flushidx]; + flushidx++; + set_current_component(component); + update(component.$$); + } + } catch (e) { + dirty_components.length = 0; + flushidx = 0; + throw e; + } + set_current_component(null); + dirty_components.length = 0; + flushidx = 0; + while (binding_callbacks.length) + binding_callbacks.pop()(); + for (let i = 0; i < render_callbacks.length; i += 1) { + const callback = render_callbacks[i]; + if (!seen_callbacks.has(callback)) { + seen_callbacks.add(callback); + callback(); + } + } + render_callbacks.length = 0; + } while (dirty_components.length); + while (flush_callbacks.length) { + flush_callbacks.pop()(); + } + update_scheduled = false; + seen_callbacks.clear(); + set_current_component(saved_component); +} +function update($$) { + if ($$.fragment !== null) { + $$.update(); + run_all($$.before_update); + const dirty = $$.dirty; + $$.dirty = [-1]; + $$.fragment && $$.fragment.p($$.ctx, dirty); + $$.after_update.forEach(add_render_callback); + } +} +function flush_render_callbacks(fns) { + const filtered = []; + const targets = []; + render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c)); + targets.forEach((c) => c()); + render_callbacks = filtered; +} + +// node_modules/svelte/src/runtime/internal/transitions.js +var outroing = /* @__PURE__ */ new Set(); +var outros; +function group_outros() { + outros = { + r: 0, + c: [], + p: outros + // parent group + }; +} +function check_outros() { + if (!outros.r) { + run_all(outros.c); + } + outros = outros.p; +} +function transition_in(block, local) { + if (block && block.i) { + outroing.delete(block); + block.i(local); + } +} +function transition_out(block, local, detach2, callback) { + if (block && block.o) { + if (outroing.has(block)) + return; + outroing.add(block); + outros.c.push(() => { + outroing.delete(block); + if (callback) { + if (detach2) + block.d(1); + callback(); + } + }); + block.o(local); + } else if (callback) { + callback(); + } +} + +// node_modules/svelte/src/runtime/internal/each.js +function ensure_array_like(array_like_or_iterator) { + return (array_like_or_iterator == null ? void 0 : array_like_or_iterator.length) !== void 0 ? array_like_or_iterator : Array.from(array_like_or_iterator); +} + +// node_modules/svelte/src/shared/boolean_attributes.js +var _boolean_attributes = ( + /** @type {const} */ + [ + "allowfullscreen", + "allowpaymentrequest", + "async", + "autofocus", + "autoplay", + "checked", + "controls", + "default", + "defer", + "disabled", + "formnovalidate", + "hidden", + "inert", + "ismap", + "loop", + "multiple", + "muted", + "nomodule", + "novalidate", + "open", + "playsinline", + "readonly", + "required", + "reversed", + "selected" + ] +); +var boolean_attributes = /* @__PURE__ */ new Set([..._boolean_attributes]); + +// node_modules/svelte/src/runtime/internal/Component.js +function create_component(block) { + block && block.c(); +} +function mount_component(component, target, anchor) { + const { fragment, after_update } = component.$$; + fragment && fragment.m(target, anchor); + add_render_callback(() => { + const new_on_destroy = component.$$.on_mount.map(run).filter(is_function); + if (component.$$.on_destroy) { + component.$$.on_destroy.push(...new_on_destroy); + } else { + run_all(new_on_destroy); + } + component.$$.on_mount = []; + }); + after_update.forEach(add_render_callback); +} +function destroy_component(component, detaching) { + const $$ = component.$$; + if ($$.fragment !== null) { + flush_render_callbacks($$.after_update); + run_all($$.on_destroy); + $$.fragment && $$.fragment.d(detaching); + $$.on_destroy = $$.fragment = null; + $$.ctx = []; + } +} +function make_dirty(component, i) { + if (component.$$.dirty[0] === -1) { + dirty_components.push(component); + schedule_update(); + component.$$.dirty.fill(0); + } + component.$$.dirty[i / 31 | 0] |= 1 << i % 31; +} +function init(component, options, instance5, create_fragment5, not_equal, props, append_styles2 = null, dirty = [-1]) { + const parent_component = current_component; + set_current_component(component); + const $$ = component.$$ = { + fragment: null, + ctx: [], + // state + props, + update: noop, + not_equal, + bound: blank_object(), + // lifecycle + on_mount: [], + on_destroy: [], + on_disconnect: [], + before_update: [], + after_update: [], + context: new Map(options.context || (parent_component ? parent_component.$$.context : [])), + // everything else + callbacks: blank_object(), + dirty, + skip_bound: false, + root: options.target || parent_component.$$.root + }; + append_styles2 && append_styles2($$.root); + let ready = false; + $$.ctx = instance5 ? instance5(component, options.props || {}, (i, ret, ...rest) => { + const value = rest.length ? rest[0] : ret; + if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) { + if (!$$.skip_bound && $$.bound[i]) + $$.bound[i](value); + if (ready) + make_dirty(component, i); + } + return ret; + }) : []; + $$.update(); + ready = true; + run_all($$.before_update); + $$.fragment = create_fragment5 ? create_fragment5($$.ctx) : false; + if (options.target) { + if (options.hydrate) { + start_hydrating(); + const nodes = children(options.target); + $$.fragment && $$.fragment.l(nodes); + nodes.forEach(detach); + } else { + $$.fragment && $$.fragment.c(); + } + if (options.intro) + transition_in(component.$$.fragment); + mount_component(component, options.target, options.anchor); + end_hydrating(); + flush(); + } + set_current_component(parent_component); +} +var SvelteElement; +if (typeof HTMLElement === "function") { + SvelteElement = class extends HTMLElement { + constructor($$componentCtor, $$slots, use_shadow_dom) { + super(); + /** The Svelte component constructor */ + __publicField(this, "$$ctor"); + /** Slots */ + __publicField(this, "$$s"); + /** The Svelte component instance */ + __publicField(this, "$$c"); + /** Whether or not the custom element is connected */ + __publicField(this, "$$cn", false); + /** Component props data */ + __publicField(this, "$$d", {}); + /** `true` if currently in the process of reflecting component props back to attributes */ + __publicField(this, "$$r", false); + /** @type {Record} Props definition (name, reflected, type etc) */ + __publicField(this, "$$p_d", {}); + /** @type {Record} Event listeners */ + __publicField(this, "$$l", {}); + /** @type {Map} Event listener unsubscribe functions */ + __publicField(this, "$$l_u", /* @__PURE__ */ new Map()); + this.$$ctor = $$componentCtor; + this.$$s = $$slots; + if (use_shadow_dom) { + this.attachShadow({ mode: "open" }); + } + } + addEventListener(type, listener, options) { + this.$$l[type] = this.$$l[type] || []; + this.$$l[type].push(listener); + if (this.$$c) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); + } + super.addEventListener(type, listener, options); + } + removeEventListener(type, listener, options) { + super.removeEventListener(type, listener, options); + if (this.$$c) { + const unsub = this.$$l_u.get(listener); + if (unsub) { + unsub(); + this.$$l_u.delete(listener); + } + } + } + async connectedCallback() { + this.$$cn = true; + if (!this.$$c) { + let create_slot = function(name) { + return () => { + let node; + const obj = { + c: function create() { + node = element("slot"); + if (name !== "default") { + attr(node, "name", name); + } + }, + /** + * @param {HTMLElement} target + * @param {HTMLElement} [anchor] + */ + m: function mount(target, anchor) { + insert(target, node, anchor); + }, + d: function destroy(detaching) { + if (detaching) { + detach(node); + } + } + }; + return obj; + }; + }; + await Promise.resolve(); + if (!this.$$cn || this.$$c) { + return; + } + const $$slots = {}; + const existing_slots = get_custom_elements_slots(this); + for (const name of this.$$s) { + if (name in existing_slots) { + $$slots[name] = [create_slot(name)]; + } + } + for (const attribute of this.attributes) { + const name = this.$$g_p(attribute.name); + if (!(name in this.$$d)) { + this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, "toProp"); + } + } + for (const key in this.$$p_d) { + if (!(key in this.$$d) && this[key] !== void 0) { + this.$$d[key] = this[key]; + delete this[key]; + } + } + this.$$c = new this.$$ctor({ + target: this.shadowRoot || this, + props: { + ...this.$$d, + $$slots, + $$scope: { + ctx: [] + } + } + }); + const reflect_attributes = () => { + this.$$r = true; + for (const key in this.$$p_d) { + this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]]; + if (this.$$p_d[key].reflect) { + const attribute_value = get_custom_element_value( + key, + this.$$d[key], + this.$$p_d, + "toAttribute" + ); + if (attribute_value == null) { + this.removeAttribute(this.$$p_d[key].attribute || key); + } else { + this.setAttribute(this.$$p_d[key].attribute || key, attribute_value); + } + } + } + this.$$r = false; + }; + this.$$c.$$.after_update.push(reflect_attributes); + reflect_attributes(); + for (const type in this.$$l) { + for (const listener of this.$$l[type]) { + const unsub = this.$$c.$on(type, listener); + this.$$l_u.set(listener, unsub); + } + } + this.$$l = {}; + } + } + // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte + // and setting attributes through setAttribute etc, this is helpful + attributeChangedCallback(attr2, _oldValue, newValue) { + var _a; + if (this.$$r) + return; + attr2 = this.$$g_p(attr2); + this.$$d[attr2] = get_custom_element_value(attr2, newValue, this.$$p_d, "toProp"); + (_a = this.$$c) == null ? void 0 : _a.$set({ [attr2]: this.$$d[attr2] }); + } + disconnectedCallback() { + this.$$cn = false; + Promise.resolve().then(() => { + if (!this.$$cn) { + this.$$c.$destroy(); + this.$$c = void 0; + } + }); + } + $$g_p(attribute_name) { + return Object.keys(this.$$p_d).find( + (key) => this.$$p_d[key].attribute === attribute_name || !this.$$p_d[key].attribute && key.toLowerCase() === attribute_name + ) || attribute_name; + } + }; +} +function get_custom_element_value(prop, value, props_definition, transform) { + var _a; + const type = (_a = props_definition[prop]) == null ? void 0 : _a.type; + value = type === "Boolean" && typeof value !== "boolean" ? value != null : value; + if (!transform || !props_definition[prop]) { + return value; + } else if (transform === "toAttribute") { + switch (type) { + case "Object": + case "Array": + return value == null ? null : JSON.stringify(value); + case "Boolean": + return value ? "" : null; + case "Number": + return value == null ? null : value; + default: + return value; + } + } else { + switch (type) { + case "Object": + case "Array": + return value && JSON.parse(value); + case "Boolean": + return value; + case "Number": + return value != null ? +value : value; + default: + return value; + } + } +} +var SvelteComponent = class { + constructor() { + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * @type {any} + */ + __publicField(this, "$$"); + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * @type {any} + */ + __publicField(this, "$$set"); + } + /** @returns {void} */ + $destroy() { + destroy_component(this, 1); + this.$destroy = noop; + } + /** + * @template {Extract} K + * @param {K} type + * @param {((e: Events[K]) => void) | null | undefined} callback + * @returns {() => void} + */ + $on(type, callback) { + if (!is_function(callback)) { + return noop; + } + const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []); + callbacks.push(callback); + return () => { + const index = callbacks.indexOf(callback); + if (index !== -1) + callbacks.splice(index, 1); + }; + } + /** + * @param {Partial} props + * @returns {void} + */ + $set(props) { + if (this.$$set && !is_empty(props)) { + this.$$.skip_bound = true; + this.$$set(props); + this.$$.skip_bound = false; + } + } +}; + +// node_modules/svelte/src/shared/version.js +var PUBLIC_VERSION = "4"; + +// node_modules/svelte/src/runtime/internal/disclose-version/index.js +if (typeof window !== "undefined") + (window.__svelte || (window.__svelte = { v: /* @__PURE__ */ new Set() })).v.add(PUBLIC_VERSION); + +// src/ui/main.svelte +var import_obsidian4 = require("obsidian"); + +// src/ui/tasks/store.ts +var import_obsidian2 = require("obsidian"); + +// src/ui/tasks/task.ts +var import_sha256 = __toESM(require_sha256()); +var Task = class { + constructor(rawContent, fileHandle, rowIndex, columnTagTable) { + const task = this._deserialise(rawContent, fileHandle, rowIndex); + this.id = task.id; + this.content = task.content; + this.done = task.done; + this.path = fileHandle.path; + this.rowIndex = rowIndex; + let column; + for (const tag of task.tags) { + if (tag in columnTagTable || tag === "done") { + column = tag; + break; + } + } + this.column = column; + } + _deserialise(rawContent, fileHandle, rowIndex) { + const [, remainder = ""] = rawContent.split("- ["); + const [status, content = ""] = remainder.split("] "); + const { tags, cleanedContent } = getTags(content); + return { + id: (0, import_sha256.default)(content + fileHandle.path + rowIndex).toString(), + done: status === "x", + content: cleanedContent, + tags + }; + } + serialise(data) { + var _a; + const done = data.column === "done" || this.done; + const column = (_a = data.column) != null ? _a : this.column; + return `- [${done ? "x" : " "}] ${this.content}${column ? ` #${column}` : ""}`; + } +}; +function isTaskString(input) { + return taskStringRegex.test(input); +} +var taskStringRegex = /^\s*-\s\[[x\s]\]\s/; +function getTags(content) { + const tags = /* @__PURE__ */ new Set(); + let cleanedContent = content; + const allMatches = content.matchAll(/#([\w-]+)/g); + for (const match of [...allMatches]) { + const maybeTag = match[1]; + if (maybeTag) { + tags.add(maybeTag); + cleanedContent = cleanedContent.replaceAll(`#${maybeTag}`, ""); + } + } + return { tags: [...tags], cleanedContent: cleanedContent.trim() }; +} + +// node_modules/svelte/src/runtime/store/index.js +var subscriber_queue = []; +function writable(value, start = noop) { + let stop; + const subscribers = /* @__PURE__ */ new Set(); + function set(new_value) { + if (safe_not_equal(value, new_value)) { + value = new_value; + if (stop) { + const run_queue = !subscriber_queue.length; + for (const subscriber of subscribers) { + subscriber[1](); + subscriber_queue.push(subscriber, value); + } + if (run_queue) { + for (let i = 0; i < subscriber_queue.length; i += 2) { + subscriber_queue[i][0](subscriber_queue[i + 1]); + } + subscriber_queue.length = 0; + } + } + } + } + function update2(fn) { + set(fn(value)); + } + function subscribe2(run2, invalidate = noop) { + const subscriber = [run2, invalidate]; + subscribers.add(subscriber); + if (subscribers.size === 1) { + stop = start(set, update2) || noop; + } + run2(value); + return () => { + subscribers.delete(subscriber); + if (subscribers.size === 0 && stop) { + stop(); + stop = null; + } + }; + } + return { set, update: update2, subscribe: subscribe2 }; +} + +// src/ui/tasks/tasks.ts +async function updateMapsFromFile({ + fileHandle, + taskIdsByFileHandle, + tasksByTaskId, + metadataByTaskId, + vault, + columnTagTableStore: columnTagTableStore2 +}) { + var _a; + try { + const previousTaskIds = (_a = taskIdsByFileHandle.get(fileHandle)) != null ? _a : /* @__PURE__ */ new Set(); + const newTaskIds = /* @__PURE__ */ new Set(); + const contents = await vault.read(fileHandle); + const rows = contents.split("\n"); + const columnTagTable = get_store_value(columnTagTableStore2); + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if (!row) { + continue; + } + if (isTaskString(row)) { + const task = new Task(row, fileHandle, i, columnTagTable); + newTaskIds.add(task.id); + tasksByTaskId.set(task.id, task); + metadataByTaskId.set(task.id, { rowIndex: i, fileHandle }); + previousTaskIds.delete(task.id); + } + } + for (const prevId of previousTaskIds) { + tasksByTaskId.delete(prevId); + metadataByTaskId.delete(prevId); + } + taskIdsByFileHandle.set(fileHandle, newTaskIds); + } catch (e) { + } +} + +// src/ui/tasks/actions.ts +var import_obsidian = require("obsidian"); +function createTaskActions({ + tasksByTaskId, + metadataByTaskId, + vault, + workspace +}) { + async function changeColumn(id, newColumn) { + const metadata = metadataByTaskId.get(id); + const task = tasksByTaskId.get(id); + if (!metadata || !task) { + return; + } + const newTaskString = task.serialise({ column: newColumn }); + await updateRow( + vault, + metadata.fileHandle, + metadata.rowIndex, + newTaskString + ); + } + async function viewFile(id) { + const metadata = metadataByTaskId.get(id); + if (!metadata) { + return; + } + const { fileHandle, rowIndex } = metadata; + const leaf = workspace.getLeaf("tab"); + await leaf.openFile(fileHandle); + const editorView = workspace.getActiveViewOfType(import_obsidian.MarkdownView); + editorView == null ? void 0 : editorView.editor.setCursor(rowIndex); + } + return { changeColumn, viewFile }; +} +async function updateRow(vault, fileHandle, row, newText) { + const file = await vault.read(fileHandle); + const rows = file.split("\n"); + if (rows.length < row) { + return; + } + rows[row] = newText; + const newFile = rows.join("\n"); + await vault.modify(fileHandle, newFile); +} + +// src/ui/tasks/store.ts +function createTasksStore(vault, workspace, registerEvent, columnTagTableStore2) { + const tasksStore = writable([]); + let timer; + const tasksByTaskId = /* @__PURE__ */ new Map(); + const metadataByTaskId = /* @__PURE__ */ new Map(); + const taskIdsByFileHandle = /* @__PURE__ */ new Map(); + const fileHandles = vault.getMarkdownFiles(); + function debounceSetTasks() { + if (!timer) { + timer = window.setTimeout(() => { + timer = void 0; + tasksStore.set([...tasksByTaskId.values()]); + }, 50); + } + } + for (const fileHandle of fileHandles) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore: columnTagTableStore2 + }).then(() => { + debounceSetTasks(); + }); + } + registerEvent( + vault.on("modify", (fileHandle) => { + if (fileHandle instanceof import_obsidian2.TFile) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore: columnTagTableStore2 + }).then(() => { + debounceSetTasks(); + }); + } + }) + ); + registerEvent( + vault.on("create", (fileHandle) => { + if (fileHandle instanceof import_obsidian2.TFile) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore: columnTagTableStore2 + }).then(() => { + debounceSetTasks(); + }); + } + }) + ); + registerEvent( + vault.on("delete", (fileHandle) => { + if (fileHandle instanceof import_obsidian2.TFile) { + } + }) + ); + registerEvent( + vault.on("rename", (fileHandle) => { + if (fileHandle instanceof import_obsidian2.TFile) { + } + }) + ); + const taskActions = createTaskActions({ + tasksByTaskId, + metadataByTaskId, + vault, + workspace + }); + return { tasksStore, taskActions }; +} + +// src/ui/columns/columns.ts +function createColumnTagTable({ + columns +}) { + const output = {}; + for (const column of columns) { + output[kebab(column)] = column; + } + return output; +} +function kebab(input) { + return input.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z0-9-]/g, "").replaceAll(/-+/g, "-"); +} +var columnTagTableStore = writable({}); + +// src/ui/components/task_menu.svelte +var import_obsidian3 = require("obsidian"); +function add_css(target) { + append_styles(target, "svelte-aq3t9y", "span.svelte-aq3t9y{width:24px;height:24px;display:flex;justify-content:center;align-items:center;border-radius:var(--radius-s);transition:background linear 100ms;cursor:pointer}span.svelte-aq3t9y:hover{background:var(--background-modifier-hover)}"); +} +function create_fragment(ctx) { + let span; + let mounted; + let dispose; + return { + c() { + span = element("span"); + attr(span, "role", "button"); + attr(span, "tabindex", "0"); + attr(span, "class", "svelte-aq3t9y"); + }, + m(target, anchor) { + insert(target, span, anchor); + ctx[4](span); + if (!mounted) { + dispose = listen( + span, + "click", + /*click_handler*/ + ctx[5] + ); + mounted = true; + } + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) { + detach(span); + } + ctx[4](null); + mounted = false; + dispose(); + } + }; +} +function instance($$self, $$props, $$invalidate) { + let $columnTagTableStore; + component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(6, $columnTagTableStore = $$value)); + let { task } = $$props; + let { taskActions } = $$props; + let element2; + function showMenu(e) { + const menu = new import_obsidian3.Menu(); + menu.addItem((i) => { + i.setTitle(`Go to file`).onClick(() => taskActions.viewFile(task.id)); + }); + menu.addSeparator(); + for (const [tag, label] of Object.entries($columnTagTableStore)) { + menu.addItem((i) => { + i.setTitle(`Move to ${label}`).onClick(() => taskActions.changeColumn(task.id, tag)); + if (task.column === tag) { + i.setDisabled(true); + } + }); + } + menu.addSeparator(); + menu.addItem((i) => { + i.setTitle(`Move to done`).onClick(() => taskActions.changeColumn(task.id, "done")); + if (task.column === "done") { + i.setDisabled(true); + } + }); + menu.showAtMouseEvent(e); + } + function span_binding($$value) { + binding_callbacks[$$value ? "unshift" : "push"](() => { + element2 = $$value; + $$invalidate(0, element2); + }); + } + const click_handler = (e) => showMenu(e); + $$self.$$set = ($$props2) => { + if ("task" in $$props2) + $$invalidate(2, task = $$props2.task); + if ("taskActions" in $$props2) + $$invalidate(3, taskActions = $$props2.taskActions); + }; + $$self.$$.update = () => { + if ($$self.$$.dirty & /*element*/ + 1) { + $: { + if (element2) { + (0, import_obsidian3.setIcon)(element2, "lucide-more-vertical"); + } + } + } + }; + return [element2, showMenu, task, taskActions, span_binding, click_handler]; +} +var Task_menu = class extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, { task: 2, taskActions: 3 }, add_css); + } +}; +var task_menu_default = Task_menu; + +// src/ui/components/task.svelte +function add_css2(target) { + append_styles(target, "svelte-1mufstf", ".task.svelte-1mufstf.svelte-1mufstf{background-color:var(--background-primary-alt);border-radius:var(--radius-m);border:var(--border-width) solid var(--background-modifier-border);padding:var(--size-4-2);display:grid;grid-template-columns:1fr auto}.task.svelte-1mufstf p.svelte-1mufstf{margin-top:0}.task.svelte-1mufstf p.svelte-1mufstf:last-child{margin-bottom:0}"); +} +function create_fragment2(ctx) { + let div1; + let div0; + let p; + let t0_value = ( + /*task*/ + ctx[0].content + "" + ); + let t0; + let t1; + let taskmenu; + let current; + taskmenu = new task_menu_default({ + props: { + task: ( + /*task*/ + ctx[0] + ), + taskActions: ( + /*taskActions*/ + ctx[1] + ) + } + }); + return { + c() { + div1 = element("div"); + div0 = element("div"); + p = element("p"); + t0 = text(t0_value); + t1 = space(); + create_component(taskmenu.$$.fragment); + attr(p, "class", "svelte-1mufstf"); + attr(div0, "class", "task-content"); + attr(div1, "class", "task svelte-1mufstf"); + }, + m(target, anchor) { + insert(target, div1, anchor); + append(div1, div0); + append(div0, p); + append(p, t0); + append(div1, t1); + mount_component(taskmenu, div1, null); + current = true; + }, + p(ctx2, [dirty]) { + if ((!current || dirty & /*task*/ + 1) && t0_value !== (t0_value = /*task*/ + ctx2[0].content + "")) + set_data(t0, t0_value); + const taskmenu_changes = {}; + if (dirty & /*task*/ + 1) + taskmenu_changes.task = /*task*/ + ctx2[0]; + if (dirty & /*taskActions*/ + 2) + taskmenu_changes.taskActions = /*taskActions*/ + ctx2[1]; + taskmenu.$set(taskmenu_changes); + }, + i(local) { + if (current) + return; + transition_in(taskmenu.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(taskmenu.$$.fragment, local); + current = false; + }, + d(detaching) { + if (detaching) { + detach(div1); + } + destroy_component(taskmenu); + } + }; +} +function instance2($$self, $$props, $$invalidate) { + let { task } = $$props; + let { taskActions } = $$props; + $$self.$$set = ($$props2) => { + if ("task" in $$props2) + $$invalidate(0, task = $$props2.task); + if ("taskActions" in $$props2) + $$invalidate(1, taskActions = $$props2.taskActions); + }; + return [task, taskActions]; +} +var Task3 = class extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance2, create_fragment2, safe_not_equal, { task: 0, taskActions: 1 }, add_css2); + } +}; +var task_default = Task3; + +// src/ui/components/column.svelte +function add_css3(target) { + append_styles(target, "svelte-e4tnso", ".column.svelte-e4tnso.svelte-e4tnso{width:220px;flex-shrink:0;padding:var(--size-4-3);border-radius:var(--radius-m);border:var(--border-width) solid var(--background-modifier-border);background-color:var(--background-primary)}.column.svelte-e4tnso h2.svelte-e4tnso{font-size:var(--font-ui-larger);font-weight:var(--font-bold);margin:0}.column.svelte-e4tnso .divide.svelte-e4tnso{width:calc(100% + calc(2 * var(--size-4-3)));border-bottom:var(--border-width) solid\n var(--background-modifier-border);margin:var(--size-4-3) calc(-1 * var(--size-4-3))}.column.svelte-e4tnso .tasks.svelte-e4tnso{display:flex;flex-direction:column;gap:var(--size-4-2)}"); +} +function get_each_context(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[7] = list[i]; + return child_ctx; +} +function create_if_block(ctx) { + let div2; + let h2; + let t0; + let t1; + let div0; + let t2; + let div1; + let current; + let each_value = ensure_array_like( + /*sortedTasks*/ + ctx[3] + ); + let each_blocks = []; + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i)); + } + const out = (i) => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + return { + c() { + div2 = element("div"); + h2 = element("h2"); + t0 = text( + /*columnTitle*/ + ctx[4] + ); + t1 = space(); + div0 = element("div"); + t2 = space(); + div1 = element("div"); + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + attr(h2, "class", "svelte-e4tnso"); + attr(div0, "class", "divide svelte-e4tnso"); + attr(div1, "class", "tasks svelte-e4tnso"); + attr(div2, "class", "column svelte-e4tnso"); + }, + m(target, anchor) { + insert(target, div2, anchor); + append(div2, h2); + append(h2, t0); + append(div2, t1); + append(div2, div0); + append(div2, t2); + append(div2, div1); + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div1, null); + } + } + current = true; + }, + p(ctx2, dirty) { + if (!current || dirty & /*columnTitle*/ + 16) + set_data( + t0, + /*columnTitle*/ + ctx2[4] + ); + if (dirty & /*sortedTasks, taskActions*/ + 12) { + each_value = ensure_array_like( + /*sortedTasks*/ + ctx2[3] + ); + let i; + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context(ctx2, each_value, i); + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(div1, null); + } + } + group_outros(); + for (i = each_value.length; i < each_blocks.length; i += 1) { + out(i); + } + check_outros(); + } + }, + i(local) { + if (current) + return; + for (let i = 0; i < each_value.length; i += 1) { + transition_in(each_blocks[i]); + } + current = true; + }, + o(local) { + each_blocks = each_blocks.filter(Boolean); + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + current = false; + }, + d(detaching) { + if (detaching) { + detach(div2); + } + destroy_each(each_blocks, detaching); + } + }; +} +function create_each_block(ctx) { + let taskcomponent; + let current; + taskcomponent = new task_default({ + props: { + task: ( + /*task*/ + ctx[7] + ), + taskActions: ( + /*taskActions*/ + ctx[2] + ) + } + }); + return { + c() { + create_component(taskcomponent.$$.fragment); + }, + m(target, anchor) { + mount_component(taskcomponent, target, anchor); + current = true; + }, + p(ctx2, dirty) { + const taskcomponent_changes = {}; + if (dirty & /*sortedTasks*/ + 8) + taskcomponent_changes.task = /*task*/ + ctx2[7]; + if (dirty & /*taskActions*/ + 4) + taskcomponent_changes.taskActions = /*taskActions*/ + ctx2[2]; + taskcomponent.$set(taskcomponent_changes); + }, + i(local) { + if (current) + return; + transition_in(taskcomponent.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(taskcomponent.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(taskcomponent, detaching); + } + }; +} +function create_fragment3(ctx) { + let if_block_anchor; + let current; + let if_block = (!/*hideOnEmpty*/ + ctx[0] || /*tasks*/ + ctx[1].length) && create_if_block(ctx); + return { + c() { + if (if_block) + if_block.c(); + if_block_anchor = empty(); + }, + m(target, anchor) { + if (if_block) + if_block.m(target, anchor); + insert(target, if_block_anchor, anchor); + current = true; + }, + p(ctx2, [dirty]) { + if (!/*hideOnEmpty*/ + ctx2[0] || /*tasks*/ + ctx2[1].length) { + if (if_block) { + if_block.p(ctx2, dirty); + if (dirty & /*hideOnEmpty, tasks*/ + 3) { + transition_in(if_block, 1); + } + } else { + if_block = create_if_block(ctx2); + if_block.c(); + transition_in(if_block, 1); + if_block.m(if_block_anchor.parentNode, if_block_anchor); + } + } else if (if_block) { + group_outros(); + transition_out(if_block, 1, 1, () => { + if_block = null; + }); + check_outros(); + } + }, + i(local) { + if (current) + return; + transition_in(if_block); + current = true; + }, + o(local) { + transition_out(if_block); + current = false; + }, + d(detaching) { + if (detaching) { + detach(if_block_anchor); + } + if (if_block) + if_block.d(detaching); + } + }; +} +function getColumnTitle(column, columnTagTable) { + switch (column) { + case "done": + return "Done"; + case "uncategorised": + return "Uncategorised"; + default: + return columnTagTable[column]; + } +} +function instance3($$self, $$props, $$invalidate) { + let columnTitle; + let sortedTasks; + let $columnTagTableStore; + component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(6, $columnTagTableStore = $$value)); + let { column } = $$props; + let { hideOnEmpty = false } = $$props; + let { tasks } = $$props; + let { taskActions } = $$props; + $$self.$$set = ($$props2) => { + if ("column" in $$props2) + $$invalidate(5, column = $$props2.column); + if ("hideOnEmpty" in $$props2) + $$invalidate(0, hideOnEmpty = $$props2.hideOnEmpty); + if ("tasks" in $$props2) + $$invalidate(1, tasks = $$props2.tasks); + if ("taskActions" in $$props2) + $$invalidate(2, taskActions = $$props2.taskActions); + }; + $$self.$$.update = () => { + if ($$self.$$.dirty & /*column, $columnTagTableStore*/ + 96) { + $: + $$invalidate(4, columnTitle = getColumnTitle(column, $columnTagTableStore)); + } + if ($$self.$$.dirty & /*tasks*/ + 2) { + $: + $$invalidate(3, sortedTasks = tasks.sort((a, b) => { + if (a.path === b.path) { + return a.rowIndex - b.rowIndex; + } else { + return a.path.localeCompare(b.path); + } + })); + } + }; + return [ + hideOnEmpty, + tasks, + taskActions, + sortedTasks, + columnTitle, + column, + $columnTagTableStore + ]; +} +var Column = class extends SvelteComponent { + constructor(options) { + super(); + init( + this, + options, + instance3, + create_fragment3, + safe_not_equal, + { + column: 5, + hideOnEmpty: 0, + tasks: 1, + taskActions: 2 + }, + add_css3 + ); + } +}; +var column_default = Column; + +// src/ui/main.svelte +function add_css4(target) { + append_styles(target, "svelte-3rjjgi", ".columns.svelte-3rjjgi.svelte-3rjjgi{max-width:100vw;overflow-x:scroll;padding-bottom:var(--size-4-3)}.columns.svelte-3rjjgi>div.svelte-3rjjgi{display:flex;gap:var(--size-4-3)}"); +} +function get_each_context2(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[10] = list[i]; + return child_ctx; +} +function create_each_block2(ctx) { + var _a; + let column_1; + let current; + column_1 = new column_default({ + props: { + column: ( + /*column*/ + ctx[10] + ), + tasks: ( + /*tasksByColumn*/ + (_a = ctx[1][ + /*column*/ + ctx[10] + ]) != null ? _a : [] + ), + taskActions: ( + /*taskActions*/ + ctx[3] + ) + } + }); + return { + c() { + create_component(column_1.$$.fragment); + }, + m(target, anchor) { + mount_component(column_1, target, anchor); + current = true; + }, + p(ctx2, dirty) { + var _a2; + const column_1_changes = {}; + if (dirty & /*columns*/ + 1) + column_1_changes.column = /*column*/ + ctx2[10]; + if (dirty & /*tasksByColumn, columns*/ + 3) + column_1_changes.tasks = /*tasksByColumn*/ + (_a2 = ctx2[1][ + /*column*/ + ctx2[10] + ]) != null ? _a2 : []; + column_1.$set(column_1_changes); + }, + i(local) { + if (current) + return; + transition_in(column_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(column_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(column_1, detaching); + } + }; +} +function create_fragment4(ctx) { + var _a; + let section; + let h1; + let t1; + let div1; + let div0; + let column0; + let t2; + let t3; + let column1; + let current; + column0 = new column_default({ + props: { + column: "uncategorised", + hideOnEmpty: true, + tasks: ( + /*tasksByColumn*/ + ctx[1]["uncategorised"] + ), + taskActions: ( + /*taskActions*/ + ctx[3] + ) + } + }); + let each_value = ensure_array_like( + /*columns*/ + ctx[0] + ); + let each_blocks = []; + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block2(get_each_context2(ctx, each_value, i)); + } + const out = (i) => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + column1 = new column_default({ + props: { + column: "done", + tasks: ( + /*tasksByColumn*/ + (_a = ctx[1]["done"]) != null ? _a : [] + ), + taskActions: ( + /*taskActions*/ + ctx[3] + ) + } + }); + return { + c() { + section = element("section"); + h1 = element("h1"); + h1.textContent = "Project Planner"; + t1 = space(); + div1 = element("div"); + div0 = element("div"); + create_component(column0.$$.fragment); + t2 = space(); + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + t3 = space(); + create_component(column1.$$.fragment); + attr(div0, "class", "svelte-3rjjgi"); + attr(div1, "class", "columns svelte-3rjjgi"); + }, + m(target, anchor) { + insert(target, section, anchor); + append(section, h1); + append(section, t1); + append(section, div1); + append(div1, div0); + mount_component(column0, div0, null); + append(div0, t2); + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div0, null); + } + } + append(div0, t3); + mount_component(column1, div0, null); + current = true; + }, + p(ctx2, [dirty]) { + var _a2; + const column0_changes = {}; + if (dirty & /*tasksByColumn*/ + 2) + column0_changes.tasks = /*tasksByColumn*/ + ctx2[1]["uncategorised"]; + column0.$set(column0_changes); + if (dirty & /*columns, tasksByColumn, taskActions*/ + 11) { + each_value = ensure_array_like( + /*columns*/ + ctx2[0] + ); + let i; + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context2(ctx2, each_value, i); + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block2(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(div0, t3); + } + } + group_outros(); + for (i = each_value.length; i < each_blocks.length; i += 1) { + out(i); + } + check_outros(); + } + const column1_changes = {}; + if (dirty & /*tasksByColumn*/ + 2) + column1_changes.tasks = /*tasksByColumn*/ + (_a2 = ctx2[1]["done"]) != null ? _a2 : []; + column1.$set(column1_changes); + }, + i(local) { + if (current) + return; + transition_in(column0.$$.fragment, local); + for (let i = 0; i < each_value.length; i += 1) { + transition_in(each_blocks[i]); + } + transition_in(column1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(column0.$$.fragment, local); + each_blocks = each_blocks.filter(Boolean); + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + transition_out(column1.$$.fragment, local); + current = false; + }, + d(detaching) { + if (detaching) { + detach(section); + } + destroy_component(column0); + destroy_each(each_blocks, detaching); + destroy_component(column1); + } + }; +} +function groupByColumnTag(tasks) { + var _a; + const output = { uncategorised: [], done: [] }; + for (const task of tasks) { + if (task.done) { + output["done"] = output["done"].concat(task); + } else if (task.column) { + output[task.column] = ((_a = output[task.column]) != null ? _a : []).concat(task); + } else { + output["uncategorised"] = output["uncategorised"].concat(task); + } + } + return output; +} +function instance4($$self, $$props, $$invalidate) { + let tasksByColumn; + let $tasksStore; + let $columnTagTableStore; + component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(9, $columnTagTableStore = $$value)); + let { vault } = $$props; + let { workspace } = $$props; + let { registerEvent } = $$props; + let { columnConfig = { + columns: ["Later", "Next week", "This week", "Today", "Pending"] + } } = $$props; + const { tasksStore, taskActions } = createTasksStore(vault, workspace, registerEvent, columnTagTableStore); + component_subscribe($$self, tasksStore, (value) => $$invalidate(8, $tasksStore = value)); + let columns; + $$self.$$set = ($$props2) => { + if ("vault" in $$props2) + $$invalidate(4, vault = $$props2.vault); + if ("workspace" in $$props2) + $$invalidate(5, workspace = $$props2.workspace); + if ("registerEvent" in $$props2) + $$invalidate(6, registerEvent = $$props2.registerEvent); + if ("columnConfig" in $$props2) + $$invalidate(7, columnConfig = $$props2.columnConfig); + }; + $$self.$$.update = () => { + if ($$self.$$.dirty & /*columnConfig*/ + 128) { + $: + columnTagTableStore.set(createColumnTagTable(columnConfig)); + } + if ($$self.$$.dirty & /*$columnTagTableStore*/ + 512) { + $: + $$invalidate(0, columns = Object.keys($columnTagTableStore)); + } + if ($$self.$$.dirty & /*$tasksStore*/ + 256) { + $: + $$invalidate(1, tasksByColumn = groupByColumnTag($tasksStore)); + } + }; + return [ + columns, + tasksByColumn, + tasksStore, + taskActions, + vault, + workspace, + registerEvent, + columnConfig, + $tasksStore, + $columnTagTableStore + ]; +} +var Main = class extends SvelteComponent { + constructor(options) { + super(); + init( + this, + options, + instance4, + create_fragment4, + safe_not_equal, + { + vault: 4, + workspace: 5, + registerEvent: 6, + columnConfig: 7 + }, + add_css4 + ); + } +}; +var main_default = Main; + +// src/ui/entry.ts +var APP_VIEW_NAME = "project-plan"; +var AppView = class extends import_obsidian5.ItemView { + constructor() { + super(...arguments); + this.icon = "kanban-square"; + } + getViewType() { + this.leaf.openFile; + return APP_VIEW_NAME; + } + getDisplayText() { + return "Project Planner"; + } + async onOpen() { + this.component = new main_default({ + target: this.contentEl, + props: { + workspace: this.app.workspace, + vault: this.app.vault, + registerEvent: this.registerEvent.bind(this) + } + }); + } + async onClose() { + var _a; + (_a = this.component) == null ? void 0 : _a.$destroy(); + } +}; + +// src/entry.ts +var Base = class extends import_obsidian6.Plugin { + async onload() { + this.registerView(APP_VIEW_NAME, (leaf) => new AppView(leaf)); + this.addRibbonIcon( + "kanban-square", + "Open Kanban", + () => this.activateView() + ); + } + onunload() { + } + async activateView() { + const { workspace } = this.app; + let leaf; + const leaves = workspace.getLeavesOfType(APP_VIEW_NAME); + if (leaves.length > 0) { + leaf = leaves[0]; + } else { + leaf = workspace.getLeaf("tab"); + await leaf.setViewState({ type: APP_VIEW_NAME, active: true }); + } + leaf && workspace.revealLeaf(leaf); + } +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9jb3JlLmpzIiwgIm5vZGVfbW9kdWxlcy9jcnlwdG8tanMvc2hhMjU2LmpzIiwgInNyYy9lbnRyeS50cyIsICJzcmMvdWkvZW50cnkudHMiLCAibm9kZV9tb2R1bGVzL3N2ZWx0ZS9zcmMvcnVudGltZS9pbnRlcm5hbC91dGlscy5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2dsb2JhbHMuanMiLCAibm9kZV9tb2R1bGVzL3N2ZWx0ZS9zcmMvcnVudGltZS9pbnRlcm5hbC9SZXNpemVPYnNlcnZlclNpbmdsZXRvbi5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2RvbS5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2xpZmVjeWNsZS5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL3NjaGVkdWxlci5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL3RyYW5zaXRpb25zLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvZWFjaC5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9zaGFyZWQvYm9vbGVhbl9hdHRyaWJ1dGVzLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvQ29tcG9uZW50LmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3NoYXJlZC92ZXJzaW9uLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvZGlzY2xvc2UtdmVyc2lvbi9pbmRleC5qcyIsICJzcmMvdWkvbWFpbi5zdmVsdGUiLCAic3JjL3VpL3Rhc2tzL3N0b3JlLnRzIiwgInNyYy91aS90YXNrcy90YXNrLnRzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvc3RvcmUvaW5kZXguanMiLCAic3JjL3VpL3Rhc2tzL3Rhc2tzLnRzIiwgInNyYy91aS90YXNrcy9hY3Rpb25zLnRzIiwgInNyYy91aS9jb2x1bW5zL2NvbHVtbnMudHMiLCAic3JjL3VpL2NvbXBvbmVudHMvdGFza19tZW51LnN2ZWx0ZSIsICJzcmMvdWkvY29tcG9uZW50cy90YXNrLnN2ZWx0ZSIsICJzcmMvdWkvY29tcG9uZW50cy9jb2x1bW4uc3ZlbHRlIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyI7KGZ1bmN0aW9uIChyb290LCBmYWN0b3J5KSB7XG5cdGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuXHRcdC8vIENvbW1vbkpTXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzID0gZmFjdG9yeSgpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0cm9vdC5DcnlwdG9KUyA9IGZhY3RvcnkoKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoKSB7XG5cblx0LypnbG9iYWxzIHdpbmRvdywgZ2xvYmFsLCByZXF1aXJlKi9cblxuXHQvKipcblx0ICogQ3J5cHRvSlMgY29yZSBjb21wb25lbnRzLlxuXHQgKi9cblx0dmFyIENyeXB0b0pTID0gQ3J5cHRvSlMgfHwgKGZ1bmN0aW9uIChNYXRoLCB1bmRlZmluZWQpIHtcblxuXHQgICAgdmFyIGNyeXB0bztcblxuXHQgICAgLy8gTmF0aXZlIGNyeXB0byBmcm9tIHdpbmRvdyAoQnJvd3Nlcilcblx0ICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuY3J5cHRvKSB7XG5cdCAgICAgICAgY3J5cHRvID0gd2luZG93LmNyeXB0bztcblx0ICAgIH1cblxuXHQgICAgLy8gTmF0aXZlIGNyeXB0byBpbiB3ZWIgd29ya2VyIChCcm93c2VyKVxuXHQgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiBzZWxmLmNyeXB0bykge1xuXHQgICAgICAgIGNyeXB0byA9IHNlbGYuY3J5cHRvO1xuXHQgICAgfVxuXG5cdCAgICAvLyBOYXRpdmUgY3J5cHRvIGZyb20gd29ya2VyXG5cdCAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbFRoaXMuY3J5cHRvKSB7XG5cdCAgICAgICAgY3J5cHRvID0gZ2xvYmFsVGhpcy5jcnlwdG87XG5cdCAgICB9XG5cblx0ICAgIC8vIE5hdGl2ZSAoZXhwZXJpbWVudGFsIElFIDExKSBjcnlwdG8gZnJvbSB3aW5kb3cgKEJyb3dzZXIpXG5cdCAgICBpZiAoIWNyeXB0byAmJiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cubXNDcnlwdG8pIHtcblx0ICAgICAgICBjcnlwdG8gPSB3aW5kb3cubXNDcnlwdG87XG5cdCAgICB9XG5cblx0ICAgIC8vIE5hdGl2ZSBjcnlwdG8gZnJvbSBnbG9iYWwgKE5vZGVKUylcblx0ICAgIGlmICghY3J5cHRvICYmIHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbC5jcnlwdG8pIHtcblx0ICAgICAgICBjcnlwdG8gPSBnbG9iYWwuY3J5cHRvO1xuXHQgICAgfVxuXG5cdCAgICAvLyBOYXRpdmUgY3J5cHRvIGltcG9ydCB2aWEgcmVxdWlyZSAoTm9kZUpTKVxuXHQgICAgaWYgKCFjcnlwdG8gJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicpIHtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcblx0ICAgICAgICB9IGNhdGNoIChlcnIpIHt9XG5cdCAgICB9XG5cblx0ICAgIC8qXG5cdCAgICAgKiBDcnlwdG9ncmFwaGljYWxseSBzZWN1cmUgcHNldWRvcmFuZG9tIG51bWJlciBnZW5lcmF0b3Jcblx0ICAgICAqXG5cdCAgICAgKiBBcyBNYXRoLnJhbmRvbSgpIGlzIGNyeXB0b2dyYXBoaWNhbGx5IG5vdCBzYWZlIHRvIHVzZVxuXHQgICAgICovXG5cdCAgICB2YXIgY3J5cHRvU2VjdXJlUmFuZG9tSW50ID0gZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIGlmIChjcnlwdG8pIHtcblx0ICAgICAgICAgICAgLy8gVXNlIGdldFJhbmRvbVZhbHVlcyBtZXRob2QgKEJyb3dzZXIpXG5cdCAgICAgICAgICAgIGlmICh0eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDMyQXJyYXkoMSkpWzBdO1xuXHQgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7fVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gVXNlIHJhbmRvbUJ5dGVzIG1ldGhvZCAoTm9kZUpTKVxuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGNyeXB0by5yYW5kb21CeXRlcyA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3J5cHRvLnJhbmRvbUJ5dGVzKDQpLnJlYWRJbnQzMkxFKCk7XG5cdCAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHt9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05hdGl2ZSBjcnlwdG8gbW9kdWxlIGNvdWxkIG5vdCBiZSB1c2VkIHRvIGdldCBzZWN1cmUgcmFuZG9tIG51bWJlci4nKTtcblx0ICAgIH07XG5cblx0ICAgIC8qXG5cdCAgICAgKiBMb2NhbCBwb2x5ZmlsbCBvZiBPYmplY3QuY3JlYXRlXG5cblx0ICAgICAqL1xuXHQgICAgdmFyIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgKGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICBmdW5jdGlvbiBGKCkge31cblxuXHQgICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqKSB7XG5cdCAgICAgICAgICAgIHZhciBzdWJ0eXBlO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gb2JqO1xuXG5cdCAgICAgICAgICAgIHN1YnR5cGUgPSBuZXcgRigpO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gbnVsbDtcblxuXHQgICAgICAgICAgICByZXR1cm4gc3VidHlwZTtcblx0ICAgICAgICB9O1xuXHQgICAgfSgpKTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBDcnlwdG9KUyBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogTGlicmFyeSBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX2xpYiA9IEMubGliID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogQmFzZSBvYmplY3QgZm9yIHByb3RvdHlwYWwgaW5oZXJpdGFuY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBCYXNlID0gQ19saWIuQmFzZSA9IChmdW5jdGlvbiAoKSB7XG5cblxuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gdGhpcyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdmVycmlkZXMgUHJvcGVydGllcyB0byBjb3B5IGludG8gdGhlIG5ldyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIG5ldyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIHZhciBNeVR5cGUgPSBDcnlwdG9KUy5saWIuQmFzZS5leHRlbmQoe1xuXHQgICAgICAgICAgICAgKiAgICAgICAgIGZpZWxkOiAndmFsdWUnLFxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgICAgIG1ldGhvZDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgKiAgICAgICAgIH1cblx0ICAgICAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAgICAgKi9cblx0ICAgICAgICAgICAgZXh0ZW5kOiBmdW5jdGlvbiAob3ZlcnJpZGVzKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTcGF3blxuXHQgICAgICAgICAgICAgICAgdmFyIHN1YnR5cGUgPSBjcmVhdGUodGhpcyk7XG5cblx0ICAgICAgICAgICAgICAgIC8vIEF1Z21lbnRcblx0ICAgICAgICAgICAgICAgIGlmIChvdmVycmlkZXMpIHtcblx0ICAgICAgICAgICAgICAgICAgICBzdWJ0eXBlLm1peEluKG92ZXJyaWRlcyk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBkZWZhdWx0IGluaXRpYWxpemVyXG5cdCAgICAgICAgICAgICAgICBpZiAoIXN1YnR5cGUuaGFzT3duUHJvcGVydHkoJ2luaXQnKSB8fCB0aGlzLmluaXQgPT09IHN1YnR5cGUuaW5pdCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHN1YnR5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgc3VidHlwZS4kc3VwZXIuaW5pdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHQgICAgICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemVyJ3MgcHJvdG90eXBlIGlzIHRoZSBzdWJ0eXBlIG9iamVjdFxuXHQgICAgICAgICAgICAgICAgc3VidHlwZS5pbml0LnByb3RvdHlwZSA9IHN1YnR5cGU7XG5cblx0ICAgICAgICAgICAgICAgIC8vIFJlZmVyZW5jZSBzdXBlcnR5cGVcblx0ICAgICAgICAgICAgICAgIHN1YnR5cGUuJHN1cGVyID0gdGhpcztcblxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHN1YnR5cGU7XG5cdCAgICAgICAgICAgIH0sXG5cblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIEV4dGVuZHMgdGhpcyBvYmplY3QgYW5kIHJ1bnMgdGhlIGluaXQgbWV0aG9kLlxuXHQgICAgICAgICAgICAgKiBBcmd1bWVudHMgdG8gY3JlYXRlKCkgd2lsbCBiZSBwYXNzZWQgdG8gaW5pdCgpLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBuZXcgb2JqZWN0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICB2YXIgaW5zdGFuY2UgPSBNeVR5cGUuY3JlYXRlKCk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IHRoaXMuZXh0ZW5kKCk7XG5cdCAgICAgICAgICAgICAgICBpbnN0YW5jZS5pbml0LmFwcGx5KGluc3RhbmNlLCBhcmd1bWVudHMpO1xuXG5cdCAgICAgICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG5cdCAgICAgICAgICAgIH0sXG5cblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCBvYmplY3QuXG5cdCAgICAgICAgICAgICAqIE92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGFkZCBzb21lIGxvZ2ljIHdoZW4geW91ciBvYmplY3RzIGFyZSBjcmVhdGVkLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgdmFyIE15VHlwZSA9IENyeXB0b0pTLmxpYi5CYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgICAgICAqICAgICAgICAgaW5pdDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgKiAgICAgICAgICAgICAvLyAuLi5cblx0ICAgICAgICAgICAgICogICAgICAgICB9XG5cdCAgICAgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgICAgICovXG5cdCAgICAgICAgICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgfSxcblxuXHQgICAgICAgICAgICAvKipcblx0ICAgICAgICAgICAgICogQ29waWVzIHByb3BlcnRpZXMgaW50byB0aGlzIG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgVGhlIHByb3BlcnRpZXMgdG8gbWl4IGluLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgTXlUeXBlLm1peEluKHtcblx0ICAgICAgICAgICAgICogICAgICAgICBmaWVsZDogJ3ZhbHVlJ1xuXHQgICAgICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBtaXhJbjogZnVuY3Rpb24gKHByb3BlcnRpZXMpIHtcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BlcnR5TmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3Byb3BlcnR5TmFtZV0gPSBwcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV07XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgICAgICAvLyBJRSB3b24ndCBjb3B5IHRvU3RyaW5nIHVzaW5nIHRoZSBsb29wIGFib3ZlXG5cdCAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eSgndG9TdHJpbmcnKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXMudG9TdHJpbmcgPSBwcm9wZXJ0aWVzLnRvU3RyaW5nO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9LFxuXG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBDcmVhdGVzIGEgY29weSBvZiB0aGlzIG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICB2YXIgY2xvbmUgPSBpbnN0YW5jZS5jbG9uZSgpO1xuXHQgICAgICAgICAgICAgKi9cblx0ICAgICAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXQucHJvdG90eXBlLmV4dGVuZCh0aGlzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9KCkpO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFuIGFycmF5IG9mIDMyLWJpdCB3b3Jkcy5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkge0FycmF5fSB3b3JkcyBUaGUgYXJyYXkgb2YgMzItYml0IHdvcmRzLlxuXHQgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IHNpZ0J5dGVzIFRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgYnl0ZXMgaW4gdGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICovXG5cdCAgICB2YXIgV29yZEFycmF5ID0gQ19saWIuV29yZEFycmF5ID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtBcnJheX0gd29yZHMgKE9wdGlvbmFsKSBBbiBhcnJheSBvZiAzMi1iaXQgd29yZHMuXG5cdCAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IHNpZ0J5dGVzIChPcHRpb25hbCkgVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBieXRlcyBpbiB0aGUgd29yZHMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5saWIuV29yZEFycmF5LmNyZWF0ZSgpO1xuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5jcmVhdGUoWzB4MDAwMTAyMDMsIDB4MDQwNTA2MDddKTtcblx0ICAgICAgICAgKiAgICAgdmFyIHdvcmRBcnJheSA9IENyeXB0b0pTLmxpYi5Xb3JkQXJyYXkuY3JlYXRlKFsweDAwMDEwMjAzLCAweDA0MDUwNjA3XSwgNik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgaW5pdDogZnVuY3Rpb24gKHdvcmRzLCBzaWdCeXRlcykge1xuXHQgICAgICAgICAgICB3b3JkcyA9IHRoaXMud29yZHMgPSB3b3JkcyB8fCBbXTtcblxuXHQgICAgICAgICAgICBpZiAoc2lnQnl0ZXMgIT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzID0gc2lnQnl0ZXM7XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzID0gd29yZHMubGVuZ3RoICogNDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIHdvcmQgYXJyYXkgdG8gYSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0VuY29kZXJ9IGVuY29kZXIgKE9wdGlvbmFsKSBUaGUgZW5jb2Rpbmcgc3RyYXRlZ3kgdG8gdXNlLiBEZWZhdWx0OiBDcnlwdG9KUy5lbmMuSGV4XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBzdHJpbmdpZmllZCB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgc3RyaW5nID0gd29yZEFycmF5ICsgJyc7XG5cdCAgICAgICAgICogICAgIHZhciBzdHJpbmcgPSB3b3JkQXJyYXkudG9TdHJpbmcoKTtcblx0ICAgICAgICAgKiAgICAgdmFyIHN0cmluZyA9IHdvcmRBcnJheS50b1N0cmluZyhDcnlwdG9KUy5lbmMuVXRmOCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIChlbmNvZGVyKSB7XG5cdCAgICAgICAgICAgIHJldHVybiAoZW5jb2RlciB8fCBIZXgpLnN0cmluZ2lmeSh0aGlzKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29uY2F0ZW5hdGVzIGEgd29yZCBhcnJheSB0byB0aGlzIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5IHRvIGFwcGVuZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB3b3JkQXJyYXkxLmNvbmNhdCh3b3JkQXJyYXkyKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjb25jYXQ6IGZ1bmN0aW9uICh3b3JkQXJyYXkpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciB0aGlzV29yZHMgPSB0aGlzLndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgdGhhdFdvcmRzID0gd29yZEFycmF5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgdGhpc1NpZ0J5dGVzID0gdGhpcy5zaWdCeXRlcztcblx0ICAgICAgICAgICAgdmFyIHRoYXRTaWdCeXRlcyA9IHdvcmRBcnJheS5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDbGFtcCBleGNlc3MgYml0c1xuXHQgICAgICAgICAgICB0aGlzLmNsYW1wKCk7XG5cblx0ICAgICAgICAgICAgLy8gQ29uY2F0XG5cdCAgICAgICAgICAgIGlmICh0aGlzU2lnQnl0ZXMgJSA0KSB7XG5cdCAgICAgICAgICAgICAgICAvLyBDb3B5IG9uZSBieXRlIGF0IGEgdGltZVxuXHQgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGF0U2lnQnl0ZXM7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgICAgIHZhciB0aGF0Qnl0ZSA9ICh0aGF0V29yZHNbaSA+Pj4gMl0gPj4+ICgyNCAtIChpICUgNCkgKiA4KSkgJiAweGZmO1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXNXb3Jkc1sodGhpc1NpZ0J5dGVzICsgaSkgPj4+IDJdIHw9IHRoYXRCeXRlIDw8ICgyNCAtICgodGhpc1NpZ0J5dGVzICsgaSkgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgLy8gQ29weSBvbmUgd29yZCBhdCBhIHRpbWVcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhhdFNpZ0J5dGVzOyBqICs9IDQpIHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzV29yZHNbKHRoaXNTaWdCeXRlcyArIGopID4+PiAyXSA9IHRoYXRXb3Jkc1tqID4+PiAyXTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzICs9IHRoYXRTaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDaGFpbmFibGVcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJlbW92ZXMgaW5zaWduaWZpY2FudCBiaXRzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB3b3JkQXJyYXkuY2xhbXAoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjbGFtcDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gdGhpcy53b3Jkcztcblx0ICAgICAgICAgICAgdmFyIHNpZ0J5dGVzID0gdGhpcy5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDbGFtcFxuXHQgICAgICAgICAgICB3b3Jkc1tzaWdCeXRlcyA+Pj4gMl0gJj0gMHhmZmZmZmZmZiA8PCAoMzIgLSAoc2lnQnl0ZXMgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICB3b3Jkcy5sZW5ndGggPSBNYXRoLmNlaWwoc2lnQnl0ZXMgLyA0KTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIGNvcHkgb2YgdGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjbG9uZSA9IHdvcmRBcnJheS5jbG9uZSgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNsb25lOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHZhciBjbG9uZSA9IEJhc2UuY2xvbmUuY2FsbCh0aGlzKTtcblx0ICAgICAgICAgICAgY2xvbmUud29yZHMgPSB0aGlzLndvcmRzLnNsaWNlKDApO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIHdvcmQgYXJyYXkgZmlsbGVkIHdpdGggcmFuZG9tIGJ5dGVzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IG5CeXRlcyBUaGUgbnVtYmVyIG9mIHJhbmRvbSBieXRlcyB0byBnZW5lcmF0ZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHJhbmRvbSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5yYW5kb20oMTYpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHJhbmRvbTogZnVuY3Rpb24gKG5CeXRlcykge1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSBbXTtcblxuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5CeXRlczsgaSArPSA0KSB7XG5cdCAgICAgICAgICAgICAgICB3b3Jkcy5wdXNoKGNyeXB0b1NlY3VyZVJhbmRvbUludCgpKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBuZXcgV29yZEFycmF5LmluaXQod29yZHMsIG5CeXRlcyk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogRW5jb2RlciBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX2VuYyA9IEMuZW5jID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogSGV4IGVuY29kaW5nIHN0cmF0ZWd5LlxuXHQgICAgICovXG5cdCAgICB2YXIgSGV4ID0gQ19lbmMuSGV4ID0ge1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIGEgd29yZCBhcnJheSB0byBhIGhleCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgaGV4IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhleFN0cmluZyA9IENyeXB0b0pTLmVuYy5IZXguc3RyaW5naWZ5KHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbiAod29yZEFycmF5KSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSB3b3JkQXJyYXkud29yZHM7XG5cdCAgICAgICAgICAgIHZhciBzaWdCeXRlcyA9IHdvcmRBcnJheS5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDb252ZXJ0XG5cdCAgICAgICAgICAgIHZhciBoZXhDaGFycyA9IFtdO1xuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpZ0J5dGVzOyBpKyspIHtcblx0ICAgICAgICAgICAgICAgIHZhciBiaXRlID0gKHdvcmRzW2kgPj4+IDJdID4+PiAoMjQgLSAoaSAlIDQpICogOCkpICYgMHhmZjtcblx0ICAgICAgICAgICAgICAgIGhleENoYXJzLnB1c2goKGJpdGUgPj4+IDQpLnRvU3RyaW5nKDE2KSk7XG5cdCAgICAgICAgICAgICAgICBoZXhDaGFycy5wdXNoKChiaXRlICYgMHgwZikudG9TdHJpbmcoMTYpKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBoZXhDaGFycy5qb2luKCcnKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSBoZXggc3RyaW5nIHRvIGEgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBoZXhTdHIgVGhlIGhleCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMuZW5jLkhleC5wYXJzZShoZXhTdHJpbmcpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHBhcnNlOiBmdW5jdGlvbiAoaGV4U3RyKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0XG5cdCAgICAgICAgICAgIHZhciBoZXhTdHJMZW5ndGggPSBoZXhTdHIubGVuZ3RoO1xuXG5cdCAgICAgICAgICAgIC8vIENvbnZlcnRcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gW107XG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGV4U3RyTGVuZ3RoOyBpICs9IDIpIHtcblx0ICAgICAgICAgICAgICAgIHdvcmRzW2kgPj4+IDNdIHw9IHBhcnNlSW50KGhleFN0ci5zdWJzdHIoaSwgMiksIDE2KSA8PCAoMjQgLSAoaSAlIDgpICogNCk7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICByZXR1cm4gbmV3IFdvcmRBcnJheS5pbml0KHdvcmRzLCBoZXhTdHJMZW5ndGggLyAyKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIExhdGluMSBlbmNvZGluZyBzdHJhdGVneS5cblx0ICAgICAqL1xuXHQgICAgdmFyIExhdGluMSA9IENfZW5jLkxhdGluMSA9IHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIHdvcmQgYXJyYXkgdG8gYSBMYXRpbjEgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IHdvcmRBcnJheSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIExhdGluMSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBsYXRpbjFTdHJpbmcgPSBDcnlwdG9KUy5lbmMuTGF0aW4xLnN0cmluZ2lmeSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHN0cmluZ2lmeTogZnVuY3Rpb24gKHdvcmRBcnJheSkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gd29yZEFycmF5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgc2lnQnl0ZXMgPSB3b3JkQXJyYXkuc2lnQnl0ZXM7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgbGF0aW4xQ2hhcnMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaWdCeXRlczsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgYml0ZSA9ICh3b3Jkc1tpID4+PiAyXSA+Pj4gKDI0IC0gKGkgJSA0KSAqIDgpKSAmIDB4ZmY7XG5cdCAgICAgICAgICAgICAgICBsYXRpbjFDaGFycy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYml0ZSkpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGxhdGluMUNoYXJzLmpvaW4oJycpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIExhdGluMSBzdHJpbmcgdG8gYSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGxhdGluMVN0ciBUaGUgTGF0aW4xIHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5lbmMuTGF0aW4xLnBhcnNlKGxhdGluMVN0cmluZyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChsYXRpbjFTdHIpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIGxhdGluMVN0ckxlbmd0aCA9IGxhdGluMVN0ci5sZW5ndGg7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXRpbjFTdHJMZW5ndGg7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgd29yZHNbaSA+Pj4gMl0gfD0gKGxhdGluMVN0ci5jaGFyQ29kZUF0KGkpICYgMHhmZikgPDwgKDI0IC0gKGkgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIG5ldyBXb3JkQXJyYXkuaW5pdCh3b3JkcywgbGF0aW4xU3RyTGVuZ3RoKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIFVURi04IGVuY29kaW5nIHN0cmF0ZWd5LlxuXHQgICAgICovXG5cdCAgICB2YXIgVXRmOCA9IENfZW5jLlV0ZjggPSB7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSB3b3JkIGFycmF5IHRvIGEgVVRGLTggc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IHdvcmRBcnJheSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIFVURi04IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHV0ZjhTdHJpbmcgPSBDcnlwdG9KUy5lbmMuVXRmOC5zdHJpbmdpZnkod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBzdHJpbmdpZnk6IGZ1bmN0aW9uICh3b3JkQXJyYXkpIHtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoZXNjYXBlKExhdGluMS5zdHJpbmdpZnkod29yZEFycmF5KSkpO1xuXHQgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01hbGZvcm1lZCBVVEYtOCBkYXRhJyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSBVVEYtOCBzdHJpbmcgdG8gYSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHV0ZjhTdHIgVGhlIFVURi04IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5lbmMuVXRmOC5wYXJzZSh1dGY4U3RyaW5nKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBwYXJzZTogZnVuY3Rpb24gKHV0ZjhTdHIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIExhdGluMS5wYXJzZSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQodXRmOFN0cikpKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFic3RyYWN0IGJ1ZmZlcmVkIGJsb2NrIGFsZ29yaXRobSB0ZW1wbGF0ZS5cblx0ICAgICAqXG5cdCAgICAgKiBUaGUgcHJvcGVydHkgYmxvY2tTaXplIG11c3QgYmUgaW1wbGVtZW50ZWQgaW4gYSBjb25jcmV0ZSBzdWJ0eXBlLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBfbWluQnVmZmVyU2l6ZSBUaGUgbnVtYmVyIG9mIGJsb2NrcyB0aGF0IHNob3VsZCBiZSBrZXB0IHVucHJvY2Vzc2VkIGluIHRoZSBidWZmZXIuIERlZmF1bHQ6IDBcblx0ICAgICAqL1xuXHQgICAgdmFyIEJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0gPSBDX2xpYi5CdWZmZXJlZEJsb2NrQWxnb3JpdGhtID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJlc2V0cyB0aGlzIGJsb2NrIGFsZ29yaXRobSdzIGRhdGEgYnVmZmVyIHRvIGl0cyBpbml0aWFsIHN0YXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBidWZmZXJlZEJsb2NrQWxnb3JpdGhtLnJlc2V0KCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgLy8gSW5pdGlhbCB2YWx1ZXNcblx0ICAgICAgICAgICAgdGhpcy5fZGF0YSA9IG5ldyBXb3JkQXJyYXkuaW5pdCgpO1xuXHQgICAgICAgICAgICB0aGlzLl9uRGF0YUJ5dGVzID0gMDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQWRkcyBuZXcgZGF0YSB0byB0aGlzIGJsb2NrIGFsZ29yaXRobSdzIGJ1ZmZlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gZGF0YSBUaGUgZGF0YSB0byBhcHBlbmQuIFN0cmluZ3MgYXJlIGNvbnZlcnRlZCB0byBhIFdvcmRBcnJheSB1c2luZyBVVEYtOC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fYXBwZW5kKCdkYXRhJyk7XG5cdCAgICAgICAgICogICAgIGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uX2FwcGVuZCh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9hcHBlbmQ6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdCAgICAgICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIFdvcmRBcnJheSwgZWxzZSBhc3N1bWUgV29yZEFycmF5IGFscmVhZHlcblx0ICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICBkYXRhID0gVXRmOC5wYXJzZShkYXRhKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIEFwcGVuZFxuXHQgICAgICAgICAgICB0aGlzLl9kYXRhLmNvbmNhdChkYXRhKTtcblx0ICAgICAgICAgICAgdGhpcy5fbkRhdGFCeXRlcyArPSBkYXRhLnNpZ0J5dGVzO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBQcm9jZXNzZXMgYXZhaWxhYmxlIGRhdGEgYmxvY2tzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogVGhpcyBtZXRob2QgaW52b2tlcyBfZG9Qcm9jZXNzQmxvY2sob2Zmc2V0KSwgd2hpY2ggbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBhIGNvbmNyZXRlIHN1YnR5cGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGRvRmx1c2ggV2hldGhlciBhbGwgYmxvY2tzIGFuZCBwYXJ0aWFsIGJsb2NrcyBzaG91bGQgYmUgcHJvY2Vzc2VkLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgcHJvY2Vzc2VkIGRhdGEuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBwcm9jZXNzZWREYXRhID0gYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fcHJvY2VzcygpO1xuXHQgICAgICAgICAqICAgICB2YXIgcHJvY2Vzc2VkRGF0YSA9IGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uX3Byb2Nlc3MoISEnZmx1c2gnKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBfcHJvY2VzczogZnVuY3Rpb24gKGRvRmx1c2gpIHtcblx0ICAgICAgICAgICAgdmFyIHByb2Nlc3NlZFdvcmRzO1xuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cdCAgICAgICAgICAgIHZhciBkYXRhV29yZHMgPSBkYXRhLndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgZGF0YVNpZ0J5dGVzID0gZGF0YS5zaWdCeXRlcztcblx0ICAgICAgICAgICAgdmFyIGJsb2NrU2l6ZSA9IHRoaXMuYmxvY2tTaXplO1xuXHQgICAgICAgICAgICB2YXIgYmxvY2tTaXplQnl0ZXMgPSBibG9ja1NpemUgKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIENvdW50IGJsb2NrcyByZWFkeVxuXHQgICAgICAgICAgICB2YXIgbkJsb2Nrc1JlYWR5ID0gZGF0YVNpZ0J5dGVzIC8gYmxvY2tTaXplQnl0ZXM7XG5cdCAgICAgICAgICAgIGlmIChkb0ZsdXNoKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBSb3VuZCB1cCB0byBpbmNsdWRlIHBhcnRpYWwgYmxvY2tzXG5cdCAgICAgICAgICAgICAgICBuQmxvY2tzUmVhZHkgPSBNYXRoLmNlaWwobkJsb2Nrc1JlYWR5KTtcblx0ICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIC8vIFJvdW5kIGRvd24gdG8gaW5jbHVkZSBvbmx5IGZ1bGwgYmxvY2tzLFxuXHQgICAgICAgICAgICAgICAgLy8gbGVzcyB0aGUgbnVtYmVyIG9mIGJsb2NrcyB0aGF0IG11c3QgcmVtYWluIGluIHRoZSBidWZmZXJcblx0ICAgICAgICAgICAgICAgIG5CbG9ja3NSZWFkeSA9IE1hdGgubWF4KChuQmxvY2tzUmVhZHkgfCAwKSAtIHRoaXMuX21pbkJ1ZmZlclNpemUsIDApO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQ291bnQgd29yZHMgcmVhZHlcblx0ICAgICAgICAgICAgdmFyIG5Xb3Jkc1JlYWR5ID0gbkJsb2Nrc1JlYWR5ICogYmxvY2tTaXplO1xuXG5cdCAgICAgICAgICAgIC8vIENvdW50IGJ5dGVzIHJlYWR5XG5cdCAgICAgICAgICAgIHZhciBuQnl0ZXNSZWFkeSA9IE1hdGgubWluKG5Xb3Jkc1JlYWR5ICogNCwgZGF0YVNpZ0J5dGVzKTtcblxuXHQgICAgICAgICAgICAvLyBQcm9jZXNzIGJsb2Nrc1xuXHQgICAgICAgICAgICBpZiAobldvcmRzUmVhZHkpIHtcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIG9mZnNldCA9IDA7IG9mZnNldCA8IG5Xb3Jkc1JlYWR5OyBvZmZzZXQgKz0gYmxvY2tTaXplKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1hbGdvcml0aG0gbG9naWNcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb1Byb2Nlc3NCbG9jayhkYXRhV29yZHMsIG9mZnNldCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBwcm9jZXNzZWQgd29yZHNcblx0ICAgICAgICAgICAgICAgIHByb2Nlc3NlZFdvcmRzID0gZGF0YVdvcmRzLnNwbGljZSgwLCBuV29yZHNSZWFkeSk7XG5cdCAgICAgICAgICAgICAgICBkYXRhLnNpZ0J5dGVzIC09IG5CeXRlc1JlYWR5O1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gUmV0dXJuIHByb2Nlc3NlZCB3b3Jkc1xuXHQgICAgICAgICAgICByZXR1cm4gbmV3IFdvcmRBcnJheS5pbml0KHByb2Nlc3NlZFdvcmRzLCBuQnl0ZXNSZWFkeSk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIHRoaXMgb2JqZWN0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjbG9uZSA9IGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uY2xvbmUoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjbG9uZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICB2YXIgY2xvbmUgPSBCYXNlLmNsb25lLmNhbGwodGhpcyk7XG5cdCAgICAgICAgICAgIGNsb25lLl9kYXRhID0gdGhpcy5fZGF0YS5jbG9uZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgX21pbkJ1ZmZlclNpemU6IDBcblx0ICAgIH0pO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFic3RyYWN0IGhhc2hlciB0ZW1wbGF0ZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gYmxvY2tTaXplIFRoZSBudW1iZXIgb2YgMzItYml0IHdvcmRzIHRoaXMgaGFzaGVyIG9wZXJhdGVzIG9uLiBEZWZhdWx0OiAxNiAoNTEyIGJpdHMpXG5cdCAgICAgKi9cblx0ICAgIHZhciBIYXNoZXIgPSBDX2xpYi5IYXNoZXIgPSBCdWZmZXJlZEJsb2NrQWxnb3JpdGhtLmV4dGVuZCh7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29uZmlndXJhdGlvbiBvcHRpb25zLlxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNmZzogQmFzZS5leHRlbmQoKSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCBoYXNoZXIuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgaGFzaCBjb21wdXRhdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2hlciA9IENyeXB0b0pTLmFsZ28uU0hBMjU2LmNyZWF0ZSgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGluaXQ6IGZ1bmN0aW9uIChjZmcpIHtcblx0ICAgICAgICAgICAgLy8gQXBwbHkgY29uZmlnIGRlZmF1bHRzXG5cdCAgICAgICAgICAgIHRoaXMuY2ZnID0gdGhpcy5jZmcuZXh0ZW5kKGNmZyk7XG5cblx0ICAgICAgICAgICAgLy8gU2V0IGluaXRpYWwgdmFsdWVzXG5cdCAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmVzZXRzIHRoaXMgaGFzaGVyIHRvIGl0cyBpbml0aWFsIHN0YXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBoYXNoZXIucmVzZXQoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBSZXNldCBkYXRhIGJ1ZmZlclxuXHQgICAgICAgICAgICBCdWZmZXJlZEJsb2NrQWxnb3JpdGhtLnJlc2V0LmNhbGwodGhpcyk7XG5cblx0ICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1oYXNoZXIgbG9naWNcblx0ICAgICAgICAgICAgdGhpcy5fZG9SZXNldCgpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBVcGRhdGVzIHRoaXMgaGFzaGVyIHdpdGggYSBtZXNzYWdlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBtZXNzYWdlVXBkYXRlIFRoZSBtZXNzYWdlIHRvIGFwcGVuZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0hhc2hlcn0gVGhpcyBoYXNoZXIuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGhhc2hlci51cGRhdGUoJ21lc3NhZ2UnKTtcblx0ICAgICAgICAgKiAgICAgaGFzaGVyLnVwZGF0ZSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHVwZGF0ZTogZnVuY3Rpb24gKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgLy8gQXBwZW5kXG5cdCAgICAgICAgICAgIHRoaXMuX2FwcGVuZChtZXNzYWdlVXBkYXRlKTtcblxuXHQgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGhhc2hcblx0ICAgICAgICAgICAgdGhpcy5fcHJvY2VzcygpO1xuXG5cdCAgICAgICAgICAgIC8vIENoYWluYWJsZVxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogRmluYWxpemVzIHRoZSBoYXNoIGNvbXB1dGF0aW9uLlxuXHQgICAgICAgICAqIE5vdGUgdGhhdCB0aGUgZmluYWxpemUgb3BlcmF0aW9uIGlzIGVmZmVjdGl2ZWx5IGEgZGVzdHJ1Y3RpdmUsIHJlYWQtb25jZSBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2VVcGRhdGUgKE9wdGlvbmFsKSBBIGZpbmFsIG1lc3NhZ2UgdXBkYXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgaGFzaC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUoKTtcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUoJ21lc3NhZ2UnKTtcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBmaW5hbGl6ZTogZnVuY3Rpb24gKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgLy8gRmluYWwgbWVzc2FnZSB1cGRhdGVcblx0ICAgICAgICAgICAgaWYgKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuX2FwcGVuZChtZXNzYWdlVXBkYXRlKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIFBlcmZvcm0gY29uY3JldGUtaGFzaGVyIGxvZ2ljXG5cdCAgICAgICAgICAgIHZhciBoYXNoID0gdGhpcy5fZG9GaW5hbGl6ZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBoYXNoO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBibG9ja1NpemU6IDUxMi8zMixcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgYSBzaG9ydGN1dCBmdW5jdGlvbiB0byBhIGhhc2hlcidzIG9iamVjdCBpbnRlcmZhY2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0hhc2hlcn0gaGFzaGVyIFRoZSBoYXNoZXIgdG8gY3JlYXRlIGEgaGVscGVyIGZvci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgc2hvcnRjdXQgZnVuY3Rpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBTSEEyNTYgPSBDcnlwdG9KUy5saWIuSGFzaGVyLl9jcmVhdGVIZWxwZXIoQ3J5cHRvSlMuYWxnby5TSEEyNTYpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9jcmVhdGVIZWxwZXI6IGZ1bmN0aW9uIChoYXNoZXIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtZXNzYWdlLCBjZmcpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBuZXcgaGFzaGVyLmluaXQoY2ZnKS5maW5hbGl6ZShtZXNzYWdlKTtcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIHNob3J0Y3V0IGZ1bmN0aW9uIHRvIHRoZSBITUFDJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7SGFzaGVyfSBoYXNoZXIgVGhlIGhhc2hlciB0byB1c2UgaW4gdGhpcyBITUFDIGhlbHBlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgc2hvcnRjdXQgZnVuY3Rpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBIbWFjU0hBMjU2ID0gQ3J5cHRvSlMubGliLkhhc2hlci5fY3JlYXRlSG1hY0hlbHBlcihDcnlwdG9KUy5hbGdvLlNIQTI1Nik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgX2NyZWF0ZUhtYWNIZWxwZXI6IGZ1bmN0aW9uIChoYXNoZXIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtZXNzYWdlLCBrZXkpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ19hbGdvLkhNQUMuaW5pdChoYXNoZXIsIGtleSkuZmluYWxpemUobWVzc2FnZSk7XG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWxnb3JpdGhtIG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfYWxnbyA9IEMuYWxnbyA9IHt9O1xuXG5cdCAgICByZXR1cm4gQztcblx0fShNYXRoKSk7XG5cblxuXHRyZXR1cm4gQ3J5cHRvSlM7XG5cbn0pKTsiLCAiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuXHRpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBDb21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZShcIi4vY29yZVwiKSk7XG5cdH1cblx0ZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoW1wiLi9jb3JlXCJdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0ZmFjdG9yeShyb290LkNyeXB0b0pTKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoQ3J5cHRvSlMpIHtcblxuXHQoZnVuY3Rpb24gKE1hdGgpIHtcblx0ICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgdmFyIEMgPSBDcnlwdG9KUztcblx0ICAgIHZhciBDX2xpYiA9IEMubGliO1xuXHQgICAgdmFyIFdvcmRBcnJheSA9IENfbGliLldvcmRBcnJheTtcblx0ICAgIHZhciBIYXNoZXIgPSBDX2xpYi5IYXNoZXI7XG5cdCAgICB2YXIgQ19hbGdvID0gQy5hbGdvO1xuXG5cdCAgICAvLyBJbml0aWFsaXphdGlvbiBhbmQgcm91bmQgY29uc3RhbnRzIHRhYmxlc1xuXHQgICAgdmFyIEggPSBbXTtcblx0ICAgIHZhciBLID0gW107XG5cblx0ICAgIC8vIENvbXB1dGUgY29uc3RhbnRzXG5cdCAgICAoZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIGZ1bmN0aW9uIGlzUHJpbWUobikge1xuXHQgICAgICAgICAgICB2YXIgc3FydE4gPSBNYXRoLnNxcnQobik7XG5cdCAgICAgICAgICAgIGZvciAodmFyIGZhY3RvciA9IDI7IGZhY3RvciA8PSBzcXJ0TjsgZmFjdG9yKyspIHtcblx0ICAgICAgICAgICAgICAgIGlmICghKG4gJSBmYWN0b3IpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIHRydWU7XG5cdCAgICAgICAgfVxuXG5cdCAgICAgICAgZnVuY3Rpb24gZ2V0RnJhY3Rpb25hbEJpdHMobikge1xuXHQgICAgICAgICAgICByZXR1cm4gKChuIC0gKG4gfCAwKSkgKiAweDEwMDAwMDAwMCkgfCAwO1xuXHQgICAgICAgIH1cblxuXHQgICAgICAgIHZhciBuID0gMjtcblx0ICAgICAgICB2YXIgblByaW1lID0gMDtcblx0ICAgICAgICB3aGlsZSAoblByaW1lIDwgNjQpIHtcblx0ICAgICAgICAgICAgaWYgKGlzUHJpbWUobikpIHtcblx0ICAgICAgICAgICAgICAgIGlmIChuUHJpbWUgPCA4KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgSFtuUHJpbWVdID0gZ2V0RnJhY3Rpb25hbEJpdHMoTWF0aC5wb3cobiwgMSAvIDIpKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIEtbblByaW1lXSA9IGdldEZyYWN0aW9uYWxCaXRzKE1hdGgucG93KG4sIDEgLyAzKSk7XG5cblx0ICAgICAgICAgICAgICAgIG5QcmltZSsrO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgbisrO1xuXHQgICAgICAgIH1cblx0ICAgIH0oKSk7XG5cblx0ICAgIC8vIFJldXNhYmxlIG9iamVjdFxuXHQgICAgdmFyIFcgPSBbXTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTSEEtMjU2IGhhc2ggYWxnb3JpdGhtLlxuXHQgICAgICovXG5cdCAgICB2YXIgU0hBMjU2ID0gQ19hbGdvLlNIQTI1NiA9IEhhc2hlci5leHRlbmQoe1xuXHQgICAgICAgIF9kb1Jlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHRoaXMuX2hhc2ggPSBuZXcgV29yZEFycmF5LmluaXQoSC5zbGljZSgwKSk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb1Byb2Nlc3NCbG9jazogZnVuY3Rpb24gKE0sIG9mZnNldCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgSCA9IHRoaXMuX2hhc2gud29yZHM7XG5cblx0ICAgICAgICAgICAgLy8gV29ya2luZyB2YXJpYWJsZXNcblx0ICAgICAgICAgICAgdmFyIGEgPSBIWzBdO1xuXHQgICAgICAgICAgICB2YXIgYiA9IEhbMV07XG5cdCAgICAgICAgICAgIHZhciBjID0gSFsyXTtcblx0ICAgICAgICAgICAgdmFyIGQgPSBIWzNdO1xuXHQgICAgICAgICAgICB2YXIgZSA9IEhbNF07XG5cdCAgICAgICAgICAgIHZhciBmID0gSFs1XTtcblx0ICAgICAgICAgICAgdmFyIGcgPSBIWzZdO1xuXHQgICAgICAgICAgICB2YXIgaCA9IEhbN107XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0YXRpb25cblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA2NDsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICBpZiAoaSA8IDE2KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgV1tpXSA9IE1bb2Zmc2V0ICsgaV0gfCAwO1xuXHQgICAgICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgICAgICB2YXIgZ2FtbWEweCA9IFdbaSAtIDE1XTtcblx0ICAgICAgICAgICAgICAgICAgICB2YXIgZ2FtbWEwICA9ICgoZ2FtbWEweCA8PCAyNSkgfCAoZ2FtbWEweCA+Pj4gNykpICBeXG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKGdhbW1hMHggPDwgMTQpIHwgKGdhbW1hMHggPj4+IDE4KSkgXlxuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChnYW1tYTB4ID4+PiAzKTtcblxuXHQgICAgICAgICAgICAgICAgICAgIHZhciBnYW1tYTF4ID0gV1tpIC0gMl07XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIGdhbW1hMSAgPSAoKGdhbW1hMXggPDwgMTUpIHwgKGdhbW1hMXggPj4+IDE3KSkgXlxuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKChnYW1tYTF4IDw8IDEzKSB8IChnYW1tYTF4ID4+PiAxOSkpIF5cblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZ2FtbWExeCA+Pj4gMTApO1xuXG5cdCAgICAgICAgICAgICAgICAgICAgV1tpXSA9IGdhbW1hMCArIFdbaSAtIDddICsgZ2FtbWExICsgV1tpIC0gMTZdO1xuXHQgICAgICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgICAgICB2YXIgY2ggID0gKGUgJiBmKSBeICh+ZSAmIGcpO1xuXHQgICAgICAgICAgICAgICAgdmFyIG1haiA9IChhICYgYikgXiAoYSAmIGMpIF4gKGIgJiBjKTtcblxuXHQgICAgICAgICAgICAgICAgdmFyIHNpZ21hMCA9ICgoYSA8PCAzMCkgfCAoYSA+Pj4gMikpIF4gKChhIDw8IDE5KSB8IChhID4+PiAxMykpIF4gKChhIDw8IDEwKSB8IChhID4+PiAyMikpO1xuXHQgICAgICAgICAgICAgICAgdmFyIHNpZ21hMSA9ICgoZSA8PCAyNikgfCAoZSA+Pj4gNikpIF4gKChlIDw8IDIxKSB8IChlID4+PiAxMSkpIF4gKChlIDw8IDcpICB8IChlID4+PiAyNSkpO1xuXG5cdCAgICAgICAgICAgICAgICB2YXIgdDEgPSBoICsgc2lnbWExICsgY2ggKyBLW2ldICsgV1tpXTtcblx0ICAgICAgICAgICAgICAgIHZhciB0MiA9IHNpZ21hMCArIG1hajtcblxuXHQgICAgICAgICAgICAgICAgaCA9IGc7XG5cdCAgICAgICAgICAgICAgICBnID0gZjtcblx0ICAgICAgICAgICAgICAgIGYgPSBlO1xuXHQgICAgICAgICAgICAgICAgZSA9IChkICsgdDEpIHwgMDtcblx0ICAgICAgICAgICAgICAgIGQgPSBjO1xuXHQgICAgICAgICAgICAgICAgYyA9IGI7XG5cdCAgICAgICAgICAgICAgICBiID0gYTtcblx0ICAgICAgICAgICAgICAgIGEgPSAodDEgKyB0MikgfCAwO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gSW50ZXJtZWRpYXRlIGhhc2ggdmFsdWVcblx0ICAgICAgICAgICAgSFswXSA9IChIWzBdICsgYSkgfCAwO1xuXHQgICAgICAgICAgICBIWzFdID0gKEhbMV0gKyBiKSB8IDA7XG5cdCAgICAgICAgICAgIEhbMl0gPSAoSFsyXSArIGMpIHwgMDtcblx0ICAgICAgICAgICAgSFszXSA9IChIWzNdICsgZCkgfCAwO1xuXHQgICAgICAgICAgICBIWzRdID0gKEhbNF0gKyBlKSB8IDA7XG5cdCAgICAgICAgICAgIEhbNV0gPSAoSFs1XSArIGYpIHwgMDtcblx0ICAgICAgICAgICAgSFs2XSA9IChIWzZdICsgZykgfCAwO1xuXHQgICAgICAgICAgICBIWzddID0gKEhbN10gKyBoKSB8IDA7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb0ZpbmFsaXplOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cdCAgICAgICAgICAgIHZhciBkYXRhV29yZHMgPSBkYXRhLndvcmRzO1xuXG5cdCAgICAgICAgICAgIHZhciBuQml0c1RvdGFsID0gdGhpcy5fbkRhdGFCeXRlcyAqIDg7XG5cdCAgICAgICAgICAgIHZhciBuQml0c0xlZnQgPSBkYXRhLnNpZ0J5dGVzICogODtcblxuXHQgICAgICAgICAgICAvLyBBZGQgcGFkZGluZ1xuXHQgICAgICAgICAgICBkYXRhV29yZHNbbkJpdHNMZWZ0ID4+PiA1XSB8PSAweDgwIDw8ICgyNCAtIG5CaXRzTGVmdCAlIDMyKTtcblx0ICAgICAgICAgICAgZGF0YVdvcmRzWygoKG5CaXRzTGVmdCArIDY0KSA+Pj4gOSkgPDwgNCkgKyAxNF0gPSBNYXRoLmZsb29yKG5CaXRzVG90YWwgLyAweDEwMDAwMDAwMCk7XG5cdCAgICAgICAgICAgIGRhdGFXb3Jkc1soKChuQml0c0xlZnQgKyA2NCkgPj4+IDkpIDw8IDQpICsgMTVdID0gbkJpdHNUb3RhbDtcblx0ICAgICAgICAgICAgZGF0YS5zaWdCeXRlcyA9IGRhdGFXb3Jkcy5sZW5ndGggKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIEhhc2ggZmluYWwgYmxvY2tzXG5cdCAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3MoKTtcblxuXHQgICAgICAgICAgICAvLyBSZXR1cm4gZmluYWwgY29tcHV0ZWQgaGFzaFxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5faGFzaDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgdmFyIGNsb25lID0gSGFzaGVyLmNsb25lLmNhbGwodGhpcyk7XG5cdCAgICAgICAgICAgIGNsb25lLl9oYXNoID0gdGhpcy5faGFzaC5jbG9uZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbiB0byB0aGUgaGFzaGVyJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gaGFzaC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBoYXNoLlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIgaGFzaCA9IENyeXB0b0pTLlNIQTI1NignbWVzc2FnZScpO1xuXHQgICAgICogICAgIHZhciBoYXNoID0gQ3J5cHRvSlMuU0hBMjU2KHdvcmRBcnJheSk7XG5cdCAgICAgKi9cblx0ICAgIEMuU0hBMjU2ID0gSGFzaGVyLl9jcmVhdGVIZWxwZXIoU0hBMjU2KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbiB0byB0aGUgSE1BQydzIG9iamVjdCBpbnRlcmZhY2UuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRvIGhhc2guXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IGtleSBUaGUgc2VjcmV0IGtleS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBITUFDLlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIgaG1hYyA9IENyeXB0b0pTLkhtYWNTSEEyNTYobWVzc2FnZSwga2V5KTtcblx0ICAgICAqL1xuXHQgICAgQy5IbWFjU0hBMjU2ID0gSGFzaGVyLl9jcmVhdGVIbWFjSGVscGVyKFNIQTI1Nik7XG5cdH0oTWF0aCkpO1xuXG5cblx0cmV0dXJuIENyeXB0b0pTLlNIQTI1NjtcblxufSkpOyIsICJpbXBvcnQgeyBQbHVnaW4sIFdvcmtzcGFjZUxlYWYgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IEFwcFZpZXcsIEFQUF9WSUVXX05BTUUgfSBmcm9tIFwiLi91aS9lbnRyeVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNlIGV4dGVuZHMgUGx1Z2luIHtcblx0YXN5bmMgb25sb2FkKCkge1xuXHRcdHRoaXMucmVnaXN0ZXJWaWV3KEFQUF9WSUVXX05BTUUsIChsZWFmKSA9PiBuZXcgQXBwVmlldyhsZWFmKSk7XG5cdFx0dGhpcy5hZGRSaWJib25JY29uKFwia2FuYmFuLXNxdWFyZVwiLCBcIk9wZW4gS2FuYmFuXCIsICgpID0+XG5cdFx0XHR0aGlzLmFjdGl2YXRlVmlldygpXG5cdFx0KTtcblx0fVxuXG5cdG9udW5sb2FkKCkge31cblxuXHRhc3luYyBhY3RpdmF0ZVZpZXcoKSB7XG5cdFx0Y29uc3QgeyB3b3Jrc3BhY2UgfSA9IHRoaXMuYXBwO1xuXG5cdFx0bGV0IGxlYWY6IFdvcmtzcGFjZUxlYWYgfCB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgbGVhdmVzID0gd29ya3NwYWNlLmdldExlYXZlc09mVHlwZShBUFBfVklFV19OQU1FKTtcblxuXHRcdGlmIChsZWF2ZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0Ly8gQSBsZWFmIHdpdGggb3VyIHZpZXcgYWxyZWFkeSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0XHRsZWFmID0gbGVhdmVzWzBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBPdXIgdmlldyBjb3VsZCBub3QgYmUgZm91bmQgaW4gdGhlIHdvcmtzcGFjZSwgY3JlYXRlIGEgbmV3IGxlYWZcblx0XHRcdC8vIGluIHRoZSByaWdodCBzaWRlYmFyIGZvciBpdFxuXHRcdFx0bGVhZiA9IHdvcmtzcGFjZS5nZXRMZWFmKFwidGFiXCIpO1xuXHRcdFx0YXdhaXQgbGVhZi5zZXRWaWV3U3RhdGUoeyB0eXBlOiBBUFBfVklFV19OQU1FLCBhY3RpdmU6IHRydWUgfSk7XG5cdFx0fVxuXG5cdFx0Ly8gXCJSZXZlYWxcIiB0aGUgbGVhZiBpbiBjYXNlIGl0IGlzIGluIGEgY29sbGFwc2VkIHNpZGViYXJcblx0XHRsZWFmICYmIHdvcmtzcGFjZS5yZXZlYWxMZWFmKGxlYWYpO1xuXHR9XG59XG4iLCAiaW1wb3J0IHsgSXRlbVZpZXcgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IE1haW4gZnJvbSBcIi4vbWFpbi5zdmVsdGVcIjtcblxuZXhwb3J0IGNvbnN0IEFQUF9WSUVXX05BTUUgPSBcInByb2plY3QtcGxhblwiO1xuXG5leHBvcnQgY2xhc3MgQXBwVmlldyBleHRlbmRzIEl0ZW1WaWV3IHtcblx0Y29tcG9uZW50OiBNYWluIHwgdW5kZWZpbmVkO1xuXHRpY29uID0gXCJrYW5iYW4tc3F1YXJlXCI7XG5cblx0Z2V0Vmlld1R5cGUoKSB7XG5cdFx0dGhpcy5sZWFmLm9wZW5GaWxlO1xuXHRcdHJldHVybiBBUFBfVklFV19OQU1FO1xuXHR9XG5cblx0Z2V0RGlzcGxheVRleHQoKSB7XG5cdFx0cmV0dXJuIFwiUHJvamVjdCBQbGFubmVyXCI7XG5cdH1cblxuXHRhc3luYyBvbk9wZW4oKSB7XG5cdFx0dGhpcy5jb21wb25lbnQgPSBuZXcgTWFpbih7XG5cdFx0XHR0YXJnZXQ6IHRoaXMuY29udGVudEVsLFxuXHRcdFx0cHJvcHM6IHtcblx0XHRcdFx0d29ya3NwYWNlOiB0aGlzLmFwcC53b3Jrc3BhY2UsXG5cdFx0XHRcdHZhdWx0OiB0aGlzLmFwcC52YXVsdCxcblx0XHRcdFx0cmVnaXN0ZXJFdmVudDogdGhpcy5yZWdpc3RlckV2ZW50LmJpbmQodGhpcyksXG5cdFx0XHR9LFxuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgb25DbG9zZSgpIHtcblx0XHR0aGlzLmNvbXBvbmVudD8uJGRlc3Ryb3koKTtcblx0fVxufVxuIiwgIi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBub29wKCkge31cblxuZXhwb3J0IGNvbnN0IGlkZW50aXR5ID0gKHgpID0+IHg7XG5cbi8qKlxuICogQHRlbXBsYXRlIFRcbiAqIEB0ZW1wbGF0ZSBTXG4gKiBAcGFyYW0ge1R9IHRhclxuICogQHBhcmFtIHtTfSBzcmNcbiAqIEByZXR1cm5zIHtUICYgU31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2lnbih0YXIsIHNyYykge1xuXHQvLyBAdHMtaWdub3JlXG5cdGZvciAoY29uc3QgayBpbiBzcmMpIHRhcltrXSA9IHNyY1trXTtcblx0cmV0dXJuIC8qKiBAdHlwZSB7VCAmIFN9ICovICh0YXIpO1xufVxuXG4vLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL3RoZW4vaXMtcHJvbWlzZS9ibG9iL21hc3Rlci9pbmRleC5qc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgTUlUIExpY2Vuc2UgaHR0cHM6Ly9naXRodWIuY29tL3RoZW4vaXMtcHJvbWlzZS9ibG9iL21hc3Rlci9MSUNFTlNFXG4vKipcbiAqIEBwYXJhbSB7YW55fSB2YWx1ZVxuICogQHJldHVybnMge3ZhbHVlIGlzIFByb21pc2VMaWtlPGFueT59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc19wcm9taXNlKHZhbHVlKSB7XG5cdHJldHVybiAoXG5cdFx0ISF2YWx1ZSAmJlxuXHRcdCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykgJiZcblx0XHR0eXBlb2YgKC8qKiBAdHlwZSB7YW55fSAqLyAodmFsdWUpLnRoZW4pID09PSAnZnVuY3Rpb24nXG5cdCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfbG9jYXRpb24oZWxlbWVudCwgZmlsZSwgbGluZSwgY29sdW1uLCBjaGFyKSB7XG5cdGVsZW1lbnQuX19zdmVsdGVfbWV0YSA9IHtcblx0XHRsb2M6IHsgZmlsZSwgbGluZSwgY29sdW1uLCBjaGFyIH1cblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1bihmbikge1xuXHRyZXR1cm4gZm4oKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJsYW5rX29iamVjdCgpIHtcblx0cmV0dXJuIE9iamVjdC5jcmVhdGUobnVsbCk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtGdW5jdGlvbltdfSBmbnNcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuX2FsbChmbnMpIHtcblx0Zm5zLmZvckVhY2gocnVuKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge2FueX0gdGhpbmdcbiAqIEByZXR1cm5zIHt0aGluZyBpcyBGdW5jdGlvbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHRoaW5nKSB7XG5cdHJldHVybiB0eXBlb2YgdGhpbmcgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKiBAcmV0dXJucyB7Ym9vbGVhbn0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYWZlX25vdF9lcXVhbChhLCBiKSB7XG5cdHJldHVybiBhICE9IGEgPyBiID09IGIgOiBhICE9PSBiIHx8IChhICYmIHR5cGVvZiBhID09PSAnb2JqZWN0JykgfHwgdHlwZW9mIGEgPT09ICdmdW5jdGlvbic7XG59XG5cbmxldCBzcmNfdXJsX2VxdWFsX2FuY2hvcjtcblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gZWxlbWVudF9zcmNcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmxcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3JjX3VybF9lcXVhbChlbGVtZW50X3NyYywgdXJsKSB7XG5cdGlmIChlbGVtZW50X3NyYyA9PT0gdXJsKSByZXR1cm4gdHJ1ZTtcblx0aWYgKCFzcmNfdXJsX2VxdWFsX2FuY2hvcikge1xuXHRcdHNyY191cmxfZXF1YWxfYW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXHR9XG5cdC8vIFRoaXMgaXMgYWN0dWFsbHkgZmFzdGVyIHRoYW4gZG9pbmcgVVJMKC4uKS5ocmVmXG5cdHNyY191cmxfZXF1YWxfYW5jaG9yLmhyZWYgPSB1cmw7XG5cdHJldHVybiBlbGVtZW50X3NyYyA9PT0gc3JjX3VybF9lcXVhbF9hbmNob3IuaHJlZjtcbn1cblxuLyoqIEBwYXJhbSB7c3RyaW5nfSBzcmNzZXQgKi9cbmZ1bmN0aW9uIHNwbGl0X3NyY3NldChzcmNzZXQpIHtcblx0cmV0dXJuIHNyY3NldC5zcGxpdCgnLCcpLm1hcCgoc3JjKSA9PiBzcmMudHJpbSgpLnNwbGl0KCcgJykuZmlsdGVyKEJvb2xlYW4pKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxTb3VyY2VFbGVtZW50IHwgSFRNTEltYWdlRWxlbWVudH0gZWxlbWVudF9zcmNzZXRcbiAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbH0gc3Jjc2V0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNyY3NldF91cmxfZXF1YWwoZWxlbWVudF9zcmNzZXQsIHNyY3NldCkge1xuXHRjb25zdCBlbGVtZW50X3VybHMgPSBzcGxpdF9zcmNzZXQoZWxlbWVudF9zcmNzZXQuc3Jjc2V0KTtcblx0Y29uc3QgdXJscyA9IHNwbGl0X3NyY3NldChzcmNzZXQgfHwgJycpO1xuXG5cdHJldHVybiAoXG5cdFx0dXJscy5sZW5ndGggPT09IGVsZW1lbnRfdXJscy5sZW5ndGggJiZcblx0XHR1cmxzLmV2ZXJ5KFxuXHRcdFx0KFt1cmwsIHdpZHRoXSwgaSkgPT5cblx0XHRcdFx0d2lkdGggPT09IGVsZW1lbnRfdXJsc1tpXVsxXSAmJlxuXHRcdFx0XHQvLyBXZSBuZWVkIHRvIHRlc3QgYm90aCB3YXlzIGJlY2F1c2UgVml0ZSB3aWxsIGNyZWF0ZSBhbiBhIGZ1bGwgVVJMIHdpdGhcblx0XHRcdFx0Ly8gYG5ldyBVUkwoYXNzZXQsIGltcG9ydC5tZXRhLnVybCkuaHJlZmAgZm9yIHRoZSBjbGllbnQgd2hlbiBgYmFzZTogJy4vJ2AsIGFuZCB0aGVcblx0XHRcdFx0Ly8gcmVsYXRpdmUgVVJMcyBpbnNpZGUgc3Jjc2V0IGFyZSBub3QgYXV0b21hdGljYWxseSByZXNvbHZlZCB0byBhYnNvbHV0ZSBVUkxzIGJ5XG5cdFx0XHRcdC8vIGJyb3dzZXJzIChpbiBjb250cmFzdCB0byBpbWcuc3JjKS4gVGhpcyBtZWFucyBib3RoIFNTUiBhbmQgRE9NIGNvZGUgY291bGRcblx0XHRcdFx0Ly8gY29udGFpbiByZWxhdGl2ZSBvciBhYnNvbHV0ZSBVUkxzLlxuXHRcdFx0XHQoc3JjX3VybF9lcXVhbChlbGVtZW50X3VybHNbaV1bMF0sIHVybCkgfHwgc3JjX3VybF9lcXVhbCh1cmwsIGVsZW1lbnRfdXJsc1tpXVswXSkpXG5cdFx0KVxuXHQpO1xufVxuXG4vKiogQHJldHVybnMge2Jvb2xlYW59ICovXG5leHBvcnQgZnVuY3Rpb24gbm90X2VxdWFsKGEsIGIpIHtcblx0cmV0dXJuIGEgIT0gYSA/IGIgPT0gYiA6IGEgIT09IGI7XG59XG5cbi8qKiBAcmV0dXJucyB7Ym9vbGVhbn0gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc19lbXB0eShvYmopIHtcblx0cmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoID09PSAwO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVfc3RvcmUoc3RvcmUsIG5hbWUpIHtcblx0aWYgKHN0b3JlICE9IG51bGwgJiYgdHlwZW9mIHN0b3JlLnN1YnNjcmliZSAhPT0gJ2Z1bmN0aW9uJykge1xuXHRcdHRocm93IG5ldyBFcnJvcihgJyR7bmFtZX0nIGlzIG5vdCBhIHN0b3JlIHdpdGggYSAnc3Vic2NyaWJlJyBtZXRob2RgKTtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3Vic2NyaWJlKHN0b3JlLCAuLi5jYWxsYmFja3MpIHtcblx0aWYgKHN0b3JlID09IG51bGwpIHtcblx0XHRmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIGNhbGxiYWNrcykge1xuXHRcdFx0Y2FsbGJhY2sodW5kZWZpbmVkKTtcblx0XHR9XG5cdFx0cmV0dXJuIG5vb3A7XG5cdH1cblx0Y29uc3QgdW5zdWIgPSBzdG9yZS5zdWJzY3JpYmUoLi4uY2FsbGJhY2tzKTtcblx0cmV0dXJuIHVuc3ViLnVuc3Vic2NyaWJlID8gKCkgPT4gdW5zdWIudW5zdWJzY3JpYmUoKSA6IHVuc3ViO1xufVxuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudCB2YWx1ZSBmcm9tIGEgc3RvcmUgYnkgc3Vic2NyaWJpbmcgYW5kIGltbWVkaWF0ZWx5IHVuc3Vic2NyaWJpbmcuXG4gKlxuICogaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3Mvc3ZlbHRlLXN0b3JlI2dldFxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuLi9zdG9yZS9wdWJsaWMuanMnKS5SZWFkYWJsZTxUPn0gc3RvcmVcbiAqIEByZXR1cm5zIHtUfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X3N0b3JlX3ZhbHVlKHN0b3JlKSB7XG5cdGxldCB2YWx1ZTtcblx0c3Vic2NyaWJlKHN0b3JlLCAoXykgPT4gKHZhbHVlID0gXykpKCk7XG5cdHJldHVybiB2YWx1ZTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvbmVudF9zdWJzY3JpYmUoY29tcG9uZW50LCBzdG9yZSwgY2FsbGJhY2spIHtcblx0Y29tcG9uZW50LiQkLm9uX2Rlc3Ryb3kucHVzaChzdWJzY3JpYmUoc3RvcmUsIGNhbGxiYWNrKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfc2xvdChkZWZpbml0aW9uLCBjdHgsICQkc2NvcGUsIGZuKSB7XG5cdGlmIChkZWZpbml0aW9uKSB7XG5cdFx0Y29uc3Qgc2xvdF9jdHggPSBnZXRfc2xvdF9jb250ZXh0KGRlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZm4pO1xuXHRcdHJldHVybiBkZWZpbml0aW9uWzBdKHNsb3RfY3R4KTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRfc2xvdF9jb250ZXh0KGRlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZm4pIHtcblx0cmV0dXJuIGRlZmluaXRpb25bMV0gJiYgZm4gPyBhc3NpZ24oJCRzY29wZS5jdHguc2xpY2UoKSwgZGVmaW5pdGlvblsxXShmbihjdHgpKSkgOiAkJHNjb3BlLmN0eDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldF9zbG90X2NoYW5nZXMoZGVmaW5pdGlvbiwgJCRzY29wZSwgZGlydHksIGZuKSB7XG5cdGlmIChkZWZpbml0aW9uWzJdICYmIGZuKSB7XG5cdFx0Y29uc3QgbGV0cyA9IGRlZmluaXRpb25bMl0oZm4oZGlydHkpKTtcblx0XHRpZiAoJCRzY29wZS5kaXJ0eSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gbGV0cztcblx0XHR9XG5cdFx0aWYgKHR5cGVvZiBsZXRzID09PSAnb2JqZWN0Jykge1xuXHRcdFx0Y29uc3QgbWVyZ2VkID0gW107XG5cdFx0XHRjb25zdCBsZW4gPSBNYXRoLm1heCgkJHNjb3BlLmRpcnR5Lmxlbmd0aCwgbGV0cy5sZW5ndGgpO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gMSkge1xuXHRcdFx0XHRtZXJnZWRbaV0gPSAkJHNjb3BlLmRpcnR5W2ldIHwgbGV0c1tpXTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtZXJnZWQ7XG5cdFx0fVxuXHRcdHJldHVybiAkJHNjb3BlLmRpcnR5IHwgbGV0cztcblx0fVxuXHRyZXR1cm4gJCRzY29wZS5kaXJ0eTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZV9zbG90X2Jhc2UoXG5cdHNsb3QsXG5cdHNsb3RfZGVmaW5pdGlvbixcblx0Y3R4LFxuXHQkJHNjb3BlLFxuXHRzbG90X2NoYW5nZXMsXG5cdGdldF9zbG90X2NvbnRleHRfZm5cbikge1xuXHRpZiAoc2xvdF9jaGFuZ2VzKSB7XG5cdFx0Y29uc3Qgc2xvdF9jb250ZXh0ID0gZ2V0X3Nsb3RfY29udGV4dChzbG90X2RlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZ2V0X3Nsb3RfY29udGV4dF9mbik7XG5cdFx0c2xvdC5wKHNsb3RfY29udGV4dCwgc2xvdF9jaGFuZ2VzKTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlX3Nsb3QoXG5cdHNsb3QsXG5cdHNsb3RfZGVmaW5pdGlvbixcblx0Y3R4LFxuXHQkJHNjb3BlLFxuXHRkaXJ0eSxcblx0Z2V0X3Nsb3RfY2hhbmdlc19mbixcblx0Z2V0X3Nsb3RfY29udGV4dF9mblxuKSB7XG5cdGNvbnN0IHNsb3RfY2hhbmdlcyA9IGdldF9zbG90X2NoYW5nZXMoc2xvdF9kZWZpbml0aW9uLCAkJHNjb3BlLCBkaXJ0eSwgZ2V0X3Nsb3RfY2hhbmdlc19mbik7XG5cdHVwZGF0ZV9zbG90X2Jhc2Uoc2xvdCwgc2xvdF9kZWZpbml0aW9uLCBjdHgsICQkc2NvcGUsIHNsb3RfY2hhbmdlcywgZ2V0X3Nsb3RfY29udGV4dF9mbik7XG59XG5cbi8qKiBAcmV0dXJucyB7YW55W10gfCAtMX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRfYWxsX2RpcnR5X2Zyb21fc2NvcGUoJCRzY29wZSkge1xuXHRpZiAoJCRzY29wZS5jdHgubGVuZ3RoID4gMzIpIHtcblx0XHRjb25zdCBkaXJ0eSA9IFtdO1xuXHRcdGNvbnN0IGxlbmd0aCA9ICQkc2NvcGUuY3R4Lmxlbmd0aCAvIDMyO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcblx0XHRcdGRpcnR5W2ldID0gLTE7XG5cdFx0fVxuXHRcdHJldHVybiBkaXJ0eTtcblx0fVxuXHRyZXR1cm4gLTE7XG59XG5cbi8qKiBAcmV0dXJucyB7e319ICovXG5leHBvcnQgZnVuY3Rpb24gZXhjbHVkZV9pbnRlcm5hbF9wcm9wcyhwcm9wcykge1xuXHRjb25zdCByZXN1bHQgPSB7fTtcblx0Zm9yIChjb25zdCBrIGluIHByb3BzKSBpZiAoa1swXSAhPT0gJyQnKSByZXN1bHRba10gPSBwcm9wc1trXTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqIEByZXR1cm5zIHt7fX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlX3Jlc3RfcHJvcHMocHJvcHMsIGtleXMpIHtcblx0Y29uc3QgcmVzdCA9IHt9O1xuXHRrZXlzID0gbmV3IFNldChrZXlzKTtcblx0Zm9yIChjb25zdCBrIGluIHByb3BzKSBpZiAoIWtleXMuaGFzKGspICYmIGtbMF0gIT09ICckJykgcmVzdFtrXSA9IHByb3BzW2tdO1xuXHRyZXR1cm4gcmVzdDtcbn1cblxuLyoqIEByZXR1cm5zIHt7fX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlX3Nsb3RzKHNsb3RzKSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRmb3IgKGNvbnN0IGtleSBpbiBzbG90cykge1xuXHRcdHJlc3VsdFtrZXldID0gdHJ1ZTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogQHJldHVybnMgeyh0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uY2UoZm4pIHtcblx0bGV0IHJhbiA9IGZhbHNlO1xuXHRyZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0XHRpZiAocmFuKSByZXR1cm47XG5cdFx0cmFuID0gdHJ1ZTtcblx0XHRmbi5jYWxsKHRoaXMsIC4uLmFyZ3MpO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVsbF90b19lbXB0eSh2YWx1ZSkge1xuXHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/ICcnIDogdmFsdWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRfc3RvcmVfdmFsdWUoc3RvcmUsIHJldCwgdmFsdWUpIHtcblx0c3RvcmUuc2V0KHZhbHVlKTtcblx0cmV0dXJuIHJldDtcbn1cblxuZXhwb3J0IGNvbnN0IGhhc19wcm9wID0gKG9iaiwgcHJvcCkgPT4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBhY3Rpb25fZGVzdHJveWVyKGFjdGlvbl9yZXN1bHQpIHtcblx0cmV0dXJuIGFjdGlvbl9yZXN1bHQgJiYgaXNfZnVuY3Rpb24oYWN0aW9uX3Jlc3VsdC5kZXN0cm95KSA/IGFjdGlvbl9yZXN1bHQuZGVzdHJveSA6IG5vb3A7XG59XG5cbi8qKiBAcGFyYW0ge251bWJlciB8IHN0cmluZ30gdmFsdWVcbiAqIEByZXR1cm5zIHtbbnVtYmVyLCBzdHJpbmddfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRfY3NzX3VuaXQodmFsdWUpIHtcblx0Y29uc3Qgc3BsaXQgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLm1hdGNoKC9eXFxzKigtP1tcXGQuXSspKFteXFxzXSopXFxzKiQvKTtcblx0cmV0dXJuIHNwbGl0ID8gW3BhcnNlRmxvYXQoc3BsaXRbMV0pLCBzcGxpdFsyXSB8fCAncHgnXSA6IFsvKiogQHR5cGUge251bWJlcn0gKi8gKHZhbHVlKSwgJ3B4J107XG59XG5cbmV4cG9ydCBjb25zdCBjb250ZW50ZWRpdGFibGVfdHJ1dGh5X3ZhbHVlcyA9IFsnJywgdHJ1ZSwgMSwgJ3RydWUnLCAnY29udGVudGVkaXRhYmxlJ107XG4iLCAiLyoqIEB0eXBlIHt0eXBlb2YgZ2xvYmFsVGhpc30gKi9cbmV4cG9ydCBjb25zdCBnbG9iYWxzID1cblx0dHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcblx0XHQ/IHdpbmRvd1xuXHRcdDogdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnXG5cdFx0PyBnbG9iYWxUaGlzXG5cdFx0OiAvLyBAdHMtaWdub3JlIE5vZGUgdHlwaW5ncyBoYXZlIHRoaXNcblx0XHQgIGdsb2JhbDtcbiIsICJpbXBvcnQgeyBnbG9iYWxzIH0gZnJvbSAnLi9nbG9iYWxzLmpzJztcblxuLyoqXG4gKiBSZXNpemUgb2JzZXJ2ZXIgc2luZ2xldG9uLlxuICogT25lIGxpc3RlbmVyIHBlciBlbGVtZW50IG9ubHkhXG4gKiBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2EvY2hyb21pdW0ub3JnL2cvYmxpbmstZGV2L2MvejZpZW5PTlViNUEvbS9GNS1WY1VadEJBQUpcbiAqL1xuZXhwb3J0IGNsYXNzIFJlc2l6ZU9ic2VydmVyU2luZ2xldG9uIHtcblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEByZWFkb25seVxuXHQgKiBAdHlwZSB7V2Vha01hcDxFbGVtZW50LCBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkxpc3RlbmVyPn1cblx0ICovXG5cdF9saXN0ZW5lcnMgPSAnV2Vha01hcCcgaW4gZ2xvYmFscyA/IG5ldyBXZWFrTWFwKCkgOiB1bmRlZmluZWQ7XG5cblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEB0eXBlIHtSZXNpemVPYnNlcnZlcn1cblx0ICovXG5cdF9vYnNlcnZlciA9IHVuZGVmaW5lZDtcblxuXHQvKiogQHR5cGUge1Jlc2l6ZU9ic2VydmVyT3B0aW9uc30gKi9cblx0b3B0aW9ucztcblxuXHQvKiogQHBhcmFtIHtSZXNpemVPYnNlcnZlck9wdGlvbnN9IG9wdGlvbnMgKi9cblx0Y29uc3RydWN0b3Iob3B0aW9ucykge1xuXHRcdHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG5cdCAqIEBwYXJhbSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5MaXN0ZW5lcn0gbGlzdGVuZXJcblx0ICogQHJldHVybnMgeygpID0+IHZvaWR9XG5cdCAqL1xuXHRvYnNlcnZlKGVsZW1lbnQsIGxpc3RlbmVyKSB7XG5cdFx0dGhpcy5fbGlzdGVuZXJzLnNldChlbGVtZW50LCBsaXN0ZW5lcik7XG5cdFx0dGhpcy5fZ2V0T2JzZXJ2ZXIoKS5vYnNlcnZlKGVsZW1lbnQsIHRoaXMub3B0aW9ucyk7XG5cdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdHRoaXMuX2xpc3RlbmVycy5kZWxldGUoZWxlbWVudCk7XG5cdFx0XHR0aGlzLl9vYnNlcnZlci51bm9ic2VydmUoZWxlbWVudCk7IC8vIHRoaXMgbGluZSBjYW4gcHJvYmFibHkgYmUgcmVtb3ZlZFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogQHByaXZhdGVcblx0ICovXG5cdF9nZXRPYnNlcnZlcigpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0dGhpcy5fb2JzZXJ2ZXIgPz9cblx0XHRcdCh0aGlzLl9vYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoZW50cmllcykgPT4ge1xuXHRcdFx0XHRmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcblx0XHRcdFx0XHRSZXNpemVPYnNlcnZlclNpbmdsZXRvbi5lbnRyaWVzLnNldChlbnRyeS50YXJnZXQsIGVudHJ5KTtcblx0XHRcdFx0XHR0aGlzLl9saXN0ZW5lcnMuZ2V0KGVudHJ5LnRhcmdldCk/LihlbnRyeSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pKVxuXHRcdCk7XG5cdH1cbn1cblxuLy8gTmVlZHMgdG8gYmUgd3JpdHRlbiBsaWtlIHRoaXMgdG8gcGFzcyB0aGUgdHJlZS1zaGFrZS10ZXN0XG5SZXNpemVPYnNlcnZlclNpbmdsZXRvbi5lbnRyaWVzID0gJ1dlYWtNYXAnIGluIGdsb2JhbHMgPyBuZXcgV2Vha01hcCgpIDogdW5kZWZpbmVkO1xuIiwgImltcG9ydCB7IGNvbnRlbnRlZGl0YWJsZV90cnV0aHlfdmFsdWVzLCBoYXNfcHJvcCB9IGZyb20gJy4vdXRpbHMuanMnO1xuXG5pbXBvcnQgeyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbiB9IGZyb20gJy4vUmVzaXplT2JzZXJ2ZXJTaW5nbGV0b24uanMnO1xuXG4vLyBUcmFjayB3aGljaCBub2RlcyBhcmUgY2xhaW1lZCBkdXJpbmcgaHlkcmF0aW9uLiBVbmNsYWltZWQgbm9kZXMgY2FuIHRoZW4gYmUgcmVtb3ZlZCBmcm9tIHRoZSBET01cbi8vIGF0IHRoZSBlbmQgb2YgaHlkcmF0aW9uIHdpdGhvdXQgdG91Y2hpbmcgdGhlIHJlbWFpbmluZyBub2Rlcy5cbmxldCBpc19oeWRyYXRpbmcgPSBmYWxzZTtcblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0X2h5ZHJhdGluZygpIHtcblx0aXNfaHlkcmF0aW5nID0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuZF9oeWRyYXRpbmcoKSB7XG5cdGlzX2h5ZHJhdGluZyA9IGZhbHNlO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoXG4gKiBAcGFyYW0geyhpbmRleDogbnVtYmVyKSA9PiBudW1iZXJ9IGtleVxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiB1cHBlcl9ib3VuZChsb3csIGhpZ2gsIGtleSwgdmFsdWUpIHtcblx0Ly8gUmV0dXJuIGZpcnN0IGluZGV4IG9mIHZhbHVlIGxhcmdlciB0aGFuIGlucHV0IHZhbHVlIGluIHRoZSByYW5nZSBbbG93LCBoaWdoKVxuXHR3aGlsZSAobG93IDwgaGlnaCkge1xuXHRcdGNvbnN0IG1pZCA9IGxvdyArICgoaGlnaCAtIGxvdykgPj4gMSk7XG5cdFx0aWYgKGtleShtaWQpIDw9IHZhbHVlKSB7XG5cdFx0XHRsb3cgPSBtaWQgKyAxO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRoaWdoID0gbWlkO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbG93O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZUV4fSB0YXJnZXRcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBpbml0X2h5ZHJhdGUodGFyZ2V0KSB7XG5cdGlmICh0YXJnZXQuaHlkcmF0ZV9pbml0KSByZXR1cm47XG5cdHRhcmdldC5oeWRyYXRlX2luaXQgPSB0cnVlO1xuXHQvLyBXZSBrbm93IHRoYXQgYWxsIGNoaWxkcmVuIGhhdmUgY2xhaW1fb3JkZXIgdmFsdWVzIHNpbmNlIHRoZSB1bmNsYWltZWQgaGF2ZSBiZWVuIGRldGFjaGVkIGlmIHRhcmdldCBpcyBub3QgPGhlYWQ+XG5cblx0bGV0IGNoaWxkcmVuID0gLyoqIEB0eXBlIHtBcnJheUxpa2U8Tm9kZUV4Mj59ICovICh0YXJnZXQuY2hpbGROb2Rlcyk7XG5cdC8vIElmIHRhcmdldCBpcyA8aGVhZD4sIHRoZXJlIG1heSBiZSBjaGlsZHJlbiB3aXRob3V0IGNsYWltX29yZGVyXG5cdGlmICh0YXJnZXQubm9kZU5hbWUgPT09ICdIRUFEJykge1xuXHRcdGNvbnN0IG15X2NoaWxkcmVuID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3Qgbm9kZSA9IGNoaWxkcmVuW2ldO1xuXHRcdFx0aWYgKG5vZGUuY2xhaW1fb3JkZXIgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRteV9jaGlsZHJlbi5wdXNoKG5vZGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjaGlsZHJlbiA9IG15X2NoaWxkcmVuO1xuXHR9XG5cdC8qXG5cdCAqIFJlb3JkZXIgY2xhaW1lZCBjaGlsZHJlbiBvcHRpbWFsbHkuXG5cdCAqIFdlIGNhbiByZW9yZGVyIGNsYWltZWQgY2hpbGRyZW4gb3B0aW1hbGx5IGJ5IGZpbmRpbmcgdGhlIGxvbmdlc3Qgc3Vic2VxdWVuY2Ugb2Zcblx0ICogbm9kZXMgdGhhdCBhcmUgYWxyZWFkeSBjbGFpbWVkIGluIG9yZGVyIGFuZCBvbmx5IG1vdmluZyB0aGUgcmVzdC4gVGhlIGxvbmdlc3Rcblx0ICogc3Vic2VxdWVuY2Ugb2Ygbm9kZXMgdGhhdCBhcmUgY2xhaW1lZCBpbiBvcmRlciBjYW4gYmUgZm91bmQgYnlcblx0ICogY29tcHV0aW5nIHRoZSBsb25nZXN0IGluY3JlYXNpbmcgc3Vic2VxdWVuY2Ugb2YgLmNsYWltX29yZGVyIHZhbHVlcy5cblx0ICpcblx0ICogVGhpcyBhbGdvcml0aG0gaXMgb3B0aW1hbCBpbiBnZW5lcmF0aW5nIHRoZSBsZWFzdCBhbW91bnQgb2YgcmVvcmRlciBvcGVyYXRpb25zXG5cdCAqIHBvc3NpYmxlLlxuXHQgKlxuXHQgKiBQcm9vZjpcblx0ICogV2Uga25vdyB0aGF0LCBnaXZlbiBhIHNldCBvZiByZW9yZGVyaW5nIG9wZXJhdGlvbnMsIHRoZSBub2RlcyB0aGF0IGRvIG5vdCBtb3ZlXG5cdCAqIGFsd2F5cyBmb3JtIGFuIGluY3JlYXNpbmcgc3Vic2VxdWVuY2UsIHNpbmNlIHRoZXkgZG8gbm90IG1vdmUgYW1vbmcgZWFjaCBvdGhlclxuXHQgKiBtZWFuaW5nIHRoYXQgdGhleSBtdXN0IGJlIGFscmVhZHkgb3JkZXJlZCBhbW9uZyBlYWNoIG90aGVyLiBUaHVzLCB0aGUgbWF4aW1hbFxuXHQgKiBzZXQgb2Ygbm9kZXMgdGhhdCBkbyBub3QgbW92ZSBmb3JtIGEgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlLlxuXHQgKi9cblx0Ly8gQ29tcHV0ZSBsb25nZXN0IGluY3JlYXNpbmcgc3Vic2VxdWVuY2Vcblx0Ly8gbTogc3Vic2VxdWVuY2UgbGVuZ3RoIGogPT4gaW5kZXggayBvZiBzbWFsbGVzdCB2YWx1ZSB0aGF0IGVuZHMgYW4gaW5jcmVhc2luZyBzdWJzZXF1ZW5jZSBvZiBsZW5ndGggalxuXHRjb25zdCBtID0gbmV3IEludDMyQXJyYXkoY2hpbGRyZW4ubGVuZ3RoICsgMSk7XG5cdC8vIFByZWRlY2Vzc29yIGluZGljZXMgKyAxXG5cdGNvbnN0IHAgPSBuZXcgSW50MzJBcnJheShjaGlsZHJlbi5sZW5ndGgpO1xuXHRtWzBdID0gLTE7XG5cdGxldCBsb25nZXN0ID0gMDtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGN1cnJlbnQgPSBjaGlsZHJlbltpXS5jbGFpbV9vcmRlcjtcblx0XHQvLyBGaW5kIHRoZSBsYXJnZXN0IHN1YnNlcXVlbmNlIGxlbmd0aCBzdWNoIHRoYXQgaXQgZW5kcyBpbiBhIHZhbHVlIGxlc3MgdGhhbiBvdXIgY3VycmVudCB2YWx1ZVxuXHRcdC8vIHVwcGVyX2JvdW5kIHJldHVybnMgZmlyc3QgZ3JlYXRlciB2YWx1ZSwgc28gd2Ugc3VidHJhY3Qgb25lXG5cdFx0Ly8gd2l0aCBmYXN0IHBhdGggZm9yIHdoZW4gd2UgYXJlIG9uIHRoZSBjdXJyZW50IGxvbmdlc3Qgc3Vic2VxdWVuY2Vcblx0XHRjb25zdCBzZXFfbGVuID1cblx0XHRcdChsb25nZXN0ID4gMCAmJiBjaGlsZHJlblttW2xvbmdlc3RdXS5jbGFpbV9vcmRlciA8PSBjdXJyZW50XG5cdFx0XHRcdD8gbG9uZ2VzdCArIDFcblx0XHRcdFx0OiB1cHBlcl9ib3VuZCgxLCBsb25nZXN0LCAoaWR4KSA9PiBjaGlsZHJlblttW2lkeF1dLmNsYWltX29yZGVyLCBjdXJyZW50KSkgLSAxO1xuXHRcdHBbaV0gPSBtW3NlcV9sZW5dICsgMTtcblx0XHRjb25zdCBuZXdfbGVuID0gc2VxX2xlbiArIDE7XG5cdFx0Ly8gV2UgY2FuIGd1YXJhbnRlZSB0aGF0IGN1cnJlbnQgaXMgdGhlIHNtYWxsZXN0IHZhbHVlLiBPdGhlcndpc2UsIHdlIHdvdWxkIGhhdmUgZ2VuZXJhdGVkIGEgbG9uZ2VyIHNlcXVlbmNlLlxuXHRcdG1bbmV3X2xlbl0gPSBpO1xuXHRcdGxvbmdlc3QgPSBNYXRoLm1heChuZXdfbGVuLCBsb25nZXN0KTtcblx0fVxuXHQvLyBUaGUgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlIG9mIG5vZGVzIChpbml0aWFsbHkgcmV2ZXJzZWQpXG5cblx0LyoqXG5cdCAqIEB0eXBlIHtOb2RlRXgyW119XG5cdCAqL1xuXHRjb25zdCBsaXMgPSBbXTtcblx0Ly8gVGhlIHJlc3Qgb2YgdGhlIG5vZGVzLCBub2RlcyB0aGF0IHdpbGwgYmUgbW92ZWRcblxuXHQvKipcblx0ICogQHR5cGUge05vZGVFeDJbXX1cblx0ICovXG5cdGNvbnN0IHRvX21vdmUgPSBbXTtcblx0bGV0IGxhc3QgPSBjaGlsZHJlbi5sZW5ndGggLSAxO1xuXHRmb3IgKGxldCBjdXIgPSBtW2xvbmdlc3RdICsgMTsgY3VyICE9IDA7IGN1ciA9IHBbY3VyIC0gMV0pIHtcblx0XHRsaXMucHVzaChjaGlsZHJlbltjdXIgLSAxXSk7XG5cdFx0Zm9yICg7IGxhc3QgPj0gY3VyOyBsYXN0LS0pIHtcblx0XHRcdHRvX21vdmUucHVzaChjaGlsZHJlbltsYXN0XSk7XG5cdFx0fVxuXHRcdGxhc3QtLTtcblx0fVxuXHRmb3IgKDsgbGFzdCA+PSAwOyBsYXN0LS0pIHtcblx0XHR0b19tb3ZlLnB1c2goY2hpbGRyZW5bbGFzdF0pO1xuXHR9XG5cdGxpcy5yZXZlcnNlKCk7XG5cdC8vIFdlIHNvcnQgdGhlIG5vZGVzIGJlaW5nIG1vdmVkIHRvIGd1YXJhbnRlZSB0aGF0IHRoZWlyIGluc2VydGlvbiBvcmRlciBtYXRjaGVzIHRoZSBjbGFpbSBvcmRlclxuXHR0b19tb3ZlLnNvcnQoKGEsIGIpID0+IGEuY2xhaW1fb3JkZXIgLSBiLmNsYWltX29yZGVyKTtcblx0Ly8gRmluYWxseSwgd2UgbW92ZSB0aGUgbm9kZXNcblx0Zm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgdG9fbW92ZS5sZW5ndGg7IGkrKykge1xuXHRcdHdoaWxlIChqIDwgbGlzLmxlbmd0aCAmJiB0b19tb3ZlW2ldLmNsYWltX29yZGVyID49IGxpc1tqXS5jbGFpbV9vcmRlcikge1xuXHRcdFx0aisrO1xuXHRcdH1cblx0XHRjb25zdCBhbmNob3IgPSBqIDwgbGlzLmxlbmd0aCA/IGxpc1tqXSA6IG51bGw7XG5cdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSh0b19tb3ZlW2ldLCBhbmNob3IpO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlfSB0YXJnZXRcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmQodGFyZ2V0LCBub2RlKSB7XG5cdHRhcmdldC5hcHBlbmRDaGlsZChub2RlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IHRhcmdldFxuICogQHBhcmFtIHtzdHJpbmd9IHN0eWxlX3NoZWV0X2lkXG4gKiBAcGFyYW0ge3N0cmluZ30gc3R5bGVzXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZF9zdHlsZXModGFyZ2V0LCBzdHlsZV9zaGVldF9pZCwgc3R5bGVzKSB7XG5cdGNvbnN0IGFwcGVuZF9zdHlsZXNfdG8gPSBnZXRfcm9vdF9mb3Jfc3R5bGUodGFyZ2V0KTtcblx0aWYgKCFhcHBlbmRfc3R5bGVzX3RvLmdldEVsZW1lbnRCeUlkKHN0eWxlX3NoZWV0X2lkKSkge1xuXHRcdGNvbnN0IHN0eWxlID0gZWxlbWVudCgnc3R5bGUnKTtcblx0XHRzdHlsZS5pZCA9IHN0eWxlX3NoZWV0X2lkO1xuXHRcdHN0eWxlLnRleHRDb250ZW50ID0gc3R5bGVzO1xuXHRcdGFwcGVuZF9zdHlsZXNoZWV0KGFwcGVuZF9zdHlsZXNfdG8sIHN0eWxlKTtcblx0fVxufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge1NoYWRvd1Jvb3QgfCBEb2N1bWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldF9yb290X2Zvcl9zdHlsZShub2RlKSB7XG5cdGlmICghbm9kZSkgcmV0dXJuIGRvY3VtZW50O1xuXHRjb25zdCByb290ID0gbm9kZS5nZXRSb290Tm9kZSA/IG5vZGUuZ2V0Um9vdE5vZGUoKSA6IG5vZGUub3duZXJEb2N1bWVudDtcblx0aWYgKHJvb3QgJiYgLyoqIEB0eXBlIHtTaGFkb3dSb290fSAqLyAocm9vdCkuaG9zdCkge1xuXHRcdHJldHVybiAvKiogQHR5cGUge1NoYWRvd1Jvb3R9ICovIChyb290KTtcblx0fVxuXHRyZXR1cm4gbm9kZS5vd25lckRvY3VtZW50O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge0NTU1N0eWxlU2hlZXR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRfZW1wdHlfc3R5bGVzaGVldChub2RlKSB7XG5cdGNvbnN0IHN0eWxlX2VsZW1lbnQgPSBlbGVtZW50KCdzdHlsZScpO1xuXHQvLyBGb3IgdHJhbnNpdGlvbnMgdG8gd29yayB3aXRob3V0ICdzdHlsZS1zcmM6IHVuc2FmZS1pbmxpbmUnIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5LFxuXHQvLyB0aGVzZSBlbXB0eSB0YWdzIG5lZWQgdG8gYmUgYWxsb3dlZCB3aXRoIGEgaGFzaCBhcyBhIHdvcmthcm91bmQgdW50aWwgd2UgbW92ZSB0byB0aGUgV2ViIEFuaW1hdGlvbnMgQVBJLlxuXHQvLyBVc2luZyB0aGUgaGFzaCBmb3IgdGhlIGVtcHR5IHN0cmluZyAoZm9yIGFuIGVtcHR5IHRhZykgd29ya3MgaW4gYWxsIGJyb3dzZXJzIGV4Y2VwdCBTYWZhcmkuXG5cdC8vIFNvIGFzIGEgd29ya2Fyb3VuZCBmb3IgdGhlIHdvcmthcm91bmQsIHdoZW4gd2UgYXBwZW5kIGVtcHR5IHN0eWxlIHRhZ3Mgd2Ugc2V0IHRoZWlyIGNvbnRlbnQgdG8gLyogZW1wdHkgKi8uXG5cdC8vIFRoZSBoYXNoICdzaGEyNTYtOU9sTk8wRE5FZWFWekhMNFJad0NMc0JIQThXQlE4dG9CcC80RjVYVjJuYz0nIHdpbGwgdGhlbiB3b3JrIGV2ZW4gaW4gU2FmYXJpLlxuXHRzdHlsZV9lbGVtZW50LnRleHRDb250ZW50ID0gJy8qIGVtcHR5ICovJztcblx0YXBwZW5kX3N0eWxlc2hlZXQoZ2V0X3Jvb3RfZm9yX3N0eWxlKG5vZGUpLCBzdHlsZV9lbGVtZW50KTtcblx0cmV0dXJuIHN0eWxlX2VsZW1lbnQuc2hlZXQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtTaGFkb3dSb290IHwgRG9jdW1lbnR9IG5vZGVcbiAqIEBwYXJhbSB7SFRNTFN0eWxlRWxlbWVudH0gc3R5bGVcbiAqIEByZXR1cm5zIHtDU1NTdHlsZVNoZWV0fVxuICovXG5mdW5jdGlvbiBhcHBlbmRfc3R5bGVzaGVldChub2RlLCBzdHlsZSkge1xuXHRhcHBlbmQoLyoqIEB0eXBlIHtEb2N1bWVudH0gKi8gKG5vZGUpLmhlYWQgfHwgbm9kZSwgc3R5bGUpO1xuXHRyZXR1cm4gc3R5bGUuc2hlZXQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlRXh9IHRhcmdldFxuICogQHBhcmFtIHtOb2RlRXh9IG5vZGVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kX2h5ZHJhdGlvbih0YXJnZXQsIG5vZGUpIHtcblx0aWYgKGlzX2h5ZHJhdGluZykge1xuXHRcdGluaXRfaHlkcmF0ZSh0YXJnZXQpO1xuXHRcdGlmIChcblx0XHRcdHRhcmdldC5hY3R1YWxfZW5kX2NoaWxkID09PSB1bmRlZmluZWQgfHxcblx0XHRcdCh0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCAhPT0gbnVsbCAmJiB0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZC5wYXJlbnROb2RlICE9PSB0YXJnZXQpXG5cdFx0KSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IHRhcmdldC5maXJzdENoaWxkO1xuXHRcdH1cblx0XHQvLyBTa2lwIG5vZGVzIG9mIHVuZGVmaW5lZCBvcmRlcmluZ1xuXHRcdHdoaWxlICh0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCAhPT0gbnVsbCAmJiB0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZC5jbGFpbV9vcmRlciA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IHRhcmdldC5hY3R1YWxfZW5kX2NoaWxkLm5leHRTaWJsaW5nO1xuXHRcdH1cblx0XHRpZiAobm9kZSAhPT0gdGFyZ2V0LmFjdHVhbF9lbmRfY2hpbGQpIHtcblx0XHRcdC8vIFdlIG9ubHkgaW5zZXJ0IGlmIHRoZSBvcmRlcmluZyBvZiB0aGlzIG5vZGUgc2hvdWxkIGJlIG1vZGlmaWVkIG9yIHRoZSBwYXJlbnQgbm9kZSBpcyBub3QgdGFyZ2V0XG5cdFx0XHRpZiAobm9kZS5jbGFpbV9vcmRlciAhPT0gdW5kZWZpbmVkIHx8IG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0KSB7XG5cdFx0XHRcdHRhcmdldC5pbnNlcnRCZWZvcmUobm9kZSwgdGFyZ2V0LmFjdHVhbF9lbmRfY2hpbGQpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IG5vZGUubmV4dFNpYmxpbmc7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0IHx8IG5vZGUubmV4dFNpYmxpbmcgIT09IG51bGwpIHtcblx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQobm9kZSk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IHRhcmdldFxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcGFyYW0ge05vZGV9IFthbmNob3JdXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydCh0YXJnZXQsIG5vZGUsIGFuY2hvcikge1xuXHR0YXJnZXQuaW5zZXJ0QmVmb3JlKG5vZGUsIGFuY2hvciB8fCBudWxsKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGVFeH0gdGFyZ2V0XG4gKiBAcGFyYW0ge05vZGVFeH0gbm9kZVxuICogQHBhcmFtIHtOb2RlRXh9IFthbmNob3JdXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydF9oeWRyYXRpb24odGFyZ2V0LCBub2RlLCBhbmNob3IpIHtcblx0aWYgKGlzX2h5ZHJhdGluZyAmJiAhYW5jaG9yKSB7XG5cdFx0YXBwZW5kX2h5ZHJhdGlvbih0YXJnZXQsIG5vZGUpO1xuXHR9IGVsc2UgaWYgKG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0IHx8IG5vZGUubmV4dFNpYmxpbmcgIT0gYW5jaG9yKSB7XG5cdFx0dGFyZ2V0Lmluc2VydEJlZm9yZShub2RlLCBhbmNob3IgfHwgbnVsbCk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGV0YWNoKG5vZGUpIHtcblx0aWYgKG5vZGUucGFyZW50Tm9kZSkge1xuXHRcdG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblx0fVxufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlc3Ryb3lfZWFjaChpdGVyYXRpb25zLCBkZXRhY2hpbmcpIHtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBpdGVyYXRpb25zLmxlbmd0aDsgaSArPSAxKSB7XG5cdFx0aWYgKGl0ZXJhdGlvbnNbaV0pIGl0ZXJhdGlvbnNbaV0uZChkZXRhY2hpbmcpO1xuXHR9XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIHtrZXlvZiBIVE1MRWxlbWVudFRhZ05hbWVNYXB9IEtcbiAqIEBwYXJhbSB7S30gbmFtZVxuICogQHJldHVybnMge0hUTUxFbGVtZW50VGFnTmFtZU1hcFtLXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVsZW1lbnQobmFtZSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChuYW1lKTtcbn1cblxuLyoqXG4gKiBAdGVtcGxhdGUge2tleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcH0gS1xuICogQHBhcmFtIHtLfSBuYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gaXNcbiAqIEByZXR1cm5zIHtIVE1MRWxlbWVudFRhZ05hbWVNYXBbS119XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbGVtZW50X2lzKG5hbWUsIGlzKSB7XG5cdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KG5hbWUsIHsgaXMgfSk7XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIFRcbiAqIEB0ZW1wbGF0ZSB7a2V5b2YgVH0gS1xuICogQHBhcmFtIHtUfSBvYmpcbiAqIEBwYXJhbSB7S1tdfSBleGNsdWRlXG4gKiBAcmV0dXJucyB7UGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+Pn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdF93aXRob3V0X3Byb3BlcnRpZXMob2JqLCBleGNsdWRlKSB7XG5cdGNvbnN0IHRhcmdldCA9IC8qKiBAdHlwZSB7UGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+Pn0gKi8gKHt9KTtcblx0Zm9yIChjb25zdCBrIGluIG9iaikge1xuXHRcdGlmIChcblx0XHRcdGhhc19wcm9wKG9iaiwgaykgJiZcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdGV4Y2x1ZGUuaW5kZXhPZihrKSA9PT0gLTFcblx0XHQpIHtcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdHRhcmdldFtrXSA9IG9ialtrXTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHRhcmdldDtcbn1cblxuLyoqXG4gKiBAdGVtcGxhdGUge2tleW9mIFNWR0VsZW1lbnRUYWdOYW1lTWFwfSBLXG4gKiBAcGFyYW0ge0t9IG5hbWVcbiAqIEByZXR1cm5zIHtTVkdFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ZnX2VsZW1lbnQobmFtZSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsIG5hbWUpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhXG4gKiBAcmV0dXJucyB7VGV4dH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRleHQoZGF0YSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoZGF0YSk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gc3BhY2UoKSB7XG5cdHJldHVybiB0ZXh0KCcgJyk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gZW1wdHkoKSB7XG5cdHJldHVybiB0ZXh0KCcnKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudFxuICogQHJldHVybnMge0NvbW1lbnR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21tZW50KGNvbnRlbnQpIHtcblx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoY29udGVudCk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtFdmVudFRhcmdldH0gbm9kZVxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG4gKiBAcGFyYW0ge0V2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3R9IGhhbmRsZXJcbiAqIEBwYXJhbSB7Ym9vbGVhbiB8IEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zIHwgRXZlbnRMaXN0ZW5lck9wdGlvbnN9IFtvcHRpb25zXVxuICogQHJldHVybnMgeygpID0+IHZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0ZW4obm9kZSwgZXZlbnQsIGhhbmRsZXIsIG9wdGlvbnMpIHtcblx0bm9kZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLCBvcHRpb25zKTtcblx0cmV0dXJuICgpID0+IG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlciwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogQHJldHVybnMgeyhldmVudDogYW55KSA9PiBhbnl9ICovXG5leHBvcnQgZnVuY3Rpb24gcHJldmVudF9kZWZhdWx0KGZuKSB7XG5cdHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdC8vIEB0cy1pZ25vcmVcblx0XHRyZXR1cm4gZm4uY2FsbCh0aGlzLCBldmVudCk7XG5cdH07XG59XG5cbi8qKlxuICogQHJldHVybnMgeyhldmVudDogYW55KSA9PiBhbnl9ICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcF9wcm9wYWdhdGlvbihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdHJldHVybiBmbi5jYWxsKHRoaXMsIGV2ZW50KTtcblx0fTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7KGV2ZW50OiBhbnkpID0+IGFueX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9wX2ltbWVkaWF0ZV9wcm9wYWdhdGlvbihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdHJldHVybiBmbi5jYWxsKHRoaXMsIGV2ZW50KTtcblx0fTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7KGV2ZW50OiBhbnkpID0+IHZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2VsZihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdGlmIChldmVudC50YXJnZXQgPT09IHRoaXMpIGZuLmNhbGwodGhpcywgZXZlbnQpO1xuXHR9O1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHsoZXZlbnQ6IGFueSkgPT4gdm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cnVzdGVkKGZuKSB7XG5cdHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0aWYgKGV2ZW50LmlzVHJ1c3RlZCkgZm4uY2FsbCh0aGlzLCBldmVudCk7XG5cdH07XG59XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0cmlidXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gW3ZhbHVlXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRyKG5vZGUsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcblx0aWYgKHZhbHVlID09IG51bGwpIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJpYnV0ZSk7XG5cdGVsc2UgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZSkgIT09IHZhbHVlKSBub2RlLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUsIHZhbHVlKTtcbn1cbi8qKlxuICogTGlzdCBvZiBhdHRyaWJ1dGVzIHRoYXQgc2hvdWxkIGFsd2F5cyBiZSBzZXQgdGhyb3VnaCB0aGUgYXR0ciBtZXRob2QsXG4gKiBiZWNhdXNlIHVwZGF0aW5nIHRoZW0gdGhyb3VnaCB0aGUgcHJvcGVydHkgc2V0dGVyIGRvZXNuJ3Qgd29yayByZWxpYWJseS5cbiAqIEluIHRoZSBleGFtcGxlIG9mIGB3aWR0aGAvYGhlaWdodGAsIHRoZSBwcm9ibGVtIGlzIHRoYXQgdGhlIHNldHRlciBvbmx5XG4gKiBhY2NlcHRzIG51bWVyaWMgdmFsdWVzLCBidXQgdGhlIGF0dHJpYnV0ZSBjYW4gYWxzbyBiZSBzZXQgdG8gYSBzdHJpbmcgbGlrZSBgNTAlYC5cbiAqIElmIHRoaXMgbGlzdCBiZWNvbWVzIHRvbyBiaWcsIHJldGhpbmsgdGhpcyBhcHByb2FjaC5cbiAqL1xuY29uc3QgYWx3YXlzX3NldF90aHJvdWdoX3NldF9hdHRyaWJ1dGUgPSBbJ3dpZHRoJywgJ2hlaWdodCddO1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHt7IFt4OiBzdHJpbmddOiBzdHJpbmcgfX0gYXR0cmlidXRlc1xuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfYXR0cmlidXRlcyhub2RlLCBhdHRyaWJ1dGVzKSB7XG5cdC8vIEB0cy1pZ25vcmVcblx0Y29uc3QgZGVzY3JpcHRvcnMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhub2RlLl9fcHJvdG9fXyk7XG5cdGZvciAoY29uc3Qga2V5IGluIGF0dHJpYnV0ZXMpIHtcblx0XHRpZiAoYXR0cmlidXRlc1trZXldID09IG51bGwpIHtcblx0XHRcdG5vZGUucmVtb3ZlQXR0cmlidXRlKGtleSk7XG5cdFx0fSBlbHNlIGlmIChrZXkgPT09ICdzdHlsZScpIHtcblx0XHRcdG5vZGUuc3R5bGUuY3NzVGV4dCA9IGF0dHJpYnV0ZXNba2V5XTtcblx0XHR9IGVsc2UgaWYgKGtleSA9PT0gJ19fdmFsdWUnKSB7XG5cdFx0XHQvKiogQHR5cGUge2FueX0gKi8gKG5vZGUpLnZhbHVlID0gbm9kZVtrZXldID0gYXR0cmlidXRlc1trZXldO1xuXHRcdH0gZWxzZSBpZiAoXG5cdFx0XHRkZXNjcmlwdG9yc1trZXldICYmXG5cdFx0XHRkZXNjcmlwdG9yc1trZXldLnNldCAmJlxuXHRcdFx0YWx3YXlzX3NldF90aHJvdWdoX3NldF9hdHRyaWJ1dGUuaW5kZXhPZihrZXkpID09PSAtMVxuXHRcdCkge1xuXHRcdFx0bm9kZVtrZXldID0gYXR0cmlidXRlc1trZXldO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhdHRyKG5vZGUsIGtleSwgYXR0cmlidXRlc1trZXldKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnQgJiBFbGVtZW50Q1NTSW5saW5lU3R5bGV9IG5vZGVcbiAqIEBwYXJhbSB7eyBbeDogc3RyaW5nXTogc3RyaW5nIH19IGF0dHJpYnV0ZXNcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X3N2Z19hdHRyaWJ1dGVzKG5vZGUsIGF0dHJpYnV0ZXMpIHtcblx0Zm9yIChjb25zdCBrZXkgaW4gYXR0cmlidXRlcykge1xuXHRcdGF0dHIobm9kZSwga2V5LCBhdHRyaWJ1dGVzW2tleV0pO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gZGF0YV9tYXBcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2N1c3RvbV9lbGVtZW50X2RhdGFfbWFwKG5vZGUsIGRhdGFfbWFwKSB7XG5cdE9iamVjdC5rZXlzKGRhdGFfbWFwKS5mb3JFYWNoKChrZXkpID0+IHtcblx0XHRzZXRfY3VzdG9tX2VsZW1lbnRfZGF0YShub2RlLCBrZXksIGRhdGFfbWFwW2tleV0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfY3VzdG9tX2VsZW1lbnRfZGF0YShub2RlLCBwcm9wLCB2YWx1ZSkge1xuXHRjb25zdCBsb3dlciA9IHByb3AudG9Mb3dlckNhc2UoKTsgLy8gZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggZXhpc3RpbmcgYmVoYXZpb3Igd2UgZG8gbG93ZXJjYXNlIGZpcnN0XG5cdGlmIChsb3dlciBpbiBub2RlKSB7XG5cdFx0bm9kZVtsb3dlcl0gPSB0eXBlb2Ygbm9kZVtsb3dlcl0gPT09ICdib29sZWFuJyAmJiB2YWx1ZSA9PT0gJycgPyB0cnVlIDogdmFsdWU7XG5cdH0gZWxzZSBpZiAocHJvcCBpbiBub2RlKSB7XG5cdFx0bm9kZVtwcm9wXSA9IHR5cGVvZiBub2RlW3Byb3BdID09PSAnYm9vbGVhbicgJiYgdmFsdWUgPT09ICcnID8gdHJ1ZSA6IHZhbHVlO1xuXHR9IGVsc2Uge1xuXHRcdGF0dHIobm9kZSwgcHJvcCwgdmFsdWUpO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHRhZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2R5bmFtaWNfZWxlbWVudF9kYXRhKHRhZykge1xuXHRyZXR1cm4gLy0vLnRlc3QodGFnKSA/IHNldF9jdXN0b21fZWxlbWVudF9kYXRhX21hcCA6IHNldF9hdHRyaWJ1dGVzO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24geGxpbmtfYXR0cihub2RlLCBhdHRyaWJ1dGUsIHZhbHVlKSB7XG5cdG5vZGUuc2V0QXR0cmlidXRlTlMoJ2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnLCBhdHRyaWJ1dGUsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBub2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X3N2ZWx0ZV9kYXRhc2V0KG5vZGUpIHtcblx0cmV0dXJuIG5vZGUuZGF0YXNldC5zdmVsdGVIO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt1bmtub3duW119ICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X2JpbmRpbmdfZ3JvdXBfdmFsdWUoZ3JvdXAsIF9fdmFsdWUsIGNoZWNrZWQpIHtcblx0Y29uc3QgdmFsdWUgPSBuZXcgU2V0KCk7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgZ3JvdXAubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRpZiAoZ3JvdXBbaV0uY2hlY2tlZCkgdmFsdWUuYWRkKGdyb3VwW2ldLl9fdmFsdWUpO1xuXHR9XG5cdGlmICghY2hlY2tlZCkge1xuXHRcdHZhbHVlLmRlbGV0ZShfX3ZhbHVlKTtcblx0fVxuXHRyZXR1cm4gQXJyYXkuZnJvbSh2YWx1ZSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MSW5wdXRFbGVtZW50W119IGdyb3VwXG4gKiBAcmV0dXJucyB7eyBwKC4uLmlucHV0czogSFRNTElucHV0RWxlbWVudFtdKTogdm9pZDsgcigpOiB2b2lkOyB9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdF9iaW5kaW5nX2dyb3VwKGdyb3VwKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2lucHV0cztcblx0cmV0dXJuIHtcblx0XHQvKiBwdXNoICovIHAoLi4uaW5wdXRzKSB7XG5cdFx0XHRfaW5wdXRzID0gaW5wdXRzO1xuXHRcdFx0X2lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gZ3JvdXAucHVzaChpbnB1dCkpO1xuXHRcdH0sXG5cdFx0LyogcmVtb3ZlICovIHIoKSB7XG5cdFx0XHRfaW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiBncm91cC5zcGxpY2UoZ3JvdXAuaW5kZXhPZihpbnB1dCksIDEpKTtcblx0XHR9XG5cdH07XG59XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJbXX0gaW5kZXhlc1xuICogQHJldHVybnMge3sgdShuZXdfaW5kZXhlczogbnVtYmVyW10pOiB2b2lkOyBwKC4uLmlucHV0czogSFRNTElucHV0RWxlbWVudFtdKTogdm9pZDsgcjogKCkgPT4gdm9pZDsgfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRfYmluZGluZ19ncm91cF9keW5hbWljKGdyb3VwLCBpbmRleGVzKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2dyb3VwID0gZ2V0X2JpbmRpbmdfZ3JvdXAoZ3JvdXApO1xuXG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2lucHV0cztcblxuXHRmdW5jdGlvbiBnZXRfYmluZGluZ19ncm91cChncm91cCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaW5kZXhlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Z3JvdXAgPSBncm91cFtpbmRleGVzW2ldXSA9IGdyb3VwW2luZGV4ZXNbaV1dIHx8IFtdO1xuXHRcdH1cblx0XHRyZXR1cm4gZ3JvdXA7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGZ1bmN0aW9uIHB1c2goKSB7XG5cdFx0X2lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gX2dyb3VwLnB1c2goaW5wdXQpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJucyB7dm9pZH0gKi9cblx0ZnVuY3Rpb24gcmVtb3ZlKCkge1xuXHRcdF9pbnB1dHMuZm9yRWFjaCgoaW5wdXQpID0+IF9ncm91cC5zcGxpY2UoX2dyb3VwLmluZGV4T2YoaW5wdXQpLCAxKSk7XG5cdH1cblx0cmV0dXJuIHtcblx0XHQvKiB1cGRhdGUgKi8gdShuZXdfaW5kZXhlcykge1xuXHRcdFx0aW5kZXhlcyA9IG5ld19pbmRleGVzO1xuXHRcdFx0Y29uc3QgbmV3X2dyb3VwID0gZ2V0X2JpbmRpbmdfZ3JvdXAoZ3JvdXApO1xuXHRcdFx0aWYgKG5ld19ncm91cCAhPT0gX2dyb3VwKSB7XG5cdFx0XHRcdHJlbW92ZSgpO1xuXHRcdFx0XHRfZ3JvdXAgPSBuZXdfZ3JvdXA7XG5cdFx0XHRcdHB1c2goKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdC8qIHB1c2ggKi8gcCguLi5pbnB1dHMpIHtcblx0XHRcdF9pbnB1dHMgPSBpbnB1dHM7XG5cdFx0XHRwdXNoKCk7XG5cdFx0fSxcblx0XHQvKiByZW1vdmUgKi8gcjogcmVtb3ZlXG5cdH07XG59XG5cbi8qKiBAcmV0dXJucyB7bnVtYmVyfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvX251bWJlcih2YWx1ZSkge1xuXHRyZXR1cm4gdmFsdWUgPT09ICcnID8gbnVsbCA6ICt2YWx1ZTtcbn1cblxuLyoqIEByZXR1cm5zIHthbnlbXX0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aW1lX3Jhbmdlc190b19hcnJheShyYW5nZXMpIHtcblx0Y29uc3QgYXJyYXkgPSBbXTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRhcnJheS5wdXNoKHsgc3RhcnQ6IHJhbmdlcy5zdGFydChpKSwgZW5kOiByYW5nZXMuZW5kKGkpIH0pO1xuXHR9XG5cdHJldHVybiBhcnJheTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtDaGlsZE5vZGVbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoaWxkcmVuKGVsZW1lbnQpIHtcblx0cmV0dXJuIEFycmF5LmZyb20oZWxlbWVudC5jaGlsZE5vZGVzKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGluaXRfY2xhaW1faW5mbyhub2Rlcykge1xuXHRpZiAobm9kZXMuY2xhaW1faW5mbyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0bm9kZXMuY2xhaW1faW5mbyA9IHsgbGFzdF9pbmRleDogMCwgdG90YWxfY2xhaW1lZDogMCB9O1xuXHR9XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIHtDaGlsZE5vZGVFeH0gUlxuICogQHBhcmFtIHtDaGlsZE5vZGVBcnJheX0gbm9kZXNcbiAqIEBwYXJhbSB7KG5vZGU6IENoaWxkTm9kZUV4KSA9PiBub2RlIGlzIFJ9IHByZWRpY2F0ZVxuICogQHBhcmFtIHsobm9kZTogQ2hpbGROb2RlRXgpID0+IENoaWxkTm9kZUV4IHwgdW5kZWZpbmVkfSBwcm9jZXNzX25vZGVcbiAqIEBwYXJhbSB7KCkgPT4gUn0gY3JlYXRlX25vZGVcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9udF91cGRhdGVfbGFzdF9pbmRleFxuICogQHJldHVybnMge1J9XG4gKi9cbmZ1bmN0aW9uIGNsYWltX25vZGUobm9kZXMsIHByZWRpY2F0ZSwgcHJvY2Vzc19ub2RlLCBjcmVhdGVfbm9kZSwgZG9udF91cGRhdGVfbGFzdF9pbmRleCA9IGZhbHNlKSB7XG5cdC8vIFRyeSB0byBmaW5kIG5vZGVzIGluIGFuIG9yZGVyIHN1Y2ggdGhhdCB3ZSBsZW5ndGhlbiB0aGUgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlXG5cdGluaXRfY2xhaW1faW5mbyhub2Rlcyk7XG5cdGNvbnN0IHJlc3VsdF9ub2RlID0gKCgpID0+IHtcblx0XHQvLyBXZSBmaXJzdCB0cnkgdG8gZmluZCBhbiBlbGVtZW50IGFmdGVyIHRoZSBwcmV2aW91cyBvbmVcblx0XHRmb3IgKGxldCBpID0gbm9kZXMuY2xhaW1faW5mby5sYXN0X2luZGV4OyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcblx0XHRcdGlmIChwcmVkaWNhdGUobm9kZSkpIHtcblx0XHRcdFx0Y29uc3QgcmVwbGFjZW1lbnQgPSBwcm9jZXNzX25vZGUobm9kZSk7XG5cdFx0XHRcdGlmIChyZXBsYWNlbWVudCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0bm9kZXMuc3BsaWNlKGksIDEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdG5vZGVzW2ldID0gcmVwbGFjZW1lbnQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCFkb250X3VwZGF0ZV9sYXN0X2luZGV4KSB7XG5cdFx0XHRcdFx0bm9kZXMuY2xhaW1faW5mby5sYXN0X2luZGV4ID0gaTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gbm9kZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gT3RoZXJ3aXNlLCB3ZSB0cnkgdG8gZmluZCBvbmUgYmVmb3JlXG5cdFx0Ly8gV2UgaXRlcmF0ZSBpbiByZXZlcnNlIHNvIHRoYXQgd2UgZG9uJ3QgZ28gdG9vIGZhciBiYWNrXG5cdFx0Zm9yIChsZXQgaSA9IG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleCAtIDE7IGkgPj0gMDsgaS0tKSB7XG5cdFx0XHRjb25zdCBub2RlID0gbm9kZXNbaV07XG5cdFx0XHRpZiAocHJlZGljYXRlKG5vZGUpKSB7XG5cdFx0XHRcdGNvbnN0IHJlcGxhY2VtZW50ID0gcHJvY2Vzc19ub2RlKG5vZGUpO1xuXHRcdFx0XHRpZiAocmVwbGFjZW1lbnQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdG5vZGVzLnNwbGljZShpLCAxKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRub2Rlc1tpXSA9IHJlcGxhY2VtZW50O1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICghZG9udF91cGRhdGVfbGFzdF9pbmRleCkge1xuXHRcdFx0XHRcdG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleCA9IGk7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVwbGFjZW1lbnQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdC8vIFNpbmNlIHdlIHNwbGljZWQgYmVmb3JlIHRoZSBsYXN0X2luZGV4LCB3ZSBkZWNyZWFzZSBpdFxuXHRcdFx0XHRcdG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleC0tO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBub2RlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBJZiB3ZSBjYW4ndCBmaW5kIGFueSBtYXRjaGluZyBub2RlLCB3ZSBjcmVhdGUgYSBuZXcgb25lXG5cdFx0cmV0dXJuIGNyZWF0ZV9ub2RlKCk7XG5cdH0pKCk7XG5cdHJlc3VsdF9ub2RlLmNsYWltX29yZGVyID0gbm9kZXMuY2xhaW1faW5mby50b3RhbF9jbGFpbWVkO1xuXHRub2Rlcy5jbGFpbV9pbmZvLnRvdGFsX2NsYWltZWQgKz0gMTtcblx0cmV0dXJuIHJlc3VsdF9ub2RlO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Q2hpbGROb2RlQXJyYXl9IG5vZGVzXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHt7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfX0gYXR0cmlidXRlc1xuICogQHBhcmFtIHsobmFtZTogc3RyaW5nKSA9PiBFbGVtZW50IHwgU1ZHRWxlbWVudH0gY3JlYXRlX2VsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50IHwgU1ZHRWxlbWVudH1cbiAqL1xuZnVuY3Rpb24gY2xhaW1fZWxlbWVudF9iYXNlKG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzLCBjcmVhdGVfZWxlbWVudCkge1xuXHRyZXR1cm4gY2xhaW1fbm9kZShcblx0XHRub2Rlcyxcblx0XHQvKiogQHJldHVybnMge25vZGUgaXMgRWxlbWVudCB8IFNWR0VsZW1lbnR9ICovXG5cdFx0KG5vZGUpID0+IG5vZGUubm9kZU5hbWUgPT09IG5hbWUsXG5cdFx0LyoqIEBwYXJhbSB7RWxlbWVudH0gbm9kZSAqL1xuXHRcdChub2RlKSA9PiB7XG5cdFx0XHRjb25zdCByZW1vdmUgPSBbXTtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgbm9kZS5hdHRyaWJ1dGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGNvbnN0IGF0dHJpYnV0ZSA9IG5vZGUuYXR0cmlidXRlc1tqXTtcblx0XHRcdFx0aWYgKCFhdHRyaWJ1dGVzW2F0dHJpYnV0ZS5uYW1lXSkge1xuXHRcdFx0XHRcdHJlbW92ZS5wdXNoKGF0dHJpYnV0ZS5uYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmVtb3ZlLmZvckVhY2goKHYpID0+IG5vZGUucmVtb3ZlQXR0cmlidXRlKHYpKTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0XHQoKSA9PiBjcmVhdGVfZWxlbWVudChuYW1lKVxuXHQpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Q2hpbGROb2RlQXJyYXl9IG5vZGVzXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHt7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfX0gYXR0cmlidXRlc1xuICogQHJldHVybnMge0VsZW1lbnQgfCBTVkdFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fZWxlbWVudChub2RlcywgbmFtZSwgYXR0cmlidXRlcykge1xuXHRyZXR1cm4gY2xhaW1fZWxlbWVudF9iYXNlKG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzLCBlbGVtZW50KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7eyBba2V5OiBzdHJpbmddOiBib29sZWFuIH19IGF0dHJpYnV0ZXNcbiAqIEByZXR1cm5zIHtFbGVtZW50IHwgU1ZHRWxlbWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYWltX3N2Z19lbGVtZW50KG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzKSB7XG5cdHJldHVybiBjbGFpbV9lbGVtZW50X2Jhc2Uobm9kZXMsIG5hbWUsIGF0dHJpYnV0ZXMsIHN2Z19lbGVtZW50KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHJldHVybnMge1RleHR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFpbV90ZXh0KG5vZGVzLCBkYXRhKSB7XG5cdHJldHVybiBjbGFpbV9ub2RlKFxuXHRcdG5vZGVzLFxuXHRcdC8qKiBAcmV0dXJucyB7bm9kZSBpcyBUZXh0fSAqL1xuXHRcdChub2RlKSA9PiBub2RlLm5vZGVUeXBlID09PSAzLFxuXHRcdC8qKiBAcGFyYW0ge1RleHR9IG5vZGUgKi9cblx0XHQobm9kZSkgPT4ge1xuXHRcdFx0Y29uc3QgZGF0YV9zdHIgPSAnJyArIGRhdGE7XG5cdFx0XHRpZiAobm9kZS5kYXRhLnN0YXJ0c1dpdGgoZGF0YV9zdHIpKSB7XG5cdFx0XHRcdGlmIChub2RlLmRhdGEubGVuZ3RoICE9PSBkYXRhX3N0ci5sZW5ndGgpIHtcblx0XHRcdFx0XHRyZXR1cm4gbm9kZS5zcGxpdFRleHQoZGF0YV9zdHIubGVuZ3RoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bm9kZS5kYXRhID0gZGF0YV9zdHI7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHQoKSA9PiB0ZXh0KGRhdGEpLFxuXHRcdHRydWUgLy8gVGV4dCBub2RlcyBzaG91bGQgbm90IHVwZGF0ZSBsYXN0IGluZGV4IHNpbmNlIGl0IGlzIGxpa2VseSBub3Qgd29ydGggaXQgdG8gZWxpbWluYXRlIGFuIGluY3JlYXNpbmcgc3Vic2VxdWVuY2Ugb2YgYWN0dWFsIGVsZW1lbnRzXG5cdCk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fc3BhY2Uobm9kZXMpIHtcblx0cmV0dXJuIGNsYWltX3RleHQobm9kZXMsICcgJyk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtDaGlsZE5vZGVBcnJheX0gbm9kZXNcbiAqIEByZXR1cm5zIHtDb21tZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fY29tbWVudChub2RlcywgZGF0YSkge1xuXHRyZXR1cm4gY2xhaW1fbm9kZShcblx0XHRub2Rlcyxcblx0XHQvKiogQHJldHVybnMge25vZGUgaXMgQ29tbWVudH0gKi9cblx0XHQobm9kZSkgPT4gbm9kZS5ub2RlVHlwZSA9PT0gOCxcblx0XHQvKiogQHBhcmFtIHtDb21tZW50fSBub2RlICovXG5cdFx0KG5vZGUpID0+IHtcblx0XHRcdG5vZGUuZGF0YSA9ICcnICsgZGF0YTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0XHQoKSA9PiBjb21tZW50KGRhdGEpLFxuXHRcdHRydWVcblx0KTtcbn1cblxuZnVuY3Rpb24gZ2V0X2NvbW1lbnRfaWR4KG5vZGVzLCB0ZXh0LCBzdGFydCkge1xuXHRmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBub2Rlcy5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcblx0XHRpZiAobm9kZS5ub2RlVHlwZSA9PT0gOCAvKiBjb21tZW50IG5vZGUgKi8gJiYgbm9kZS50ZXh0Q29udGVudC50cmltKCkgPT09IHRleHQpIHtcblx0XHRcdHJldHVybiBpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gLTE7XG59XG5cbi8qKlxuICogQHBhcmFtIHtib29sZWFufSBpc19zdmdcbiAqIEByZXR1cm5zIHtIdG1sVGFnSHlkcmF0aW9ufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1faHRtbF90YWcobm9kZXMsIGlzX3N2Zykge1xuXHQvLyBmaW5kIGh0bWwgb3BlbmluZyB0YWdcblx0Y29uc3Qgc3RhcnRfaW5kZXggPSBnZXRfY29tbWVudF9pZHgobm9kZXMsICdIVE1MX1RBR19TVEFSVCcsIDApO1xuXHRjb25zdCBlbmRfaW5kZXggPSBnZXRfY29tbWVudF9pZHgobm9kZXMsICdIVE1MX1RBR19FTkQnLCBzdGFydF9pbmRleCArIDEpO1xuXHRpZiAoc3RhcnRfaW5kZXggPT09IC0xIHx8IGVuZF9pbmRleCA9PT0gLTEpIHtcblx0XHRyZXR1cm4gbmV3IEh0bWxUYWdIeWRyYXRpb24oaXNfc3ZnKTtcblx0fVxuXG5cdGluaXRfY2xhaW1faW5mbyhub2Rlcyk7XG5cdGNvbnN0IGh0bWxfdGFnX25vZGVzID0gbm9kZXMuc3BsaWNlKHN0YXJ0X2luZGV4LCBlbmRfaW5kZXggLSBzdGFydF9pbmRleCArIDEpO1xuXHRkZXRhY2goaHRtbF90YWdfbm9kZXNbMF0pO1xuXHRkZXRhY2goaHRtbF90YWdfbm9kZXNbaHRtbF90YWdfbm9kZXMubGVuZ3RoIC0gMV0pO1xuXHRjb25zdCBjbGFpbWVkX25vZGVzID0gaHRtbF90YWdfbm9kZXMuc2xpY2UoMSwgaHRtbF90YWdfbm9kZXMubGVuZ3RoIC0gMSk7XG5cdGlmIChjbGFpbWVkX25vZGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBuZXcgSHRtbFRhZ0h5ZHJhdGlvbihpc19zdmcpO1xuXHR9XG5cdGZvciAoY29uc3QgbiBvZiBjbGFpbWVkX25vZGVzKSB7XG5cdFx0bi5jbGFpbV9vcmRlciA9IG5vZGVzLmNsYWltX2luZm8udG90YWxfY2xhaW1lZDtcblx0XHRub2Rlcy5jbGFpbV9pbmZvLnRvdGFsX2NsYWltZWQgKz0gMTtcblx0fVxuXHRyZXR1cm4gbmV3IEh0bWxUYWdIeWRyYXRpb24oaXNfc3ZnLCBjbGFpbWVkX25vZGVzKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfZGF0YSh0ZXh0LCBkYXRhKSB7XG5cdGRhdGEgPSAnJyArIGRhdGE7XG5cdGlmICh0ZXh0LmRhdGEgPT09IGRhdGEpIHJldHVybjtcblx0dGV4dC5kYXRhID0gLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkYXRhKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfZGF0YV9jb250ZW50ZWRpdGFibGUodGV4dCwgZGF0YSkge1xuXHRkYXRhID0gJycgKyBkYXRhO1xuXHRpZiAodGV4dC53aG9sZVRleHQgPT09IGRhdGEpIHJldHVybjtcblx0dGV4dC5kYXRhID0gLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkYXRhKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHJfdmFsdWVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2RhdGFfbWF5YmVfY29udGVudGVkaXRhYmxlKHRleHQsIGRhdGEsIGF0dHJfdmFsdWUpIHtcblx0aWYgKH5jb250ZW50ZWRpdGFibGVfdHJ1dGh5X3ZhbHVlcy5pbmRleE9mKGF0dHJfdmFsdWUpKSB7XG5cdFx0c2V0X2RhdGFfY29udGVudGVkaXRhYmxlKHRleHQsIGRhdGEpO1xuXHR9IGVsc2Uge1xuXHRcdHNldF9kYXRhKHRleHQsIGRhdGEpO1xuXHR9XG59XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2lucHV0X3ZhbHVlKGlucHV0LCB2YWx1ZSkge1xuXHRpbnB1dC52YWx1ZSA9IHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldF9pbnB1dF90eXBlKGlucHV0LCB0eXBlKSB7XG5cdHRyeSB7XG5cdFx0aW5wdXQudHlwZSA9IHR5cGU7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHQvLyBkbyBub3RoaW5nXG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfc3R5bGUobm9kZSwga2V5LCB2YWx1ZSwgaW1wb3J0YW50KSB7XG5cdGlmICh2YWx1ZSA9PSBudWxsKSB7XG5cdFx0bm9kZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpO1xuXHR9IGVsc2Uge1xuXHRcdG5vZGUuc3R5bGUuc2V0UHJvcGVydHkoa2V5LCB2YWx1ZSwgaW1wb3J0YW50ID8gJ2ltcG9ydGFudCcgOiAnJyk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3Rfb3B0aW9uKHNlbGVjdCwgdmFsdWUsIG1vdW50aW5nKSB7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0Lm9wdGlvbnMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRjb25zdCBvcHRpb24gPSBzZWxlY3Qub3B0aW9uc1tpXTtcblx0XHRpZiAob3B0aW9uLl9fdmFsdWUgPT09IHZhbHVlKSB7XG5cdFx0XHRvcHRpb24uc2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0fVxuXHRpZiAoIW1vdW50aW5nIHx8IHZhbHVlICE9PSB1bmRlZmluZWQpIHtcblx0XHRzZWxlY3Quc2VsZWN0ZWRJbmRleCA9IC0xOyAvLyBubyBvcHRpb24gc2hvdWxkIGJlIHNlbGVjdGVkXG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3Rfb3B0aW9ucyhzZWxlY3QsIHZhbHVlKSB7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0Lm9wdGlvbnMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRjb25zdCBvcHRpb24gPSBzZWxlY3Qub3B0aW9uc1tpXTtcblx0XHRvcHRpb24uc2VsZWN0ZWQgPSB+dmFsdWUuaW5kZXhPZihvcHRpb24uX192YWx1ZSk7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNlbGVjdF92YWx1ZShzZWxlY3QpIHtcblx0Y29uc3Qgc2VsZWN0ZWRfb3B0aW9uID0gc2VsZWN0LnF1ZXJ5U2VsZWN0b3IoJzpjaGVja2VkJyk7XG5cdHJldHVybiBzZWxlY3RlZF9vcHRpb24gJiYgc2VsZWN0ZWRfb3B0aW9uLl9fdmFsdWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RfbXVsdGlwbGVfdmFsdWUoc2VsZWN0KSB7XG5cdHJldHVybiBbXS5tYXAuY2FsbChzZWxlY3QucXVlcnlTZWxlY3RvckFsbCgnOmNoZWNrZWQnKSwgKG9wdGlvbikgPT4gb3B0aW9uLl9fdmFsdWUpO1xufVxuLy8gdW5mb3J0dW5hdGVseSB0aGlzIGNhbid0IGJlIGEgY29uc3RhbnQgYXMgdGhhdCB3b3VsZG4ndCBiZSB0cmVlLXNoYWtlYWJsZVxuLy8gc28gd2UgY2FjaGUgdGhlIHJlc3VsdCBpbnN0ZWFkXG5cbi8qKlxuICogQHR5cGUge2Jvb2xlYW59ICovXG5sZXQgY3Jvc3NvcmlnaW47XG5cbi8qKlxuICogQHJldHVybnMge2Jvb2xlYW59ICovXG5leHBvcnQgZnVuY3Rpb24gaXNfY3Jvc3NvcmlnaW4oKSB7XG5cdGlmIChjcm9zc29yaWdpbiA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0Y3Jvc3NvcmlnaW4gPSBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5wYXJlbnQpIHtcblx0XHRcdFx0dm9pZCB3aW5kb3cucGFyZW50LmRvY3VtZW50O1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRjcm9zc29yaWdpbiA9IHRydWU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBjcm9zc29yaWdpbjtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBub2RlXG4gKiBAcGFyYW0geygpID0+IHZvaWR9IGZuXG4gKiBAcmV0dXJucyB7KCkgPT4gdm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZF9pZnJhbWVfcmVzaXplX2xpc3RlbmVyKG5vZGUsIGZuKSB7XG5cdGNvbnN0IGNvbXB1dGVkX3N0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShub2RlKTtcblx0aWYgKGNvbXB1dGVkX3N0eWxlLnBvc2l0aW9uID09PSAnc3RhdGljJykge1xuXHRcdG5vZGUuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuXHR9XG5cdGNvbnN0IGlmcmFtZSA9IGVsZW1lbnQoJ2lmcmFtZScpO1xuXHRpZnJhbWUuc2V0QXR0cmlidXRlKFxuXHRcdCdzdHlsZScsXG5cdFx0J2Rpc3BsYXk6IGJsb2NrOyBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogMDsgbGVmdDogMDsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsgJyArXG5cdFx0XHQnb3ZlcmZsb3c6IGhpZGRlbjsgYm9yZGVyOiAwOyBvcGFjaXR5OiAwOyBwb2ludGVyLWV2ZW50czogbm9uZTsgei1pbmRleDogLTE7J1xuXHQpO1xuXHRpZnJhbWUuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG5cdGlmcmFtZS50YWJJbmRleCA9IC0xO1xuXHRjb25zdCBjcm9zc29yaWdpbiA9IGlzX2Nyb3Nzb3JpZ2luKCk7XG5cblx0LyoqXG5cdCAqIEB0eXBlIHsoKSA9PiB2b2lkfVxuXHQgKi9cblx0bGV0IHVuc3Vic2NyaWJlO1xuXHRpZiAoY3Jvc3NvcmlnaW4pIHtcblx0XHRpZnJhbWUuc3JjID0gXCJkYXRhOnRleHQvaHRtbCw8c2NyaXB0Pm9ucmVzaXplPWZ1bmN0aW9uKCl7cGFyZW50LnBvc3RNZXNzYWdlKDAsJyonKX08L3NjcmlwdD5cIjtcblx0XHR1bnN1YnNjcmliZSA9IGxpc3Rlbihcblx0XHRcdHdpbmRvdyxcblx0XHRcdCdtZXNzYWdlJyxcblx0XHRcdC8qKiBAcGFyYW0ge01lc3NhZ2VFdmVudH0gZXZlbnQgKi8gKGV2ZW50KSA9PiB7XG5cdFx0XHRcdGlmIChldmVudC5zb3VyY2UgPT09IGlmcmFtZS5jb250ZW50V2luZG93KSBmbigpO1xuXHRcdFx0fVxuXHRcdCk7XG5cdH0gZWxzZSB7XG5cdFx0aWZyYW1lLnNyYyA9ICdhYm91dDpibGFuayc7XG5cdFx0aWZyYW1lLm9ubG9hZCA9ICgpID0+IHtcblx0XHRcdHVuc3Vic2NyaWJlID0gbGlzdGVuKGlmcmFtZS5jb250ZW50V2luZG93LCAncmVzaXplJywgZm4pO1xuXHRcdFx0Ly8gbWFrZSBzdXJlIGFuIGluaXRpYWwgcmVzaXplIGV2ZW50IGlzIGZpcmVkIF9hZnRlcl8gdGhlIGlmcmFtZSBpcyBsb2FkZWQgKHdoaWNoIGlzIGFzeW5jaHJvbm91cylcblx0XHRcdC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vc3ZlbHRlanMvc3ZlbHRlL2lzc3Vlcy80MjMzXG5cdFx0XHRmbigpO1xuXHRcdH07XG5cdH1cblx0YXBwZW5kKG5vZGUsIGlmcmFtZSk7XG5cdHJldHVybiAoKSA9PiB7XG5cdFx0aWYgKGNyb3Nzb3JpZ2luKSB7XG5cdFx0XHR1bnN1YnNjcmliZSgpO1xuXHRcdH0gZWxzZSBpZiAodW5zdWJzY3JpYmUgJiYgaWZyYW1lLmNvbnRlbnRXaW5kb3cpIHtcblx0XHRcdHVuc3Vic2NyaWJlKCk7XG5cdFx0fVxuXHRcdGRldGFjaChpZnJhbWUpO1xuXHR9O1xufVxuZXhwb3J0IGNvbnN0IHJlc2l6ZV9vYnNlcnZlcl9jb250ZW50X2JveCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgUmVzaXplT2JzZXJ2ZXJTaW5nbGV0b24oe1xuXHRib3g6ICdjb250ZW50LWJveCdcbn0pO1xuZXhwb3J0IGNvbnN0IHJlc2l6ZV9vYnNlcnZlcl9ib3JkZXJfYm94ID0gLyogQF9fUFVSRV9fICovIG5ldyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbih7XG5cdGJveDogJ2JvcmRlci1ib3gnXG59KTtcbmV4cG9ydCBjb25zdCByZXNpemVfb2JzZXJ2ZXJfZGV2aWNlX3BpeGVsX2NvbnRlbnRfYm94ID0gLyogQF9fUFVSRV9fICovIG5ldyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbihcblx0eyBib3g6ICdkZXZpY2UtcGl4ZWwtY29udGVudC1ib3gnIH1cbik7XG5leHBvcnQgeyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbiB9O1xuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZV9jbGFzcyhlbGVtZW50LCBuYW1lLCB0b2dnbGUpIHtcblx0Ly8gVGhlIGAhIWAgaXMgcmVxdWlyZWQgYmVjYXVzZSBhbiBgdW5kZWZpbmVkYCBmbGFnIG1lYW5zIGZsaXBwaW5nIHRoZSBjdXJyZW50IHN0YXRlLlxuXHRlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUobmFtZSwgISF0b2dnbGUpO1xufVxuXG4vKipcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogQHBhcmFtIHtUfSBbZGV0YWlsXVxuICogQHBhcmFtIHt7IGJ1YmJsZXM/OiBib29sZWFuLCBjYW5jZWxhYmxlPzogYm9vbGVhbiB9fSBbb3B0aW9uc11cbiAqIEByZXR1cm5zIHtDdXN0b21FdmVudDxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1c3RvbV9ldmVudCh0eXBlLCBkZXRhaWwsIHsgYnViYmxlcyA9IGZhbHNlLCBjYW5jZWxhYmxlID0gZmFsc2UgfSA9IHt9KSB7XG5cdHJldHVybiBuZXcgQ3VzdG9tRXZlbnQodHlwZSwgeyBkZXRhaWwsIGJ1YmJsZXMsIGNhbmNlbGFibGUgfSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwYXJlbnRcbiAqIEByZXR1cm5zIHtDaGlsZE5vZGVBcnJheX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1ZXJ5X3NlbGVjdG9yX2FsbChzZWxlY3RvciwgcGFyZW50ID0gZG9jdW1lbnQuYm9keSkge1xuXHRyZXR1cm4gQXJyYXkuZnJvbShwYXJlbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBub2RlSWRcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGhlYWRcbiAqIEByZXR1cm5zIHthbnlbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhlYWRfc2VsZWN0b3Iobm9kZUlkLCBoZWFkKSB7XG5cdGNvbnN0IHJlc3VsdCA9IFtdO1xuXHRsZXQgc3RhcnRlZCA9IDA7XG5cdGZvciAoY29uc3Qgbm9kZSBvZiBoZWFkLmNoaWxkTm9kZXMpIHtcblx0XHRpZiAobm9kZS5ub2RlVHlwZSA9PT0gOCAvKiBjb21tZW50IG5vZGUgKi8pIHtcblx0XHRcdGNvbnN0IGNvbW1lbnQgPSBub2RlLnRleHRDb250ZW50LnRyaW0oKTtcblx0XHRcdGlmIChjb21tZW50ID09PSBgSEVBRF8ke25vZGVJZH1fRU5EYCkge1xuXHRcdFx0XHRzdGFydGVkIC09IDE7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKG5vZGUpO1xuXHRcdFx0fSBlbHNlIGlmIChjb21tZW50ID09PSBgSEVBRF8ke25vZGVJZH1fU1RBUlRgKSB7XG5cdFx0XHRcdHN0YXJ0ZWQgKz0gMTtcblx0XHRcdFx0cmVzdWx0LnB1c2gobm9kZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChzdGFydGVkID4gMCkge1xuXHRcdFx0cmVzdWx0LnB1c2gobm9kZSk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiByZXN1bHQ7XG59XG4vKiogKi9cbmV4cG9ydCBjbGFzcyBIdG1sVGFnIHtcblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBkZWZhdWx0IGZhbHNlXG5cdCAqL1xuXHRpc19zdmcgPSBmYWxzZTtcblx0LyoqIHBhcmVudCBmb3IgY3JlYXRpbmcgbm9kZSAqL1xuXHRlID0gdW5kZWZpbmVkO1xuXHQvKiogaHRtbCB0YWcgbm9kZXMgKi9cblx0biA9IHVuZGVmaW5lZDtcblx0LyoqIHRhcmdldCAqL1xuXHR0ID0gdW5kZWZpbmVkO1xuXHQvKiogYW5jaG9yICovXG5cdGEgPSB1bmRlZmluZWQ7XG5cdGNvbnN0cnVjdG9yKGlzX3N2ZyA9IGZhbHNlKSB7XG5cdFx0dGhpcy5pc19zdmcgPSBpc19zdmc7XG5cdFx0dGhpcy5lID0gdGhpcy5uID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaHRtbFxuXHQgKiBAcmV0dXJucyB7dm9pZH1cblx0ICovXG5cdGMoaHRtbCkge1xuXHRcdHRoaXMuaChodG1sKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaHRtbFxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50IHwgU1ZHRWxlbWVudH0gdGFyZ2V0XG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnQgfCBTVkdFbGVtZW50fSBhbmNob3Jcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRtKGh0bWwsIHRhcmdldCwgYW5jaG9yID0gbnVsbCkge1xuXHRcdGlmICghdGhpcy5lKSB7XG5cdFx0XHRpZiAodGhpcy5pc19zdmcpXG5cdFx0XHRcdHRoaXMuZSA9IHN2Z19lbGVtZW50KC8qKiBAdHlwZSB7a2V5b2YgU1ZHRWxlbWVudFRhZ05hbWVNYXB9ICovICh0YXJnZXQubm9kZU5hbWUpKTtcblx0XHRcdC8qKiAjNzM2NCAgdGFyZ2V0IGZvciA8dGVtcGxhdGU+IG1heSBiZSBwcm92aWRlZCBhcyAjZG9jdW1lbnQtZnJhZ21lbnQoMTEpICovIGVsc2Vcblx0XHRcdFx0dGhpcy5lID0gZWxlbWVudChcblx0XHRcdFx0XHQvKiogQHR5cGUge2tleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcH0gKi8gKFxuXHRcdFx0XHRcdFx0dGFyZ2V0Lm5vZGVUeXBlID09PSAxMSA/ICdURU1QTEFURScgOiB0YXJnZXQubm9kZU5hbWVcblx0XHRcdFx0XHQpXG5cdFx0XHRcdCk7XG5cdFx0XHR0aGlzLnQgPVxuXHRcdFx0XHR0YXJnZXQudGFnTmFtZSAhPT0gJ1RFTVBMQVRFJ1xuXHRcdFx0XHRcdD8gdGFyZ2V0XG5cdFx0XHRcdFx0OiAvKiogQHR5cGUge0hUTUxUZW1wbGF0ZUVsZW1lbnR9ICovICh0YXJnZXQpLmNvbnRlbnQ7XG5cdFx0XHR0aGlzLmMoaHRtbCk7XG5cdFx0fVxuXHRcdHRoaXMuaShhbmNob3IpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0aChodG1sKSB7XG5cdFx0dGhpcy5lLmlubmVySFRNTCA9IGh0bWw7XG5cdFx0dGhpcy5uID0gQXJyYXkuZnJvbShcblx0XHRcdHRoaXMuZS5ub2RlTmFtZSA9PT0gJ1RFTVBMQVRFJyA/IHRoaXMuZS5jb250ZW50LmNoaWxkTm9kZXMgOiB0aGlzLmUuY2hpbGROb2Rlc1xuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGkoYW5jaG9yKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm4ubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRcdGluc2VydCh0aGlzLnQsIHRoaXMubltpXSwgYW5jaG9yKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtzdHJpbmd9IGh0bWxcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRwKGh0bWwpIHtcblx0XHR0aGlzLmQoKTtcblx0XHR0aGlzLmgoaHRtbCk7XG5cdFx0dGhpcy5pKHRoaXMuYSk7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGQoKSB7XG5cdFx0dGhpcy5uLmZvckVhY2goZGV0YWNoKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSHRtbFRhZ0h5ZHJhdGlvbiBleHRlbmRzIEh0bWxUYWcge1xuXHQvKiogQHR5cGUge0VsZW1lbnRbXX0gaHlkcmF0aW9uIGNsYWltZWQgbm9kZXMgKi9cblx0bCA9IHVuZGVmaW5lZDtcblxuXHRjb25zdHJ1Y3Rvcihpc19zdmcgPSBmYWxzZSwgY2xhaW1lZF9ub2Rlcykge1xuXHRcdHN1cGVyKGlzX3N2Zyk7XG5cdFx0dGhpcy5lID0gdGhpcy5uID0gbnVsbDtcblx0XHR0aGlzLmwgPSBjbGFpbWVkX25vZGVzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0YyhodG1sKSB7XG5cdFx0aWYgKHRoaXMubCkge1xuXHRcdFx0dGhpcy5uID0gdGhpcy5sO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzdXBlci5jKGh0bWwpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJucyB7dm9pZH0gKi9cblx0aShhbmNob3IpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubi5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdFx0aW5zZXJ0X2h5ZHJhdGlvbih0aGlzLnQsIHRoaXMubltpXSwgYW5jaG9yKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05hbWVkTm9kZU1hcH0gYXR0cmlidXRlc1xuICogQHJldHVybnMge3t9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXR0cmlidXRlX3RvX29iamVjdChhdHRyaWJ1dGVzKSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiBhdHRyaWJ1dGVzKSB7XG5cdFx0cmVzdWx0W2F0dHJpYnV0ZS5uYW1lXSA9IGF0dHJpYnV0ZS52YWx1ZTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG5jb25zdCBlc2NhcGVkID0ge1xuXHQnXCInOiAnJnF1b3Q7Jyxcblx0JyYnOiAnJmFtcDsnLFxuXHQnPCc6ICcmbHQ7J1xufTtcblxuY29uc3QgcmVnZXhfYXR0cmlidXRlX2NoYXJhY3RlcnNfdG9fZXNjYXBlID0gL1tcIiY8XS9nO1xuXG4vKipcbiAqIE5vdGUgdGhhdCB0aGUgYXR0cmlidXRlIGl0c2VsZiBzaG91bGQgYmUgc3Vycm91bmRlZCBpbiBkb3VibGUgcXVvdGVzXG4gKiBAcGFyYW0ge2FueX0gYXR0cmlidXRlXG4gKi9cbmZ1bmN0aW9uIGVzY2FwZV9hdHRyaWJ1dGUoYXR0cmlidXRlKSB7XG5cdHJldHVybiBTdHJpbmcoYXR0cmlidXRlKS5yZXBsYWNlKHJlZ2V4X2F0dHJpYnV0ZV9jaGFyYWN0ZXJzX3RvX2VzY2FwZSwgKG1hdGNoKSA9PiBlc2NhcGVkW21hdGNoXSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fSBhdHRyaWJ1dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpbmdpZnlfc3ByZWFkKGF0dHJpYnV0ZXMpIHtcblx0bGV0IHN0ciA9ICcgJztcblx0Zm9yIChjb25zdCBrZXkgaW4gYXR0cmlidXRlcykge1xuXHRcdGlmIChhdHRyaWJ1dGVzW2tleV0gIT0gbnVsbCkge1xuXHRcdFx0c3RyICs9IGAke2tleX09XCIke2VzY2FwZV9hdHRyaWJ1dGUoYXR0cmlidXRlc1trZXldKX1cIiBgO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBzdHI7XG59XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge3t9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X2N1c3RvbV9lbGVtZW50c19zbG90cyhlbGVtZW50KSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRlbGVtZW50LmNoaWxkTm9kZXMuZm9yRWFjaChcblx0XHQvKiogQHBhcmFtIHtFbGVtZW50fSBub2RlICovIChub2RlKSA9PiB7XG5cdFx0XHRyZXN1bHRbbm9kZS5zbG90IHx8ICdkZWZhdWx0J10gPSB0cnVlO1xuXHRcdH1cblx0KTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN0cnVjdF9zdmVsdGVfY29tcG9uZW50KGNvbXBvbmVudCwgcHJvcHMpIHtcblx0cmV0dXJuIG5ldyBjb21wb25lbnQocHJvcHMpO1xufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtOb2RlICYge1xuICogXHRjbGFpbV9vcmRlcj86IG51bWJlcjtcbiAqIFx0aHlkcmF0ZV9pbml0PzogdHJ1ZTtcbiAqIFx0YWN0dWFsX2VuZF9jaGlsZD86IE5vZGVFeDtcbiAqIFx0Y2hpbGROb2RlczogTm9kZUxpc3RPZjxOb2RlRXg+O1xuICogfX0gTm9kZUV4XG4gKi9cblxuLyoqIEB0eXBlZGVmIHtDaGlsZE5vZGUgJiBOb2RlRXh9IENoaWxkTm9kZUV4ICovXG5cbi8qKiBAdHlwZWRlZiB7Tm9kZUV4ICYgeyBjbGFpbV9vcmRlcjogbnVtYmVyIH19IE5vZGVFeDIgKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7Q2hpbGROb2RlRXhbXSAmIHtcbiAqIFx0Y2xhaW1faW5mbz86IHtcbiAqIFx0XHRsYXN0X2luZGV4OiBudW1iZXI7XG4gKiBcdFx0dG90YWxfY2xhaW1lZDogbnVtYmVyO1xuICogXHR9O1xuICogfX0gQ2hpbGROb2RlQXJyYXlcbiAqL1xuIiwgImltcG9ydCB7IGN1c3RvbV9ldmVudCB9IGZyb20gJy4vZG9tLmpzJztcblxuZXhwb3J0IGxldCBjdXJyZW50X2NvbXBvbmVudDtcblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldF9jdXJyZW50X2NvbXBvbmVudChjb21wb25lbnQpIHtcblx0Y3VycmVudF9jb21wb25lbnQgPSBjb21wb25lbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRfY3VycmVudF9jb21wb25lbnQoKSB7XG5cdGlmICghY3VycmVudF9jb21wb25lbnQpIHRocm93IG5ldyBFcnJvcignRnVuY3Rpb24gY2FsbGVkIG91dHNpZGUgY29tcG9uZW50IGluaXRpYWxpemF0aW9uJyk7XG5cdHJldHVybiBjdXJyZW50X2NvbXBvbmVudDtcbn1cblxuLyoqXG4gKiBTY2hlZHVsZXMgYSBjYWxsYmFjayB0byBydW4gaW1tZWRpYXRlbHkgYmVmb3JlIHRoZSBjb21wb25lbnQgaXMgdXBkYXRlZCBhZnRlciBhbnkgc3RhdGUgY2hhbmdlLlxuICpcbiAqIFRoZSBmaXJzdCB0aW1lIHRoZSBjYWxsYmFjayBydW5zIHdpbGwgYmUgYmVmb3JlIHRoZSBpbml0aWFsIGBvbk1vdW50YFxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNiZWZvcmV1cGRhdGVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiZWZvcmVVcGRhdGUoZm4pIHtcblx0Z2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuYmVmb3JlX3VwZGF0ZS5wdXNoKGZuKTtcbn1cblxuLyoqXG4gKiBUaGUgYG9uTW91bnRgIGZ1bmN0aW9uIHNjaGVkdWxlcyBhIGNhbGxiYWNrIHRvIHJ1biBhcyBzb29uIGFzIHRoZSBjb21wb25lbnQgaGFzIGJlZW4gbW91bnRlZCB0byB0aGUgRE9NLlxuICogSXQgbXVzdCBiZSBjYWxsZWQgZHVyaW5nIHRoZSBjb21wb25lbnQncyBpbml0aWFsaXNhdGlvbiAoYnV0IGRvZXNuJ3QgbmVlZCB0byBsaXZlICppbnNpZGUqIHRoZSBjb21wb25lbnQ7XG4gKiBpdCBjYW4gYmUgY2FsbGVkIGZyb20gYW4gZXh0ZXJuYWwgbW9kdWxlKS5cbiAqXG4gKiBJZiBhIGZ1bmN0aW9uIGlzIHJldHVybmVkIF9zeW5jaHJvbm91c2x5XyBmcm9tIGBvbk1vdW50YCwgaXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgY29tcG9uZW50IGlzIHVubW91bnRlZC5cbiAqXG4gKiBgb25Nb3VudGAgZG9lcyBub3QgcnVuIGluc2lkZSBhIFtzZXJ2ZXItc2lkZSBjb21wb25lbnRdKGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzI3J1bi10aW1lLXNlcnZlci1zaWRlLWNvbXBvbmVudC1hcGkpLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNvbm1vdW50XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHsoKSA9PiBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLk5vdEZ1bmN0aW9uPFQ+IHwgUHJvbWlzZTxpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLk5vdEZ1bmN0aW9uPFQ+PiB8ICgoKSA9PiBhbnkpfSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbk1vdW50KGZuKSB7XG5cdGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLm9uX21vdW50LnB1c2goZm4pO1xufVxuXG4vKipcbiAqIFNjaGVkdWxlcyBhIGNhbGxiYWNrIHRvIHJ1biBpbW1lZGlhdGVseSBhZnRlciB0aGUgY29tcG9uZW50IGhhcyBiZWVuIHVwZGF0ZWQuXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIHJ1bnMgd2lsbCBiZSBhZnRlciB0aGUgaW5pdGlhbCBgb25Nb3VudGBcbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUjYWZ0ZXJ1cGRhdGVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclVwZGF0ZShmbikge1xuXHRnZXRfY3VycmVudF9jb21wb25lbnQoKS4kJC5hZnRlcl91cGRhdGUucHVzaChmbik7XG59XG5cbi8qKlxuICogU2NoZWR1bGVzIGEgY2FsbGJhY2sgdG8gcnVuIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgY29tcG9uZW50IGlzIHVubW91bnRlZC5cbiAqXG4gKiBPdXQgb2YgYG9uTW91bnRgLCBgYmVmb3JlVXBkYXRlYCwgYGFmdGVyVXBkYXRlYCBhbmQgYG9uRGVzdHJveWAsIHRoaXMgaXMgdGhlXG4gKiBvbmx5IG9uZSB0aGF0IHJ1bnMgaW5zaWRlIGEgc2VydmVyLXNpZGUgY29tcG9uZW50LlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNvbmRlc3Ryb3lcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkRlc3Ryb3koZm4pIHtcblx0Z2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQub25fZGVzdHJveS5wdXNoKGZuKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGV2ZW50IGRpc3BhdGNoZXIgdGhhdCBjYW4gYmUgdXNlZCB0byBkaXNwYXRjaCBbY29tcG9uZW50IGV2ZW50c10oaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3MjdGVtcGxhdGUtc3ludGF4LWNvbXBvbmVudC1kaXJlY3RpdmVzLW9uLWV2ZW50bmFtZSkuXG4gKiBFdmVudCBkaXNwYXRjaGVycyBhcmUgZnVuY3Rpb25zIHRoYXQgY2FuIHRha2UgdHdvIGFyZ3VtZW50czogYG5hbWVgIGFuZCBgZGV0YWlsYC5cbiAqXG4gKiBDb21wb25lbnQgZXZlbnRzIGNyZWF0ZWQgd2l0aCBgY3JlYXRlRXZlbnREaXNwYXRjaGVyYCBjcmVhdGUgYVxuICogW0N1c3RvbUV2ZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ3VzdG9tRXZlbnQpLlxuICogVGhlc2UgZXZlbnRzIGRvIG5vdCBbYnViYmxlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL0xlYXJuL0phdmFTY3JpcHQvQnVpbGRpbmdfYmxvY2tzL0V2ZW50cyNFdmVudF9idWJibGluZ19hbmRfY2FwdHVyZSkuXG4gKiBUaGUgYGRldGFpbGAgYXJndW1lbnQgY29ycmVzcG9uZHMgdG8gdGhlIFtDdXN0b21FdmVudC5kZXRhaWxdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9DdXN0b21FdmVudC9kZXRhaWwpXG4gKiBwcm9wZXJ0eSBhbmQgY2FuIGNvbnRhaW4gYW55IHR5cGUgb2YgZGF0YS5cbiAqXG4gKiBUaGUgZXZlbnQgZGlzcGF0Y2hlciBjYW4gYmUgdHlwZWQgdG8gbmFycm93IHRoZSBhbGxvd2VkIGV2ZW50IG5hbWVzIGFuZCB0aGUgdHlwZSBvZiB0aGUgYGRldGFpbGAgYXJndW1lbnQ6XG4gKiBgYGB0c1xuICogY29uc3QgZGlzcGF0Y2ggPSBjcmVhdGVFdmVudERpc3BhdGNoZXI8e1xuICogIGxvYWRlZDogbmV2ZXI7IC8vIGRvZXMgbm90IHRha2UgYSBkZXRhaWwgYXJndW1lbnRcbiAqICBjaGFuZ2U6IHN0cmluZzsgLy8gdGFrZXMgYSBkZXRhaWwgYXJndW1lbnQgb2YgdHlwZSBzdHJpbmcsIHdoaWNoIGlzIHJlcXVpcmVkXG4gKiAgb3B0aW9uYWw6IG51bWJlciB8IG51bGw7IC8vIHRha2VzIGFuIG9wdGlvbmFsIGRldGFpbCBhcmd1bWVudCBvZiB0eXBlIG51bWJlclxuICogfT4oKTtcbiAqIGBgYFxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNjcmVhdGVldmVudGRpc3BhdGNoZXJcbiAqIEB0ZW1wbGF0ZSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW0V2ZW50TWFwPWFueV1cbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuRXZlbnREaXNwYXRjaGVyPEV2ZW50TWFwPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUV2ZW50RGlzcGF0Y2hlcigpIHtcblx0Y29uc3QgY29tcG9uZW50ID0gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCk7XG5cdHJldHVybiAodHlwZSwgZGV0YWlsLCB7IGNhbmNlbGFibGUgPSBmYWxzZSB9ID0ge30pID0+IHtcblx0XHRjb25zdCBjYWxsYmFja3MgPSBjb21wb25lbnQuJCQuY2FsbGJhY2tzW3R5cGVdO1xuXHRcdGlmIChjYWxsYmFja3MpIHtcblx0XHRcdC8vIFRPRE8gYXJlIHRoZXJlIHNpdHVhdGlvbnMgd2hlcmUgZXZlbnRzIGNvdWxkIGJlIGRpc3BhdGNoZWRcblx0XHRcdC8vIGluIGEgc2VydmVyIChub24tRE9NKSBlbnZpcm9ubWVudD9cblx0XHRcdGNvbnN0IGV2ZW50ID0gY3VzdG9tX2V2ZW50KC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodHlwZSksIGRldGFpbCwgeyBjYW5jZWxhYmxlIH0pO1xuXHRcdFx0Y2FsbGJhY2tzLnNsaWNlKCkuZm9yRWFjaCgoZm4pID0+IHtcblx0XHRcdFx0Zm4uY2FsbChjb21wb25lbnQsIGV2ZW50KTtcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuICFldmVudC5kZWZhdWx0UHJldmVudGVkO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcbn1cblxuLyoqXG4gKiBBc3NvY2lhdGVzIGFuIGFyYml0cmFyeSBgY29udGV4dGAgb2JqZWN0IHdpdGggdGhlIGN1cnJlbnQgY29tcG9uZW50IGFuZCB0aGUgc3BlY2lmaWVkIGBrZXlgXG4gKiBhbmQgcmV0dXJucyB0aGF0IG9iamVjdC4gVGhlIGNvbnRleHQgaXMgdGhlbiBhdmFpbGFibGUgdG8gY2hpbGRyZW4gb2YgdGhlIGNvbXBvbmVudFxuICogKGluY2x1ZGluZyBzbG90dGVkIGNvbnRlbnQpIHdpdGggYGdldENvbnRleHRgLlxuICpcbiAqIExpa2UgbGlmZWN5Y2xlIGZ1bmN0aW9ucywgdGhpcyBtdXN0IGJlIGNhbGxlZCBkdXJpbmcgY29tcG9uZW50IGluaXRpYWxpc2F0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNzZXRjb250ZXh0XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHBhcmFtIHtUfSBjb250ZXh0XG4gKiBAcmV0dXJucyB7VH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldENvbnRleHQoa2V5LCBjb250ZXh0KSB7XG5cdGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLmNvbnRleHQuc2V0KGtleSwgY29udGV4dCk7XG5cdHJldHVybiBjb250ZXh0O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgY29udGV4dCB0aGF0IGJlbG9uZ3MgdG8gdGhlIGNsb3Nlc3QgcGFyZW50IGNvbXBvbmVudCB3aXRoIHRoZSBzcGVjaWZpZWQgYGtleWAuXG4gKiBNdXN0IGJlIGNhbGxlZCBkdXJpbmcgY29tcG9uZW50IGluaXRpYWxpc2F0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNnZXRjb250ZXh0XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHJldHVybnMge1R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250ZXh0KGtleSkge1xuXHRyZXR1cm4gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuY29udGV4dC5nZXQoa2V5KTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIHdob2xlIGNvbnRleHQgbWFwIHRoYXQgYmVsb25ncyB0byB0aGUgY2xvc2VzdCBwYXJlbnQgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgZHVyaW5nIGNvbXBvbmVudCBpbml0aWFsaXNhdGlvbi4gVXNlZnVsLCBmb3IgZXhhbXBsZSwgaWYgeW91XG4gKiBwcm9ncmFtbWF0aWNhbGx5IGNyZWF0ZSBhIGNvbXBvbmVudCBhbmQgd2FudCB0byBwYXNzIHRoZSBleGlzdGluZyBjb250ZXh0IHRvIGl0LlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNnZXRhbGxjb250ZXh0c1xuICogQHRlbXBsYXRlIHtNYXA8YW55LCBhbnk+fSBbVD1NYXA8YW55LCBhbnk+XVxuICogQHJldHVybnMge1R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbGxDb250ZXh0cygpIHtcblx0cmV0dXJuIGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLmNvbnRleHQ7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBnaXZlbiBga2V5YCBoYXMgYmVlbiBzZXQgaW4gdGhlIGNvbnRleHQgb2YgYSBwYXJlbnQgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgZHVyaW5nIGNvbXBvbmVudCBpbml0aWFsaXNhdGlvbi5cbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUjaGFzY29udGV4dFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNDb250ZXh0KGtleSkge1xuXHRyZXR1cm4gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuY29udGV4dC5oYXMoa2V5KTtcbn1cblxuLy8gVE9ETyBmaWd1cmUgb3V0IGlmIHdlIHN0aWxsIHdhbnQgdG8gc3VwcG9ydFxuLy8gc2hvcnRoYW5kIGV2ZW50cywgb3IgaWYgd2Ugd2FudCB0byBpbXBsZW1lbnRcbi8vIGEgcmVhbCBidWJibGluZyBtZWNoYW5pc21cbi8qKlxuICogQHBhcmFtIGNvbXBvbmVudFxuICogQHBhcmFtIGV2ZW50XG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1YmJsZShjb21wb25lbnQsIGV2ZW50KSB7XG5cdGNvbnN0IGNhbGxiYWNrcyA9IGNvbXBvbmVudC4kJC5jYWxsYmFja3NbZXZlbnQudHlwZV07XG5cdGlmIChjYWxsYmFja3MpIHtcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0Y2FsbGJhY2tzLnNsaWNlKCkuZm9yRWFjaCgoZm4pID0+IGZuLmNhbGwodGhpcywgZXZlbnQpKTtcblx0fVxufVxuIiwgImltcG9ydCB7IHJ1bl9hbGwgfSBmcm9tICcuL3V0aWxzLmpzJztcbmltcG9ydCB7IGN1cnJlbnRfY29tcG9uZW50LCBzZXRfY3VycmVudF9jb21wb25lbnQgfSBmcm9tICcuL2xpZmVjeWNsZS5qcyc7XG5cbmV4cG9ydCBjb25zdCBkaXJ0eV9jb21wb25lbnRzID0gW107XG5leHBvcnQgY29uc3QgaW50cm9zID0geyBlbmFibGVkOiBmYWxzZSB9O1xuZXhwb3J0IGNvbnN0IGJpbmRpbmdfY2FsbGJhY2tzID0gW107XG5cbmxldCByZW5kZXJfY2FsbGJhY2tzID0gW107XG5cbmNvbnN0IGZsdXNoX2NhbGxiYWNrcyA9IFtdO1xuXG5jb25zdCByZXNvbHZlZF9wcm9taXNlID0gLyogQF9fUFVSRV9fICovIFByb21pc2UucmVzb2x2ZSgpO1xuXG5sZXQgdXBkYXRlX3NjaGVkdWxlZCA9IGZhbHNlO1xuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2NoZWR1bGVfdXBkYXRlKCkge1xuXHRpZiAoIXVwZGF0ZV9zY2hlZHVsZWQpIHtcblx0XHR1cGRhdGVfc2NoZWR1bGVkID0gdHJ1ZTtcblx0XHRyZXNvbHZlZF9wcm9taXNlLnRoZW4oZmx1c2gpO1xuXHR9XG59XG5cbi8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWNrKCkge1xuXHRzY2hlZHVsZV91cGRhdGUoKTtcblx0cmV0dXJuIHJlc29sdmVkX3Byb21pc2U7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfcmVuZGVyX2NhbGxiYWNrKGZuKSB7XG5cdHJlbmRlcl9jYWxsYmFja3MucHVzaChmbik7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfZmx1c2hfY2FsbGJhY2soZm4pIHtcblx0Zmx1c2hfY2FsbGJhY2tzLnB1c2goZm4pO1xufVxuXG4vLyBmbHVzaCgpIGNhbGxzIGNhbGxiYWNrcyBpbiB0aGlzIG9yZGVyOlxuLy8gMS4gQWxsIGJlZm9yZVVwZGF0ZSBjYWxsYmFja3MsIGluIG9yZGVyOiBwYXJlbnRzIGJlZm9yZSBjaGlsZHJlblxuLy8gMi4gQWxsIGJpbmQ6dGhpcyBjYWxsYmFja3MsIGluIHJldmVyc2Ugb3JkZXI6IGNoaWxkcmVuIGJlZm9yZSBwYXJlbnRzLlxuLy8gMy4gQWxsIGFmdGVyVXBkYXRlIGNhbGxiYWNrcywgaW4gb3JkZXI6IHBhcmVudHMgYmVmb3JlIGNoaWxkcmVuLiBFWENFUFRcbi8vICAgIGZvciBhZnRlclVwZGF0ZXMgY2FsbGVkIGR1cmluZyB0aGUgaW5pdGlhbCBvbk1vdW50LCB3aGljaCBhcmUgY2FsbGVkIGluXG4vLyAgICByZXZlcnNlIG9yZGVyOiBjaGlsZHJlbiBiZWZvcmUgcGFyZW50cy5cbi8vIFNpbmNlIGNhbGxiYWNrcyBtaWdodCB1cGRhdGUgY29tcG9uZW50IHZhbHVlcywgd2hpY2ggY291bGQgdHJpZ2dlciBhbm90aGVyXG4vLyBjYWxsIHRvIGZsdXNoKCksIHRoZSBmb2xsb3dpbmcgc3RlcHMgZ3VhcmQgYWdhaW5zdCB0aGlzOlxuLy8gMS4gRHVyaW5nIGJlZm9yZVVwZGF0ZSwgYW55IHVwZGF0ZWQgY29tcG9uZW50cyB3aWxsIGJlIGFkZGVkIHRvIHRoZVxuLy8gICAgZGlydHlfY29tcG9uZW50cyBhcnJheSBhbmQgd2lsbCBjYXVzZSBhIHJlZW50cmFudCBjYWxsIHRvIGZsdXNoKCkuIEJlY2F1c2Vcbi8vICAgIHRoZSBmbHVzaCBpbmRleCBpcyBrZXB0IG91dHNpZGUgdGhlIGZ1bmN0aW9uLCB0aGUgcmVlbnRyYW50IGNhbGwgd2lsbCBwaWNrXG4vLyAgICB1cCB3aGVyZSB0aGUgZWFybGllciBjYWxsIGxlZnQgb2ZmIGFuZCBnbyB0aHJvdWdoIGFsbCBkaXJ0eSBjb21wb25lbnRzLiBUaGVcbi8vICAgIGN1cnJlbnRfY29tcG9uZW50IHZhbHVlIGlzIHNhdmVkIGFuZCByZXN0b3JlZCBzbyB0aGF0IHRoZSByZWVudHJhbnQgY2FsbCB3aWxsXG4vLyAgICBub3QgaW50ZXJmZXJlIHdpdGggdGhlIFwicGFyZW50XCIgZmx1c2goKSBjYWxsLlxuLy8gMi4gYmluZDp0aGlzIGNhbGxiYWNrcyBjYW5ub3QgdHJpZ2dlciBuZXcgZmx1c2goKSBjYWxscy5cbi8vIDMuIER1cmluZyBhZnRlclVwZGF0ZSwgYW55IHVwZGF0ZWQgY29tcG9uZW50cyB3aWxsIE5PVCBoYXZlIHRoZWlyIGFmdGVyVXBkYXRlXG4vLyAgICBjYWxsYmFjayBjYWxsZWQgYSBzZWNvbmQgdGltZTsgdGhlIHNlZW5fY2FsbGJhY2tzIHNldCwgb3V0c2lkZSB0aGUgZmx1c2goKVxuLy8gICAgZnVuY3Rpb24sIGd1YXJhbnRlZXMgdGhpcyBiZWhhdmlvci5cbmNvbnN0IHNlZW5fY2FsbGJhY2tzID0gbmV3IFNldCgpO1xuXG5sZXQgZmx1c2hpZHggPSAwOyAvLyBEbyAqbm90KiBtb3ZlIHRoaXMgaW5zaWRlIHRoZSBmbHVzaCgpIGZ1bmN0aW9uXG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaCgpIHtcblx0Ly8gRG8gbm90IHJlZW50ZXIgZmx1c2ggd2hpbGUgZGlydHkgY29tcG9uZW50cyBhcmUgdXBkYXRlZCwgYXMgdGhpcyBjYW5cblx0Ly8gcmVzdWx0IGluIGFuIGluZmluaXRlIGxvb3AuIEluc3RlYWQsIGxldCB0aGUgaW5uZXIgZmx1c2ggaGFuZGxlIGl0LlxuXHQvLyBSZWVudHJhbmN5IGlzIG9rIGFmdGVyd2FyZHMgZm9yIGJpbmRpbmdzIGV0Yy5cblx0aWYgKGZsdXNoaWR4ICE9PSAwKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHNhdmVkX2NvbXBvbmVudCA9IGN1cnJlbnRfY29tcG9uZW50O1xuXHRkbyB7XG5cdFx0Ly8gZmlyc3QsIGNhbGwgYmVmb3JlVXBkYXRlIGZ1bmN0aW9uc1xuXHRcdC8vIGFuZCB1cGRhdGUgY29tcG9uZW50c1xuXHRcdHRyeSB7XG5cdFx0XHR3aGlsZSAoZmx1c2hpZHggPCBkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCkge1xuXHRcdFx0XHRjb25zdCBjb21wb25lbnQgPSBkaXJ0eV9jb21wb25lbnRzW2ZsdXNoaWR4XTtcblx0XHRcdFx0Zmx1c2hpZHgrKztcblx0XHRcdFx0c2V0X2N1cnJlbnRfY29tcG9uZW50KGNvbXBvbmVudCk7XG5cdFx0XHRcdHVwZGF0ZShjb21wb25lbnQuJCQpO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdC8vIHJlc2V0IGRpcnR5IHN0YXRlIHRvIG5vdCBlbmQgdXAgaW4gYSBkZWFkbG9ja2VkIHN0YXRlIGFuZCB0aGVuIHJldGhyb3dcblx0XHRcdGRpcnR5X2NvbXBvbmVudHMubGVuZ3RoID0gMDtcblx0XHRcdGZsdXNoaWR4ID0gMDtcblx0XHRcdHRocm93IGU7XG5cdFx0fVxuXHRcdHNldF9jdXJyZW50X2NvbXBvbmVudChudWxsKTtcblx0XHRkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCA9IDA7XG5cdFx0Zmx1c2hpZHggPSAwO1xuXHRcdHdoaWxlIChiaW5kaW5nX2NhbGxiYWNrcy5sZW5ndGgpIGJpbmRpbmdfY2FsbGJhY2tzLnBvcCgpKCk7XG5cdFx0Ly8gdGhlbiwgb25jZSBjb21wb25lbnRzIGFyZSB1cGRhdGVkLCBjYWxsXG5cdFx0Ly8gYWZ0ZXJVcGRhdGUgZnVuY3Rpb25zLiBUaGlzIG1heSBjYXVzZVxuXHRcdC8vIHN1YnNlcXVlbnQgdXBkYXRlcy4uLlxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcmVuZGVyX2NhbGxiYWNrcy5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdFx0Y29uc3QgY2FsbGJhY2sgPSByZW5kZXJfY2FsbGJhY2tzW2ldO1xuXHRcdFx0aWYgKCFzZWVuX2NhbGxiYWNrcy5oYXMoY2FsbGJhY2spKSB7XG5cdFx0XHRcdC8vIC4uLnNvIGd1YXJkIGFnYWluc3QgaW5maW5pdGUgbG9vcHNcblx0XHRcdFx0c2Vlbl9jYWxsYmFja3MuYWRkKGNhbGxiYWNrKTtcblx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVuZGVyX2NhbGxiYWNrcy5sZW5ndGggPSAwO1xuXHR9IHdoaWxlIChkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCk7XG5cdHdoaWxlIChmbHVzaF9jYWxsYmFja3MubGVuZ3RoKSB7XG5cdFx0Zmx1c2hfY2FsbGJhY2tzLnBvcCgpKCk7XG5cdH1cblx0dXBkYXRlX3NjaGVkdWxlZCA9IGZhbHNlO1xuXHRzZWVuX2NhbGxiYWNrcy5jbGVhcigpO1xuXHRzZXRfY3VycmVudF9jb21wb25lbnQoc2F2ZWRfY29tcG9uZW50KTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZnVuY3Rpb24gdXBkYXRlKCQkKSB7XG5cdGlmICgkJC5mcmFnbWVudCAhPT0gbnVsbCkge1xuXHRcdCQkLnVwZGF0ZSgpO1xuXHRcdHJ1bl9hbGwoJCQuYmVmb3JlX3VwZGF0ZSk7XG5cdFx0Y29uc3QgZGlydHkgPSAkJC5kaXJ0eTtcblx0XHQkJC5kaXJ0eSA9IFstMV07XG5cdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQucCgkJC5jdHgsIGRpcnR5KTtcblx0XHQkJC5hZnRlcl91cGRhdGUuZm9yRWFjaChhZGRfcmVuZGVyX2NhbGxiYWNrKTtcblx0fVxufVxuXG4vKipcbiAqIFVzZWZ1bCBmb3IgZXhhbXBsZSB0byBleGVjdXRlIHJlbWFpbmluZyBgYWZ0ZXJVcGRhdGVgIGNhbGxiYWNrcyBiZWZvcmUgZXhlY3V0aW5nIGBkZXN0cm95YC5cbiAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gZm5zXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsdXNoX3JlbmRlcl9jYWxsYmFja3MoZm5zKSB7XG5cdGNvbnN0IGZpbHRlcmVkID0gW107XG5cdGNvbnN0IHRhcmdldHMgPSBbXTtcblx0cmVuZGVyX2NhbGxiYWNrcy5mb3JFYWNoKChjKSA9PiAoZm5zLmluZGV4T2YoYykgPT09IC0xID8gZmlsdGVyZWQucHVzaChjKSA6IHRhcmdldHMucHVzaChjKSkpO1xuXHR0YXJnZXRzLmZvckVhY2goKGMpID0+IGMoKSk7XG5cdHJlbmRlcl9jYWxsYmFja3MgPSBmaWx0ZXJlZDtcbn1cbiIsICJpbXBvcnQgeyBpZGVudGl0eSBhcyBsaW5lYXIsIGlzX2Z1bmN0aW9uLCBub29wLCBydW5fYWxsIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyBub3cgfSBmcm9tICcuL2Vudmlyb25tZW50LmpzJztcbmltcG9ydCB7IGxvb3AgfSBmcm9tICcuL2xvb3AuanMnO1xuaW1wb3J0IHsgY3JlYXRlX3J1bGUsIGRlbGV0ZV9ydWxlIH0gZnJvbSAnLi9zdHlsZV9tYW5hZ2VyLmpzJztcbmltcG9ydCB7IGN1c3RvbV9ldmVudCB9IGZyb20gJy4vZG9tLmpzJztcbmltcG9ydCB7IGFkZF9yZW5kZXJfY2FsbGJhY2sgfSBmcm9tICcuL3NjaGVkdWxlci5qcyc7XG5cbi8qKlxuICogQHR5cGUge1Byb21pc2U8dm9pZD4gfCBudWxsfVxuICovXG5sZXQgcHJvbWlzZTtcblxuLyoqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZnVuY3Rpb24gd2FpdCgpIHtcblx0aWYgKCFwcm9taXNlKSB7XG5cdFx0cHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdHByb21pc2UudGhlbigoKSA9PiB7XG5cdFx0XHRwcm9taXNlID0gbnVsbDtcblx0XHR9KTtcblx0fVxuXHRyZXR1cm4gcHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGVcbiAqIEBwYXJhbSB7SU5UUk8gfCBPVVRSTyB8IGJvb2xlYW59IGRpcmVjdGlvblxuICogQHBhcmFtIHsnc3RhcnQnIHwgJ2VuZCd9IGtpbmRcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBkaXNwYXRjaChub2RlLCBkaXJlY3Rpb24sIGtpbmQpIHtcblx0bm9kZS5kaXNwYXRjaEV2ZW50KGN1c3RvbV9ldmVudChgJHtkaXJlY3Rpb24gPyAnaW50cm8nIDogJ291dHJvJ30ke2tpbmR9YCkpO1xufVxuXG5jb25zdCBvdXRyb2luZyA9IG5ldyBTZXQoKTtcblxuLyoqXG4gKiBAdHlwZSB7T3V0cm99XG4gKi9cbmxldCBvdXRyb3M7XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBfb3V0cm9zKCkge1xuXHRvdXRyb3MgPSB7XG5cdFx0cjogMCxcblx0XHRjOiBbXSxcblx0XHRwOiBvdXRyb3MgLy8gcGFyZW50IGdyb3VwXG5cdH07XG59XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tfb3V0cm9zKCkge1xuXHRpZiAoIW91dHJvcy5yKSB7XG5cdFx0cnVuX2FsbChvdXRyb3MuYyk7XG5cdH1cblx0b3V0cm9zID0gb3V0cm9zLnA7XG59XG5cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkZyYWdtZW50fSBibG9ja1xuICogQHBhcmFtIHswIHwgMX0gW2xvY2FsXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2l0aW9uX2luKGJsb2NrLCBsb2NhbCkge1xuXHRpZiAoYmxvY2sgJiYgYmxvY2suaSkge1xuXHRcdG91dHJvaW5nLmRlbGV0ZShibG9jayk7XG5cdFx0YmxvY2suaShsb2NhbCk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wcml2YXRlLmpzJykuRnJhZ21lbnR9IGJsb2NrXG4gKiBAcGFyYW0gezAgfCAxfSBsb2NhbFxuICogQHBhcmFtIHswIHwgMX0gW2RldGFjaF1cbiAqIEBwYXJhbSB7KCkgPT4gdm9pZH0gW2NhbGxiYWNrXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2l0aW9uX291dChibG9jaywgbG9jYWwsIGRldGFjaCwgY2FsbGJhY2spIHtcblx0aWYgKGJsb2NrICYmIGJsb2NrLm8pIHtcblx0XHRpZiAob3V0cm9pbmcuaGFzKGJsb2NrKSkgcmV0dXJuO1xuXHRcdG91dHJvaW5nLmFkZChibG9jayk7XG5cdFx0b3V0cm9zLmMucHVzaCgoKSA9PiB7XG5cdFx0XHRvdXRyb2luZy5kZWxldGUoYmxvY2spO1xuXHRcdFx0aWYgKGNhbGxiYWNrKSB7XG5cdFx0XHRcdGlmIChkZXRhY2gpIGJsb2NrLmQoMSk7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0YmxvY2subyhsb2NhbCk7XG5cdH0gZWxzZSBpZiAoY2FsbGJhY2spIHtcblx0XHRjYWxsYmFjaygpO1xuXHR9XG59XG5cbi8qKlxuICogQHR5cGUge2ltcG9ydCgnLi4vdHJhbnNpdGlvbi9wdWJsaWMuanMnKS5UcmFuc2l0aW9uQ29uZmlnfVxuICovXG5jb25zdCBudWxsX3RyYW5zaXRpb24gPSB7IGR1cmF0aW9uOiAwIH07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50ICYgRWxlbWVudENTU0lubGluZVN0eWxlfSBub2RlXG4gKiBAcGFyYW0ge1RyYW5zaXRpb25Gbn0gZm5cbiAqIEBwYXJhbSB7YW55fSBwYXJhbXNcbiAqIEByZXR1cm5zIHt7IHN0YXJ0KCk6IHZvaWQ7IGludmFsaWRhdGUoKTogdm9pZDsgZW5kKCk6IHZvaWQ7IH19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfaW5fdHJhbnNpdGlvbihub2RlLCBmbiwgcGFyYW1zKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7VHJhbnNpdGlvbk9wdGlvbnN9ICovXG5cdGNvbnN0IG9wdGlvbnMgPSB7IGRpcmVjdGlvbjogJ2luJyB9O1xuXHRsZXQgY29uZmlnID0gZm4obm9kZSwgcGFyYW1zLCBvcHRpb25zKTtcblx0bGV0IHJ1bm5pbmcgPSBmYWxzZTtcblx0bGV0IGFuaW1hdGlvbl9uYW1lO1xuXHRsZXQgdGFzaztcblx0bGV0IHVpZCA9IDA7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBjbGVhbnVwKCkge1xuXHRcdGlmIChhbmltYXRpb25fbmFtZSkgZGVsZXRlX3J1bGUobm9kZSwgYW5pbWF0aW9uX25hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBnbygpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cdFx0aWYgKGNzcykgYW5pbWF0aW9uX25hbWUgPSBjcmVhdGVfcnVsZShub2RlLCAwLCAxLCBkdXJhdGlvbiwgZGVsYXksIGVhc2luZywgY3NzLCB1aWQrKyk7XG5cdFx0dGljaygwLCAxKTtcblx0XHRjb25zdCBzdGFydF90aW1lID0gbm93KCkgKyBkZWxheTtcblx0XHRjb25zdCBlbmRfdGltZSA9IHN0YXJ0X3RpbWUgKyBkdXJhdGlvbjtcblx0XHRpZiAodGFzaykgdGFzay5hYm9ydCgpO1xuXHRcdHJ1bm5pbmcgPSB0cnVlO1xuXHRcdGFkZF9yZW5kZXJfY2FsbGJhY2soKCkgPT4gZGlzcGF0Y2gobm9kZSwgdHJ1ZSwgJ3N0YXJ0JykpO1xuXHRcdHRhc2sgPSBsb29wKChub3cpID0+IHtcblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChub3cgPj0gZW5kX3RpbWUpIHtcblx0XHRcdFx0XHR0aWNrKDEsIDApO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIHRydWUsICdlbmQnKTtcblx0XHRcdFx0XHRjbGVhbnVwKCk7XG5cdFx0XHRcdFx0cmV0dXJuIChydW5uaW5nID0gZmFsc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChub3cgPj0gc3RhcnRfdGltZSkge1xuXHRcdFx0XHRcdGNvbnN0IHQgPSBlYXNpbmcoKG5vdyAtIHN0YXJ0X3RpbWUpIC8gZHVyYXRpb24pO1xuXHRcdFx0XHRcdHRpY2sodCwgMSAtIHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcnVubmluZztcblx0XHR9KTtcblx0fVxuXHRsZXQgc3RhcnRlZCA9IGZhbHNlO1xuXHRyZXR1cm4ge1xuXHRcdHN0YXJ0KCkge1xuXHRcdFx0aWYgKHN0YXJ0ZWQpIHJldHVybjtcblx0XHRcdHN0YXJ0ZWQgPSB0cnVlO1xuXHRcdFx0ZGVsZXRlX3J1bGUobm9kZSk7XG5cdFx0XHRpZiAoaXNfZnVuY3Rpb24oY29uZmlnKSkge1xuXHRcdFx0XHRjb25maWcgPSBjb25maWcob3B0aW9ucyk7XG5cdFx0XHRcdHdhaXQoKS50aGVuKGdvKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGdvKCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRpbnZhbGlkYXRlKCkge1xuXHRcdFx0c3RhcnRlZCA9IGZhbHNlO1xuXHRcdH0sXG5cdFx0ZW5kKCkge1xuXHRcdFx0aWYgKHJ1bm5pbmcpIHtcblx0XHRcdFx0Y2xlYW51cCgpO1xuXHRcdFx0XHRydW5uaW5nID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHtUcmFuc2l0aW9uRm59IGZuXG4gKiBAcGFyYW0ge2FueX0gcGFyYW1zXG4gKiBAcmV0dXJucyB7eyBlbmQocmVzZXQ6IGFueSk6IHZvaWQ7IH19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfb3V0X3RyYW5zaXRpb24obm9kZSwgZm4sIHBhcmFtcykge1xuXHQvKiogQHR5cGUge1RyYW5zaXRpb25PcHRpb25zfSAqL1xuXHRjb25zdCBvcHRpb25zID0geyBkaXJlY3Rpb246ICdvdXQnIH07XG5cdGxldCBjb25maWcgPSBmbihub2RlLCBwYXJhbXMsIG9wdGlvbnMpO1xuXHRsZXQgcnVubmluZyA9IHRydWU7XG5cdGxldCBhbmltYXRpb25fbmFtZTtcblx0Y29uc3QgZ3JvdXAgPSBvdXRyb3M7XG5cdGdyb3VwLnIgKz0gMTtcblx0LyoqIEB0eXBlIHtib29sZWFufSAqL1xuXHRsZXQgb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBnbygpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cblx0XHRpZiAoY3NzKSBhbmltYXRpb25fbmFtZSA9IGNyZWF0ZV9ydWxlKG5vZGUsIDEsIDAsIGR1cmF0aW9uLCBkZWxheSwgZWFzaW5nLCBjc3MpO1xuXG5cdFx0Y29uc3Qgc3RhcnRfdGltZSA9IG5vdygpICsgZGVsYXk7XG5cdFx0Y29uc3QgZW5kX3RpbWUgPSBzdGFydF90aW1lICsgZHVyYXRpb247XG5cdFx0YWRkX3JlbmRlcl9jYWxsYmFjaygoKSA9PiBkaXNwYXRjaChub2RlLCBmYWxzZSwgJ3N0YXJ0JykpO1xuXG5cdFx0aWYgKCdpbmVydCcgaW4gbm9kZSkge1xuXHRcdFx0b3JpZ2luYWxfaW5lcnRfdmFsdWUgPSAvKiogQHR5cGUge0hUTUxFbGVtZW50fSAqLyAobm9kZSkuaW5lcnQ7XG5cdFx0XHRub2RlLmluZXJ0ID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRsb29wKChub3cpID0+IHtcblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChub3cgPj0gZW5kX3RpbWUpIHtcblx0XHRcdFx0XHR0aWNrKDAsIDEpO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIGZhbHNlLCAnZW5kJyk7XG5cdFx0XHRcdFx0aWYgKCEtLWdyb3VwLnIpIHtcblx0XHRcdFx0XHRcdC8vIHRoaXMgd2lsbCByZXN1bHQgaW4gYGVuZCgpYCBiZWluZyBjYWxsZWQsXG5cdFx0XHRcdFx0XHQvLyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNsZWFuIHVwIGhlcmVcblx0XHRcdFx0XHRcdHJ1bl9hbGwoZ3JvdXAuYyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm93ID49IHN0YXJ0X3RpbWUpIHtcblx0XHRcdFx0XHRjb25zdCB0ID0gZWFzaW5nKChub3cgLSBzdGFydF90aW1lKSAvIGR1cmF0aW9uKTtcblx0XHRcdFx0XHR0aWNrKDEgLSB0LCB0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJ1bm5pbmc7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoaXNfZnVuY3Rpb24oY29uZmlnKSkge1xuXHRcdHdhaXQoKS50aGVuKCgpID0+IHtcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdGNvbmZpZyA9IGNvbmZpZyhvcHRpb25zKTtcblx0XHRcdGdvKCk7XG5cdFx0fSk7XG5cdH0gZWxzZSB7XG5cdFx0Z28oKTtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0ZW5kKHJlc2V0KSB7XG5cdFx0XHRpZiAocmVzZXQgJiYgJ2luZXJ0JyBpbiBub2RlKSB7XG5cdFx0XHRcdG5vZGUuaW5lcnQgPSBvcmlnaW5hbF9pbmVydF92YWx1ZTtcblx0XHRcdH1cblx0XHRcdGlmIChyZXNldCAmJiBjb25maWcudGljaykge1xuXHRcdFx0XHRjb25maWcudGljaygxLCAwKTtcblx0XHRcdH1cblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChhbmltYXRpb25fbmFtZSkgZGVsZXRlX3J1bGUobm9kZSwgYW5pbWF0aW9uX25hbWUpO1xuXHRcdFx0XHRydW5uaW5nID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHtUcmFuc2l0aW9uRm59IGZuXG4gKiBAcGFyYW0ge2FueX0gcGFyYW1zXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGludHJvXG4gKiBAcmV0dXJucyB7eyBydW4oYjogMCB8IDEpOiB2b2lkOyBlbmQoKTogdm9pZDsgfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZV9iaWRpcmVjdGlvbmFsX3RyYW5zaXRpb24obm9kZSwgZm4sIHBhcmFtcywgaW50cm8pIHtcblx0LyoqXG5cdCAqIEB0eXBlIHtUcmFuc2l0aW9uT3B0aW9uc30gKi9cblx0Y29uc3Qgb3B0aW9ucyA9IHsgZGlyZWN0aW9uOiAnYm90aCcgfTtcblx0bGV0IGNvbmZpZyA9IGZuKG5vZGUsIHBhcmFtcywgb3B0aW9ucyk7XG5cdGxldCB0ID0gaW50cm8gPyAwIDogMTtcblxuXHQvKipcblx0ICogQHR5cGUge1Byb2dyYW0gfCBudWxsfSAqL1xuXHRsZXQgcnVubmluZ19wcm9ncmFtID0gbnVsbDtcblxuXHQvKipcblx0ICogQHR5cGUge1BlbmRpbmdQcm9ncmFtIHwgbnVsbH0gKi9cblx0bGV0IHBlbmRpbmdfcHJvZ3JhbSA9IG51bGw7XG5cdGxldCBhbmltYXRpb25fbmFtZSA9IG51bGw7XG5cblx0LyoqIEB0eXBlIHtib29sZWFufSAqL1xuXHRsZXQgb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBjbGVhcl9hbmltYXRpb24oKSB7XG5cdFx0aWYgKGFuaW1hdGlvbl9uYW1lKSBkZWxldGVfcnVsZShub2RlLCBhbmltYXRpb25fbmFtZSk7XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtQZW5kaW5nUHJvZ3JhbX0gcHJvZ3JhbVxuXHQgKiBAcGFyYW0ge251bWJlcn0gZHVyYXRpb25cblx0ICogQHJldHVybnMge1Byb2dyYW19XG5cdCAqL1xuXHRmdW5jdGlvbiBpbml0KHByb2dyYW0sIGR1cmF0aW9uKSB7XG5cdFx0Y29uc3QgZCA9IC8qKiBAdHlwZSB7UHJvZ3JhbVsnZCddfSAqLyAocHJvZ3JhbS5iIC0gdCk7XG5cdFx0ZHVyYXRpb24gKj0gTWF0aC5hYnMoZCk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGE6IHQsXG5cdFx0XHRiOiBwcm9ncmFtLmIsXG5cdFx0XHRkLFxuXHRcdFx0ZHVyYXRpb24sXG5cdFx0XHRzdGFydDogcHJvZ3JhbS5zdGFydCxcblx0XHRcdGVuZDogcHJvZ3JhbS5zdGFydCArIGR1cmF0aW9uLFxuXHRcdFx0Z3JvdXA6IHByb2dyYW0uZ3JvdXBcblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7SU5UUk8gfCBPVVRST30gYlxuXHQgKiBAcmV0dXJucyB7dm9pZH1cblx0ICovXG5cdGZ1bmN0aW9uIGdvKGIpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cblx0XHQvKipcblx0XHQgKiBAdHlwZSB7UGVuZGluZ1Byb2dyYW19ICovXG5cdFx0Y29uc3QgcHJvZ3JhbSA9IHtcblx0XHRcdHN0YXJ0OiBub3coKSArIGRlbGF5LFxuXHRcdFx0YlxuXHRcdH07XG5cblx0XHRpZiAoIWIpIHtcblx0XHRcdC8vIEB0cy1pZ25vcmUgdG9kbzogaW1wcm92ZSB0eXBpbmdzXG5cdFx0XHRwcm9ncmFtLmdyb3VwID0gb3V0cm9zO1xuXHRcdFx0b3V0cm9zLnIgKz0gMTtcblx0XHR9XG5cblx0XHRpZiAoJ2luZXJ0JyBpbiBub2RlKSB7XG5cdFx0XHRpZiAoYikge1xuXHRcdFx0XHRpZiAob3JpZ2luYWxfaW5lcnRfdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdC8vIGFib3J0ZWQvcmV2ZXJzZWQgb3V0cm8gXHUyMDE0IHJlc3RvcmUgcHJldmlvdXMgaW5lcnQgdmFsdWVcblx0XHRcdFx0XHRub2RlLmluZXJ0ID0gb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG9yaWdpbmFsX2luZXJ0X3ZhbHVlID0gLyoqIEB0eXBlIHtIVE1MRWxlbWVudH0gKi8gKG5vZGUpLmluZXJ0O1xuXHRcdFx0XHRub2RlLmluZXJ0ID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAocnVubmluZ19wcm9ncmFtIHx8IHBlbmRpbmdfcHJvZ3JhbSkge1xuXHRcdFx0cGVuZGluZ19wcm9ncmFtID0gcHJvZ3JhbTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gaWYgdGhpcyBpcyBhbiBpbnRybywgYW5kIHRoZXJlJ3MgYSBkZWxheSwgd2UgbmVlZCB0byBkb1xuXHRcdFx0Ly8gYW4gaW5pdGlhbCB0aWNrIGFuZC9vciBhcHBseSBDU1MgYW5pbWF0aW9uIGltbWVkaWF0ZWx5XG5cdFx0XHRpZiAoY3NzKSB7XG5cdFx0XHRcdGNsZWFyX2FuaW1hdGlvbigpO1xuXHRcdFx0XHRhbmltYXRpb25fbmFtZSA9IGNyZWF0ZV9ydWxlKG5vZGUsIHQsIGIsIGR1cmF0aW9uLCBkZWxheSwgZWFzaW5nLCBjc3MpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGIpIHRpY2soMCwgMSk7XG5cdFx0XHRydW5uaW5nX3Byb2dyYW0gPSBpbml0KHByb2dyYW0sIGR1cmF0aW9uKTtcblx0XHRcdGFkZF9yZW5kZXJfY2FsbGJhY2soKCkgPT4gZGlzcGF0Y2gobm9kZSwgYiwgJ3N0YXJ0JykpO1xuXHRcdFx0bG9vcCgobm93KSA9PiB7XG5cdFx0XHRcdGlmIChwZW5kaW5nX3Byb2dyYW0gJiYgbm93ID4gcGVuZGluZ19wcm9ncmFtLnN0YXJ0KSB7XG5cdFx0XHRcdFx0cnVubmluZ19wcm9ncmFtID0gaW5pdChwZW5kaW5nX3Byb2dyYW0sIGR1cmF0aW9uKTtcblx0XHRcdFx0XHRwZW5kaW5nX3Byb2dyYW0gPSBudWxsO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIHJ1bm5pbmdfcHJvZ3JhbS5iLCAnc3RhcnQnKTtcblx0XHRcdFx0XHRpZiAoY3NzKSB7XG5cdFx0XHRcdFx0XHRjbGVhcl9hbmltYXRpb24oKTtcblx0XHRcdFx0XHRcdGFuaW1hdGlvbl9uYW1lID0gY3JlYXRlX3J1bGUoXG5cdFx0XHRcdFx0XHRcdG5vZGUsXG5cdFx0XHRcdFx0XHRcdHQsXG5cdFx0XHRcdFx0XHRcdHJ1bm5pbmdfcHJvZ3JhbS5iLFxuXHRcdFx0XHRcdFx0XHRydW5uaW5nX3Byb2dyYW0uZHVyYXRpb24sXG5cdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdGVhc2luZyxcblx0XHRcdFx0XHRcdFx0Y29uZmlnLmNzc1xuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHJ1bm5pbmdfcHJvZ3JhbSkge1xuXHRcdFx0XHRcdGlmIChub3cgPj0gcnVubmluZ19wcm9ncmFtLmVuZCkge1xuXHRcdFx0XHRcdFx0dGljaygodCA9IHJ1bm5pbmdfcHJvZ3JhbS5iKSwgMSAtIHQpO1xuXHRcdFx0XHRcdFx0ZGlzcGF0Y2gobm9kZSwgcnVubmluZ19wcm9ncmFtLmIsICdlbmQnKTtcblx0XHRcdFx0XHRcdGlmICghcGVuZGluZ19wcm9ncmFtKSB7XG5cdFx0XHRcdFx0XHRcdC8vIHdlJ3JlIGRvbmVcblx0XHRcdFx0XHRcdFx0aWYgKHJ1bm5pbmdfcHJvZ3JhbS5iKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gaW50cm8gXHUyMDE0IHdlIGNhbiB0aWR5IHVwIGltbWVkaWF0ZWx5XG5cdFx0XHRcdFx0XHRcdFx0Y2xlYXJfYW5pbWF0aW9uKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gb3V0cm8gXHUyMDE0IG5lZWRzIHRvIGJlIGNvb3JkaW5hdGVkXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCEtLXJ1bm5pbmdfcHJvZ3JhbS5ncm91cC5yKSBydW5fYWxsKHJ1bm5pbmdfcHJvZ3JhbS5ncm91cC5jKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0cnVubmluZ19wcm9ncmFtID0gbnVsbDtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKG5vdyA+PSBydW5uaW5nX3Byb2dyYW0uc3RhcnQpIHtcblx0XHRcdFx0XHRcdGNvbnN0IHAgPSBub3cgLSBydW5uaW5nX3Byb2dyYW0uc3RhcnQ7XG5cdFx0XHRcdFx0XHR0ID0gcnVubmluZ19wcm9ncmFtLmEgKyBydW5uaW5nX3Byb2dyYW0uZCAqIGVhc2luZyhwIC8gcnVubmluZ19wcm9ncmFtLmR1cmF0aW9uKTtcblx0XHRcdFx0XHRcdHRpY2sodCwgMSAtIHQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gISEocnVubmluZ19wcm9ncmFtIHx8IHBlbmRpbmdfcHJvZ3JhbSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHtcblx0XHRydW4oYikge1xuXHRcdFx0aWYgKGlzX2Z1bmN0aW9uKGNvbmZpZykpIHtcblx0XHRcdFx0d2FpdCgpLnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IG9wdHMgPSB7IGRpcmVjdGlvbjogYiA/ICdpbicgOiAnb3V0JyB9O1xuXHRcdFx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdFx0XHRjb25maWcgPSBjb25maWcob3B0cyk7XG5cdFx0XHRcdFx0Z28oYik7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Z28oYik7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRlbmQoKSB7XG5cdFx0XHRjbGVhcl9hbmltYXRpb24oKTtcblx0XHRcdHJ1bm5pbmdfcHJvZ3JhbSA9IHBlbmRpbmdfcHJvZ3JhbSA9IG51bGw7XG5cdFx0fVxuXHR9O1xufVxuXG4vKiogQHR5cGVkZWYgezF9IElOVFJPICovXG4vKiogQHR5cGVkZWYgezB9IE9VVFJPICovXG4vKiogQHR5cGVkZWYge3sgZGlyZWN0aW9uOiAnaW4nIHwgJ291dCcgfCAnYm90aCcgfX0gVHJhbnNpdGlvbk9wdGlvbnMgKi9cbi8qKiBAdHlwZWRlZiB7KG5vZGU6IEVsZW1lbnQsIHBhcmFtczogYW55LCBvcHRpb25zOiBUcmFuc2l0aW9uT3B0aW9ucykgPT4gaW1wb3J0KCcuLi90cmFuc2l0aW9uL3B1YmxpYy5qcycpLlRyYW5zaXRpb25Db25maWd9IFRyYW5zaXRpb25GbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE91dHJvXG4gKiBAcHJvcGVydHkge251bWJlcn0gclxuICogQHByb3BlcnR5IHtGdW5jdGlvbltdfSBjXG4gKiBAcHJvcGVydHkge09iamVjdH0gcFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGVuZGluZ1Byb2dyYW1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzdGFydFxuICogQHByb3BlcnR5IHtJTlRST3xPVVRST30gYlxuICogQHByb3BlcnR5IHtPdXRyb30gW2dyb3VwXVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUHJvZ3JhbVxuICogQHByb3BlcnR5IHtudW1iZXJ9IGFcbiAqIEBwcm9wZXJ0eSB7SU5UUk98T1VUUk99IGJcbiAqIEBwcm9wZXJ0eSB7MXwtMX0gZFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGR1cmF0aW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gc3RhcnRcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBlbmRcbiAqIEBwcm9wZXJ0eSB7T3V0cm99IFtncm91cF1cbiAqL1xuIiwgImltcG9ydCB7IHRyYW5zaXRpb25faW4sIHRyYW5zaXRpb25fb3V0IH0gZnJvbSAnLi90cmFuc2l0aW9ucy5qcyc7XG5pbXBvcnQgeyBydW5fYWxsIH0gZnJvbSAnLi91dGlscy5qcyc7XG5cbi8vIGdlbmVyYWwgZWFjaCBmdW5jdGlvbnM6XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVfYXJyYXlfbGlrZShhcnJheV9saWtlX29yX2l0ZXJhdG9yKSB7XG5cdHJldHVybiBhcnJheV9saWtlX29yX2l0ZXJhdG9yPy5sZW5ndGggIT09IHVuZGVmaW5lZFxuXHRcdD8gYXJyYXlfbGlrZV9vcl9pdGVyYXRvclxuXHRcdDogQXJyYXkuZnJvbShhcnJheV9saWtlX29yX2l0ZXJhdG9yKTtcbn1cblxuLy8ga2V5ZWQgZWFjaCBmdW5jdGlvbnM6XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXN0cm95X2Jsb2NrKGJsb2NrLCBsb29rdXApIHtcblx0YmxvY2suZCgxKTtcblx0bG9va3VwLmRlbGV0ZShibG9jay5rZXkpO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gb3V0cm9fYW5kX2Rlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCkge1xuXHR0cmFuc2l0aW9uX291dChibG9jaywgMSwgMSwgKCkgPT4ge1xuXHRcdGxvb2t1cC5kZWxldGUoYmxvY2sua2V5KTtcblx0fSk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaXhfYW5kX2Rlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCkge1xuXHRibG9jay5mKCk7XG5cdGRlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaXhfYW5kX291dHJvX2FuZF9kZXN0cm95X2Jsb2NrKGJsb2NrLCBsb29rdXApIHtcblx0YmxvY2suZigpO1xuXHRvdXRyb19hbmRfZGVzdHJveV9ibG9jayhibG9jaywgbG9va3VwKTtcbn1cblxuLyoqIEByZXR1cm5zIHthbnlbXX0gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVfa2V5ZWRfZWFjaChcblx0b2xkX2Jsb2Nrcyxcblx0ZGlydHksXG5cdGdldF9rZXksXG5cdGR5bmFtaWMsXG5cdGN0eCxcblx0bGlzdCxcblx0bG9va3VwLFxuXHRub2RlLFxuXHRkZXN0cm95LFxuXHRjcmVhdGVfZWFjaF9ibG9jayxcblx0bmV4dCxcblx0Z2V0X2NvbnRleHRcbikge1xuXHRsZXQgbyA9IG9sZF9ibG9ja3MubGVuZ3RoO1xuXHRsZXQgbiA9IGxpc3QubGVuZ3RoO1xuXHRsZXQgaSA9IG87XG5cdGNvbnN0IG9sZF9pbmRleGVzID0ge307XG5cdHdoaWxlIChpLS0pIG9sZF9pbmRleGVzW29sZF9ibG9ja3NbaV0ua2V5XSA9IGk7XG5cdGNvbnN0IG5ld19ibG9ja3MgPSBbXTtcblx0Y29uc3QgbmV3X2xvb2t1cCA9IG5ldyBNYXAoKTtcblx0Y29uc3QgZGVsdGFzID0gbmV3IE1hcCgpO1xuXHRjb25zdCB1cGRhdGVzID0gW107XG5cdGkgPSBuO1xuXHR3aGlsZSAoaS0tKSB7XG5cdFx0Y29uc3QgY2hpbGRfY3R4ID0gZ2V0X2NvbnRleHQoY3R4LCBsaXN0LCBpKTtcblx0XHRjb25zdCBrZXkgPSBnZXRfa2V5KGNoaWxkX2N0eCk7XG5cdFx0bGV0IGJsb2NrID0gbG9va3VwLmdldChrZXkpO1xuXHRcdGlmICghYmxvY2spIHtcblx0XHRcdGJsb2NrID0gY3JlYXRlX2VhY2hfYmxvY2soa2V5LCBjaGlsZF9jdHgpO1xuXHRcdFx0YmxvY2suYygpO1xuXHRcdH0gZWxzZSBpZiAoZHluYW1pYykge1xuXHRcdFx0Ly8gZGVmZXIgdXBkYXRlcyB1bnRpbCBhbGwgdGhlIERPTSBzaHVmZmxpbmcgaXMgZG9uZVxuXHRcdFx0dXBkYXRlcy5wdXNoKCgpID0+IGJsb2NrLnAoY2hpbGRfY3R4LCBkaXJ0eSkpO1xuXHRcdH1cblx0XHRuZXdfbG9va3VwLnNldChrZXksIChuZXdfYmxvY2tzW2ldID0gYmxvY2spKTtcblx0XHRpZiAoa2V5IGluIG9sZF9pbmRleGVzKSBkZWx0YXMuc2V0KGtleSwgTWF0aC5hYnMoaSAtIG9sZF9pbmRleGVzW2tleV0pKTtcblx0fVxuXHRjb25zdCB3aWxsX21vdmUgPSBuZXcgU2V0KCk7XG5cdGNvbnN0IGRpZF9tb3ZlID0gbmV3IFNldCgpO1xuXHQvKiogQHJldHVybnMge3ZvaWR9ICovXG5cdGZ1bmN0aW9uIGluc2VydChibG9jaykge1xuXHRcdHRyYW5zaXRpb25faW4oYmxvY2ssIDEpO1xuXHRcdGJsb2NrLm0obm9kZSwgbmV4dCk7XG5cdFx0bG9va3VwLnNldChibG9jay5rZXksIGJsb2NrKTtcblx0XHRuZXh0ID0gYmxvY2suZmlyc3Q7XG5cdFx0bi0tO1xuXHR9XG5cdHdoaWxlIChvICYmIG4pIHtcblx0XHRjb25zdCBuZXdfYmxvY2sgPSBuZXdfYmxvY2tzW24gLSAxXTtcblx0XHRjb25zdCBvbGRfYmxvY2sgPSBvbGRfYmxvY2tzW28gLSAxXTtcblx0XHRjb25zdCBuZXdfa2V5ID0gbmV3X2Jsb2NrLmtleTtcblx0XHRjb25zdCBvbGRfa2V5ID0gb2xkX2Jsb2NrLmtleTtcblx0XHRpZiAobmV3X2Jsb2NrID09PSBvbGRfYmxvY2spIHtcblx0XHRcdC8vIGRvIG5vdGhpbmdcblx0XHRcdG5leHQgPSBuZXdfYmxvY2suZmlyc3Q7XG5cdFx0XHRvLS07XG5cdFx0XHRuLS07XG5cdFx0fSBlbHNlIGlmICghbmV3X2xvb2t1cC5oYXMob2xkX2tleSkpIHtcblx0XHRcdC8vIHJlbW92ZSBvbGQgYmxvY2tcblx0XHRcdGRlc3Ryb3kob2xkX2Jsb2NrLCBsb29rdXApO1xuXHRcdFx0by0tO1xuXHRcdH0gZWxzZSBpZiAoIWxvb2t1cC5oYXMobmV3X2tleSkgfHwgd2lsbF9tb3ZlLmhhcyhuZXdfa2V5KSkge1xuXHRcdFx0aW5zZXJ0KG5ld19ibG9jayk7XG5cdFx0fSBlbHNlIGlmIChkaWRfbW92ZS5oYXMob2xkX2tleSkpIHtcblx0XHRcdG8tLTtcblx0XHR9IGVsc2UgaWYgKGRlbHRhcy5nZXQobmV3X2tleSkgPiBkZWx0YXMuZ2V0KG9sZF9rZXkpKSB7XG5cdFx0XHRkaWRfbW92ZS5hZGQobmV3X2tleSk7XG5cdFx0XHRpbnNlcnQobmV3X2Jsb2NrKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0d2lsbF9tb3ZlLmFkZChvbGRfa2V5KTtcblx0XHRcdG8tLTtcblx0XHR9XG5cdH1cblx0d2hpbGUgKG8tLSkge1xuXHRcdGNvbnN0IG9sZF9ibG9jayA9IG9sZF9ibG9ja3Nbb107XG5cdFx0aWYgKCFuZXdfbG9va3VwLmhhcyhvbGRfYmxvY2sua2V5KSkgZGVzdHJveShvbGRfYmxvY2ssIGxvb2t1cCk7XG5cdH1cblx0d2hpbGUgKG4pIGluc2VydChuZXdfYmxvY2tzW24gLSAxXSk7XG5cdHJ1bl9hbGwodXBkYXRlcyk7XG5cdHJldHVybiBuZXdfYmxvY2tzO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVfZWFjaF9rZXlzKGN0eCwgbGlzdCwgZ2V0X2NvbnRleHQsIGdldF9rZXkpIHtcblx0Y29uc3Qga2V5cyA9IG5ldyBNYXAoKTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3Qga2V5ID0gZ2V0X2tleShnZXRfY29udGV4dChjdHgsIGxpc3QsIGkpKTtcblx0XHRpZiAoa2V5cy5oYXMoa2V5KSkge1xuXHRcdFx0bGV0IHZhbHVlID0gJyc7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR2YWx1ZSA9IGB3aXRoIHZhbHVlICcke1N0cmluZyhrZXkpfScgYDtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0Ly8gY2FuJ3Qgc3RyaW5naWZ5XG5cdFx0XHR9XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBDYW5ub3QgaGF2ZSBkdXBsaWNhdGUga2V5cyBpbiBhIGtleWVkIGVhY2g6IEtleXMgYXQgaW5kZXggJHtrZXlzLmdldChcblx0XHRcdFx0XHRrZXlcblx0XHRcdFx0KX0gYW5kICR7aX0gJHt2YWx1ZX1hcmUgZHVwbGljYXRlc2Bcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGtleXMuc2V0KGtleSwgaSk7XG5cdH1cbn1cbiIsICJjb25zdCBfYm9vbGVhbl9hdHRyaWJ1dGVzID0gLyoqIEB0eXBlIHtjb25zdH0gKi8gKFtcblx0J2FsbG93ZnVsbHNjcmVlbicsXG5cdCdhbGxvd3BheW1lbnRyZXF1ZXN0Jyxcblx0J2FzeW5jJyxcblx0J2F1dG9mb2N1cycsXG5cdCdhdXRvcGxheScsXG5cdCdjaGVja2VkJyxcblx0J2NvbnRyb2xzJyxcblx0J2RlZmF1bHQnLFxuXHQnZGVmZXInLFxuXHQnZGlzYWJsZWQnLFxuXHQnZm9ybW5vdmFsaWRhdGUnLFxuXHQnaGlkZGVuJyxcblx0J2luZXJ0Jyxcblx0J2lzbWFwJyxcblx0J2xvb3AnLFxuXHQnbXVsdGlwbGUnLFxuXHQnbXV0ZWQnLFxuXHQnbm9tb2R1bGUnLFxuXHQnbm92YWxpZGF0ZScsXG5cdCdvcGVuJyxcblx0J3BsYXlzaW5saW5lJyxcblx0J3JlYWRvbmx5Jyxcblx0J3JlcXVpcmVkJyxcblx0J3JldmVyc2VkJyxcblx0J3NlbGVjdGVkJ1xuXSk7XG5cbi8qKlxuICogTGlzdCBvZiBIVE1MIGJvb2xlYW4gYXR0cmlidXRlcyAoZS5nLiBgPGlucHV0IGRpc2FibGVkPmApLlxuICogU291cmNlOiBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9pbmRpY2VzLmh0bWxcbiAqXG4gKiBAdHlwZSB7U2V0PHN0cmluZz59XG4gKi9cbmV4cG9ydCBjb25zdCBib29sZWFuX2F0dHJpYnV0ZXMgPSBuZXcgU2V0KFsuLi5fYm9vbGVhbl9hdHRyaWJ1dGVzXSk7XG5cbi8qKiBAdHlwZWRlZiB7dHlwZW9mIF9ib29sZWFuX2F0dHJpYnV0ZXNbbnVtYmVyXX0gQm9vbGVhbkF0dHJpYnV0ZXMgKi9cbiIsICJpbXBvcnQge1xuXHRhZGRfcmVuZGVyX2NhbGxiYWNrLFxuXHRmbHVzaCxcblx0Zmx1c2hfcmVuZGVyX2NhbGxiYWNrcyxcblx0c2NoZWR1bGVfdXBkYXRlLFxuXHRkaXJ0eV9jb21wb25lbnRzXG59IGZyb20gJy4vc2NoZWR1bGVyLmpzJztcbmltcG9ydCB7IGN1cnJlbnRfY29tcG9uZW50LCBzZXRfY3VycmVudF9jb21wb25lbnQgfSBmcm9tICcuL2xpZmVjeWNsZS5qcyc7XG5pbXBvcnQgeyBibGFua19vYmplY3QsIGlzX2VtcHR5LCBpc19mdW5jdGlvbiwgcnVuLCBydW5fYWxsLCBub29wIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQge1xuXHRjaGlsZHJlbixcblx0ZGV0YWNoLFxuXHRzdGFydF9oeWRyYXRpbmcsXG5cdGVuZF9oeWRyYXRpbmcsXG5cdGdldF9jdXN0b21fZWxlbWVudHNfc2xvdHMsXG5cdGluc2VydCxcblx0ZWxlbWVudCxcblx0YXR0clxufSBmcm9tICcuL2RvbS5qcyc7XG5pbXBvcnQgeyB0cmFuc2l0aW9uX2luIH0gZnJvbSAnLi90cmFuc2l0aW9ucy5qcyc7XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaW5kKGNvbXBvbmVudCwgbmFtZSwgY2FsbGJhY2spIHtcblx0Y29uc3QgaW5kZXggPSBjb21wb25lbnQuJCQucHJvcHNbbmFtZV07XG5cdGlmIChpbmRleCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0Y29tcG9uZW50LiQkLmJvdW5kW2luZGV4XSA9IGNhbGxiYWNrO1xuXHRcdGNhbGxiYWNrKGNvbXBvbmVudC4kJC5jdHhbaW5kZXhdKTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlX2NvbXBvbmVudChibG9jaykge1xuXHRibG9jayAmJiBibG9jay5jKCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFpbV9jb21wb25lbnQoYmxvY2ssIHBhcmVudF9ub2Rlcykge1xuXHRibG9jayAmJiBibG9jay5sKHBhcmVudF9ub2Rlcyk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3VudF9jb21wb25lbnQoY29tcG9uZW50LCB0YXJnZXQsIGFuY2hvcikge1xuXHRjb25zdCB7IGZyYWdtZW50LCBhZnRlcl91cGRhdGUgfSA9IGNvbXBvbmVudC4kJDtcblx0ZnJhZ21lbnQgJiYgZnJhZ21lbnQubSh0YXJnZXQsIGFuY2hvcik7XG5cdC8vIG9uTW91bnQgaGFwcGVucyBiZWZvcmUgdGhlIGluaXRpYWwgYWZ0ZXJVcGRhdGVcblx0YWRkX3JlbmRlcl9jYWxsYmFjaygoKSA9PiB7XG5cdFx0Y29uc3QgbmV3X29uX2Rlc3Ryb3kgPSBjb21wb25lbnQuJCQub25fbW91bnQubWFwKHJ1bikuZmlsdGVyKGlzX2Z1bmN0aW9uKTtcblx0XHQvLyBpZiB0aGUgY29tcG9uZW50IHdhcyBkZXN0cm95ZWQgaW1tZWRpYXRlbHlcblx0XHQvLyBpdCB3aWxsIHVwZGF0ZSB0aGUgYCQkLm9uX2Rlc3Ryb3lgIHJlZmVyZW5jZSB0byBgbnVsbGAuXG5cdFx0Ly8gdGhlIGRlc3RydWN0dXJlZCBvbl9kZXN0cm95IG1heSBzdGlsbCByZWZlcmVuY2UgdG8gdGhlIG9sZCBhcnJheVxuXHRcdGlmIChjb21wb25lbnQuJCQub25fZGVzdHJveSkge1xuXHRcdFx0Y29tcG9uZW50LiQkLm9uX2Rlc3Ryb3kucHVzaCguLi5uZXdfb25fZGVzdHJveSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIEVkZ2UgY2FzZSAtIGNvbXBvbmVudCB3YXMgZGVzdHJveWVkIGltbWVkaWF0ZWx5LFxuXHRcdFx0Ly8gbW9zdCBsaWtlbHkgYXMgYSByZXN1bHQgb2YgYSBiaW5kaW5nIGluaXRpYWxpc2luZ1xuXHRcdFx0cnVuX2FsbChuZXdfb25fZGVzdHJveSk7XG5cdFx0fVxuXHRcdGNvbXBvbmVudC4kJC5vbl9tb3VudCA9IFtdO1xuXHR9KTtcblx0YWZ0ZXJfdXBkYXRlLmZvckVhY2goYWRkX3JlbmRlcl9jYWxsYmFjayk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXN0cm95X2NvbXBvbmVudChjb21wb25lbnQsIGRldGFjaGluZykge1xuXHRjb25zdCAkJCA9IGNvbXBvbmVudC4kJDtcblx0aWYgKCQkLmZyYWdtZW50ICE9PSBudWxsKSB7XG5cdFx0Zmx1c2hfcmVuZGVyX2NhbGxiYWNrcygkJC5hZnRlcl91cGRhdGUpO1xuXHRcdHJ1bl9hbGwoJCQub25fZGVzdHJveSk7XG5cdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQuZChkZXRhY2hpbmcpO1xuXHRcdC8vIFRPRE8gbnVsbCBvdXQgb3RoZXIgcmVmcywgaW5jbHVkaW5nIGNvbXBvbmVudC4kJCAoYnV0IG5lZWQgdG9cblx0XHQvLyBwcmVzZXJ2ZSBmaW5hbCBzdGF0ZT8pXG5cdFx0JCQub25fZGVzdHJveSA9ICQkLmZyYWdtZW50ID0gbnVsbDtcblx0XHQkJC5jdHggPSBbXTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5mdW5jdGlvbiBtYWtlX2RpcnR5KGNvbXBvbmVudCwgaSkge1xuXHRpZiAoY29tcG9uZW50LiQkLmRpcnR5WzBdID09PSAtMSkge1xuXHRcdGRpcnR5X2NvbXBvbmVudHMucHVzaChjb21wb25lbnQpO1xuXHRcdHNjaGVkdWxlX3VwZGF0ZSgpO1xuXHRcdGNvbXBvbmVudC4kJC5kaXJ0eS5maWxsKDApO1xuXHR9XG5cdGNvbXBvbmVudC4kJC5kaXJ0eVsoaSAvIDMxKSB8IDBdIHw9IDEgPDwgaSAlIDMxO1xufVxuXG4vLyBUT0RPOiBEb2N1bWVudCB0aGUgb3RoZXIgcGFyYW1zXG4vKipcbiAqIEBwYXJhbSB7U3ZlbHRlQ29tcG9uZW50fSBjb21wb25lbnRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLkNvbXBvbmVudENvbnN0cnVjdG9yT3B0aW9uc30gb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3V0aWxzLmpzJylbJ25vdF9lcXVhbCddfSBub3RfZXF1YWwgVXNlZCB0byBjb21wYXJlIHByb3BzIGFuZCBzdGF0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0geyh0YXJnZXQ6IEVsZW1lbnQgfCBTaGFkb3dSb290KSA9PiB2b2lkfSBbYXBwZW5kX3N0eWxlc10gRnVuY3Rpb24gdGhhdCBhcHBlbmRzIHN0eWxlcyB0byB0aGUgRE9NIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBmaXJzdCBpbml0aWFsaXNlZC5cbiAqIFRoaXMgd2lsbCBiZSB0aGUgYGFkZF9jc3NgIGZ1bmN0aW9uIGZyb20gdGhlIGNvbXBpbGVkIGNvbXBvbmVudC5cbiAqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXQoXG5cdGNvbXBvbmVudCxcblx0b3B0aW9ucyxcblx0aW5zdGFuY2UsXG5cdGNyZWF0ZV9mcmFnbWVudCxcblx0bm90X2VxdWFsLFxuXHRwcm9wcyxcblx0YXBwZW5kX3N0eWxlcyA9IG51bGwsXG5cdGRpcnR5ID0gWy0xXVxuKSB7XG5cdGNvbnN0IHBhcmVudF9jb21wb25lbnQgPSBjdXJyZW50X2NvbXBvbmVudDtcblx0c2V0X2N1cnJlbnRfY29tcG9uZW50KGNvbXBvbmVudCk7XG5cdC8qKiBAdHlwZSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5UJCR9ICovXG5cdGNvbnN0ICQkID0gKGNvbXBvbmVudC4kJCA9IHtcblx0XHRmcmFnbWVudDogbnVsbCxcblx0XHRjdHg6IFtdLFxuXHRcdC8vIHN0YXRlXG5cdFx0cHJvcHMsXG5cdFx0dXBkYXRlOiBub29wLFxuXHRcdG5vdF9lcXVhbCxcblx0XHRib3VuZDogYmxhbmtfb2JqZWN0KCksXG5cdFx0Ly8gbGlmZWN5Y2xlXG5cdFx0b25fbW91bnQ6IFtdLFxuXHRcdG9uX2Rlc3Ryb3k6IFtdLFxuXHRcdG9uX2Rpc2Nvbm5lY3Q6IFtdLFxuXHRcdGJlZm9yZV91cGRhdGU6IFtdLFxuXHRcdGFmdGVyX3VwZGF0ZTogW10sXG5cdFx0Y29udGV4dDogbmV3IE1hcChvcHRpb25zLmNvbnRleHQgfHwgKHBhcmVudF9jb21wb25lbnQgPyBwYXJlbnRfY29tcG9uZW50LiQkLmNvbnRleHQgOiBbXSkpLFxuXHRcdC8vIGV2ZXJ5dGhpbmcgZWxzZVxuXHRcdGNhbGxiYWNrczogYmxhbmtfb2JqZWN0KCksXG5cdFx0ZGlydHksXG5cdFx0c2tpcF9ib3VuZDogZmFsc2UsXG5cdFx0cm9vdDogb3B0aW9ucy50YXJnZXQgfHwgcGFyZW50X2NvbXBvbmVudC4kJC5yb290XG5cdH0pO1xuXHRhcHBlbmRfc3R5bGVzICYmIGFwcGVuZF9zdHlsZXMoJCQucm9vdCk7XG5cdGxldCByZWFkeSA9IGZhbHNlO1xuXHQkJC5jdHggPSBpbnN0YW5jZVxuXHRcdD8gaW5zdGFuY2UoY29tcG9uZW50LCBvcHRpb25zLnByb3BzIHx8IHt9LCAoaSwgcmV0LCAuLi5yZXN0KSA9PiB7XG5cdFx0XHRcdGNvbnN0IHZhbHVlID0gcmVzdC5sZW5ndGggPyByZXN0WzBdIDogcmV0O1xuXHRcdFx0XHRpZiAoJCQuY3R4ICYmIG5vdF9lcXVhbCgkJC5jdHhbaV0sICgkJC5jdHhbaV0gPSB2YWx1ZSkpKSB7XG5cdFx0XHRcdFx0aWYgKCEkJC5za2lwX2JvdW5kICYmICQkLmJvdW5kW2ldKSAkJC5ib3VuZFtpXSh2YWx1ZSk7XG5cdFx0XHRcdFx0aWYgKHJlYWR5KSBtYWtlX2RpcnR5KGNvbXBvbmVudCwgaSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHQgIH0pXG5cdFx0OiBbXTtcblx0JCQudXBkYXRlKCk7XG5cdHJlYWR5ID0gdHJ1ZTtcblx0cnVuX2FsbCgkJC5iZWZvcmVfdXBkYXRlKTtcblx0Ly8gYGZhbHNlYCBhcyBhIHNwZWNpYWwgY2FzZSBvZiBubyBET00gY29tcG9uZW50XG5cdCQkLmZyYWdtZW50ID0gY3JlYXRlX2ZyYWdtZW50ID8gY3JlYXRlX2ZyYWdtZW50KCQkLmN0eCkgOiBmYWxzZTtcblx0aWYgKG9wdGlvbnMudGFyZ2V0KSB7XG5cdFx0aWYgKG9wdGlvbnMuaHlkcmF0ZSkge1xuXHRcdFx0c3RhcnRfaHlkcmF0aW5nKCk7XG5cdFx0XHQvLyBUT0RPOiB3aGF0IGlzIHRoZSBjb3JyZWN0IHR5cGUgaGVyZT9cblx0XHRcdC8vIEB0cy1leHBlY3QtZXJyb3Jcblx0XHRcdGNvbnN0IG5vZGVzID0gY2hpbGRyZW4ob3B0aW9ucy50YXJnZXQpO1xuXHRcdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQubChub2Rlcyk7XG5cdFx0XHRub2Rlcy5mb3JFYWNoKGRldGFjaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG5cdFx0XHQkJC5mcmFnbWVudCAmJiAkJC5mcmFnbWVudC5jKCk7XG5cdFx0fVxuXHRcdGlmIChvcHRpb25zLmludHJvKSB0cmFuc2l0aW9uX2luKGNvbXBvbmVudC4kJC5mcmFnbWVudCk7XG5cdFx0bW91bnRfY29tcG9uZW50KGNvbXBvbmVudCwgb3B0aW9ucy50YXJnZXQsIG9wdGlvbnMuYW5jaG9yKTtcblx0XHRlbmRfaHlkcmF0aW5nKCk7XG5cdFx0Zmx1c2goKTtcblx0fVxuXHRzZXRfY3VycmVudF9jb21wb25lbnQocGFyZW50X2NvbXBvbmVudCk7XG59XG5cbmV4cG9ydCBsZXQgU3ZlbHRlRWxlbWVudDtcblxuaWYgKHR5cGVvZiBIVE1MRWxlbWVudCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRTdmVsdGVFbGVtZW50ID0gY2xhc3MgZXh0ZW5kcyBIVE1MRWxlbWVudCB7XG5cdFx0LyoqIFRoZSBTdmVsdGUgY29tcG9uZW50IGNvbnN0cnVjdG9yICovXG5cdFx0JCRjdG9yO1xuXHRcdC8qKiBTbG90cyAqL1xuXHRcdCQkcztcblx0XHQvKiogVGhlIFN2ZWx0ZSBjb21wb25lbnQgaW5zdGFuY2UgKi9cblx0XHQkJGM7XG5cdFx0LyoqIFdoZXRoZXIgb3Igbm90IHRoZSBjdXN0b20gZWxlbWVudCBpcyBjb25uZWN0ZWQgKi9cblx0XHQkJGNuID0gZmFsc2U7XG5cdFx0LyoqIENvbXBvbmVudCBwcm9wcyBkYXRhICovXG5cdFx0JCRkID0ge307XG5cdFx0LyoqIGB0cnVlYCBpZiBjdXJyZW50bHkgaW4gdGhlIHByb2Nlc3Mgb2YgcmVmbGVjdGluZyBjb21wb25lbnQgcHJvcHMgYmFjayB0byBhdHRyaWJ1dGVzICovXG5cdFx0JCRyID0gZmFsc2U7XG5cdFx0LyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBDdXN0b21FbGVtZW50UHJvcERlZmluaXRpb24+fSBQcm9wcyBkZWZpbml0aW9uIChuYW1lLCByZWZsZWN0ZWQsIHR5cGUgZXRjKSAqL1xuXHRcdCQkcF9kID0ge307XG5cdFx0LyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBGdW5jdGlvbltdPn0gRXZlbnQgbGlzdGVuZXJzICovXG5cdFx0JCRsID0ge307XG5cdFx0LyoqIEB0eXBlIHtNYXA8RnVuY3Rpb24sIEZ1bmN0aW9uPn0gRXZlbnQgbGlzdGVuZXIgdW5zdWJzY3JpYmUgZnVuY3Rpb25zICovXG5cdFx0JCRsX3UgPSBuZXcgTWFwKCk7XG5cblx0XHRjb25zdHJ1Y3RvcigkJGNvbXBvbmVudEN0b3IsICQkc2xvdHMsIHVzZV9zaGFkb3dfZG9tKSB7XG5cdFx0XHRzdXBlcigpO1xuXHRcdFx0dGhpcy4kJGN0b3IgPSAkJGNvbXBvbmVudEN0b3I7XG5cdFx0XHR0aGlzLiQkcyA9ICQkc2xvdHM7XG5cdFx0XHRpZiAodXNlX3NoYWRvd19kb20pIHtcblx0XHRcdFx0dGhpcy5hdHRhY2hTaGFkb3coeyBtb2RlOiAnb3BlbicgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0YWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lciwgb3B0aW9ucykge1xuXHRcdFx0Ly8gV2UgY2FuJ3QgZGV0ZXJtaW5lIHVwZnJvbnQgaWYgdGhlIGV2ZW50IGlzIGEgY3VzdG9tIGV2ZW50IG9yIG5vdCwgc28gd2UgaGF2ZSB0b1xuXHRcdFx0Ly8gbGlzdGVuIHRvIGJvdGguIElmIHNvbWVvbmUgdXNlcyBhIGN1c3RvbSBldmVudCB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgYSByZWd1bGFyXG5cdFx0XHQvLyBicm93c2VyIGV2ZW50LCB0aGlzIGZpcmVzIHR3aWNlIC0gd2UgY2FuJ3QgYXZvaWQgdGhhdC5cblx0XHRcdHRoaXMuJCRsW3R5cGVdID0gdGhpcy4kJGxbdHlwZV0gfHwgW107XG5cdFx0XHR0aGlzLiQkbFt0eXBlXS5wdXNoKGxpc3RlbmVyKTtcblx0XHRcdGlmICh0aGlzLiQkYykge1xuXHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRjLiRvbih0eXBlLCBsaXN0ZW5lcik7XG5cdFx0XHRcdHRoaXMuJCRsX3Uuc2V0KGxpc3RlbmVyLCB1bnN1Yik7XG5cdFx0XHR9XG5cdFx0XHRzdXBlci5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcblx0XHR9XG5cblx0XHRyZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG5cdFx0XHRzdXBlci5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcblx0XHRcdGlmICh0aGlzLiQkYykge1xuXHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRsX3UuZ2V0KGxpc3RlbmVyKTtcblx0XHRcdFx0aWYgKHVuc3ViKSB7XG5cdFx0XHRcdFx0dW5zdWIoKTtcblx0XHRcdFx0XHR0aGlzLiQkbF91LmRlbGV0ZShsaXN0ZW5lcik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRhc3luYyBjb25uZWN0ZWRDYWxsYmFjaygpIHtcblx0XHRcdHRoaXMuJCRjbiA9IHRydWU7XG5cdFx0XHRpZiAoIXRoaXMuJCRjKSB7XG5cdFx0XHRcdC8vIFdlIHdhaXQgb25lIHRpY2sgdG8gbGV0IHBvc3NpYmxlIGNoaWxkIHNsb3QgZWxlbWVudHMgYmUgY3JlYXRlZC9tb3VudGVkXG5cdFx0XHRcdGF3YWl0IFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdFx0XHRpZiAoIXRoaXMuJCRjbiB8fCB0aGlzLiQkYykge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRmdW5jdGlvbiBjcmVhdGVfc2xvdChuYW1lKSB7XG5cdFx0XHRcdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdFx0XHRcdGxldCBub2RlO1xuXHRcdFx0XHRcdFx0Y29uc3Qgb2JqID0ge1xuXHRcdFx0XHRcdFx0XHRjOiBmdW5jdGlvbiBjcmVhdGUoKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW1lbnQoJ3Nsb3QnKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAobmFtZSAhPT0gJ2RlZmF1bHQnKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRhdHRyKG5vZGUsICduYW1lJywgbmFtZSk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHQvKipcblx0XHRcdFx0XHRcdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdGFyZ2V0XG5cdFx0XHRcdFx0XHRcdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IFthbmNob3JdXG5cdFx0XHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdFx0XHRtOiBmdW5jdGlvbiBtb3VudCh0YXJnZXQsIGFuY2hvcikge1xuXHRcdFx0XHRcdFx0XHRcdGluc2VydCh0YXJnZXQsIG5vZGUsIGFuY2hvcik7XG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdGQ6IGZ1bmN0aW9uIGRlc3Ryb3koZGV0YWNoaW5nKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRldGFjaGluZykge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGV0YWNoKG5vZGUpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdHJldHVybiBvYmo7XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCAkJHNsb3RzID0ge307XG5cdFx0XHRcdGNvbnN0IGV4aXN0aW5nX3Nsb3RzID0gZ2V0X2N1c3RvbV9lbGVtZW50c19zbG90cyh0aGlzKTtcblx0XHRcdFx0Zm9yIChjb25zdCBuYW1lIG9mIHRoaXMuJCRzKSB7XG5cdFx0XHRcdFx0aWYgKG5hbWUgaW4gZXhpc3Rpbmdfc2xvdHMpIHtcblx0XHRcdFx0XHRcdCQkc2xvdHNbbmFtZV0gPSBbY3JlYXRlX3Nsb3QobmFtZSldO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiB0aGlzLmF0dHJpYnV0ZXMpIHtcblx0XHRcdFx0XHQvLyB0aGlzLiQkZGF0YSB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgdGhpcy5hdHRyaWJ1dGVzXG5cdFx0XHRcdFx0Y29uc3QgbmFtZSA9IHRoaXMuJCRnX3AoYXR0cmlidXRlLm5hbWUpO1xuXHRcdFx0XHRcdGlmICghKG5hbWUgaW4gdGhpcy4kJGQpKSB7XG5cdFx0XHRcdFx0XHR0aGlzLiQkZFtuYW1lXSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShuYW1lLCBhdHRyaWJ1dGUudmFsdWUsIHRoaXMuJCRwX2QsICd0b1Byb3AnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gUG9ydCBvdmVyIHByb3BzIHRoYXQgd2VyZSBzZXQgcHJvZ3JhbW1hdGljYWxseSBiZWZvcmUgY2Ugd2FzIGluaXRpYWxpemVkXG5cdFx0XHRcdGZvciAoY29uc3Qga2V5IGluIHRoaXMuJCRwX2QpIHtcblx0XHRcdFx0XHRpZiAoIShrZXkgaW4gdGhpcy4kJGQpICYmIHRoaXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHR0aGlzLiQkZFtrZXldID0gdGhpc1trZXldOyAvLyBkb24ndCB0cmFuc2Zvcm0sIHRoZXNlIHdlcmUgc2V0IHRocm91Z2ggSmF2YVNjcmlwdFxuXHRcdFx0XHRcdFx0ZGVsZXRlIHRoaXNba2V5XTsgLy8gcmVtb3ZlIHRoZSBwcm9wZXJ0eSB0aGF0IHNoYWRvd3MgdGhlIGdldHRlci9zZXR0ZXJcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy4kJGMgPSBuZXcgdGhpcy4kJGN0b3Ioe1xuXHRcdFx0XHRcdHRhcmdldDogdGhpcy5zaGFkb3dSb290IHx8IHRoaXMsXG5cdFx0XHRcdFx0cHJvcHM6IHtcblx0XHRcdFx0XHRcdC4uLnRoaXMuJCRkLFxuXHRcdFx0XHRcdFx0JCRzbG90cyxcblx0XHRcdFx0XHRcdCQkc2NvcGU6IHtcblx0XHRcdFx0XHRcdFx0Y3R4OiBbXVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gUmVmbGVjdCBjb21wb25lbnQgcHJvcHMgYXMgYXR0cmlidXRlc1xuXHRcdFx0XHRjb25zdCByZWZsZWN0X2F0dHJpYnV0ZXMgPSAoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy4kJHIgPSB0cnVlO1xuXHRcdFx0XHRcdGZvciAoY29uc3Qga2V5IGluIHRoaXMuJCRwX2QpIHtcblx0XHRcdFx0XHRcdHRoaXMuJCRkW2tleV0gPSB0aGlzLiQkYy4kJC5jdHhbdGhpcy4kJGMuJCQucHJvcHNba2V5XV07XG5cdFx0XHRcdFx0XHRpZiAodGhpcy4kJHBfZFtrZXldLnJlZmxlY3QpIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgYXR0cmlidXRlX3ZhbHVlID0gZ2V0X2N1c3RvbV9lbGVtZW50X3ZhbHVlKFxuXHRcdFx0XHRcdFx0XHRcdGtleSxcblx0XHRcdFx0XHRcdFx0XHR0aGlzLiQkZFtrZXldLFxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuJCRwX2QsXG5cdFx0XHRcdFx0XHRcdFx0J3RvQXR0cmlidXRlJ1xuXHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRpZiAoYXR0cmlidXRlX3ZhbHVlID09IG51bGwpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnJlbW92ZUF0dHJpYnV0ZSh0aGlzLiQkcF9kW2tleV0uYXR0cmlidXRlIHx8IGtleSk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUodGhpcy4kJHBfZFtrZXldLmF0dHJpYnV0ZSB8fCBrZXksIGF0dHJpYnV0ZV92YWx1ZSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhpcy4kJHIgPSBmYWxzZTtcblx0XHRcdFx0fTtcblx0XHRcdFx0dGhpcy4kJGMuJCQuYWZ0ZXJfdXBkYXRlLnB1c2gocmVmbGVjdF9hdHRyaWJ1dGVzKTtcblx0XHRcdFx0cmVmbGVjdF9hdHRyaWJ1dGVzKCk7IC8vIG9uY2UgaW5pdGlhbGx5IGJlY2F1c2UgYWZ0ZXJfdXBkYXRlIGlzIGFkZGVkIHRvbyBsYXRlIGZvciBmaXJzdCByZW5kZXJcblxuXHRcdFx0XHRmb3IgKGNvbnN0IHR5cGUgaW4gdGhpcy4kJGwpIHtcblx0XHRcdFx0XHRmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuJCRsW3R5cGVdKSB7XG5cdFx0XHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRjLiRvbih0eXBlLCBsaXN0ZW5lcik7XG5cdFx0XHRcdFx0XHR0aGlzLiQkbF91LnNldChsaXN0ZW5lciwgdW5zdWIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLiQkbCA9IHt9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFdlIGRvbid0IG5lZWQgdGhpcyB3aGVuIHdvcmtpbmcgd2l0aGluIFN2ZWx0ZSBjb2RlLCBidXQgZm9yIGNvbXBhdGliaWxpdHkgb2YgcGVvcGxlIHVzaW5nIHRoaXMgb3V0c2lkZSBvZiBTdmVsdGVcblx0XHQvLyBhbmQgc2V0dGluZyBhdHRyaWJ1dGVzIHRocm91Z2ggc2V0QXR0cmlidXRlIGV0YywgdGhpcyBpcyBoZWxwZnVsXG5cdFx0YXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGF0dHIsIF9vbGRWYWx1ZSwgbmV3VmFsdWUpIHtcblx0XHRcdGlmICh0aGlzLiQkcikgcmV0dXJuO1xuXHRcdFx0YXR0ciA9IHRoaXMuJCRnX3AoYXR0cik7XG5cdFx0XHR0aGlzLiQkZFthdHRyXSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShhdHRyLCBuZXdWYWx1ZSwgdGhpcy4kJHBfZCwgJ3RvUHJvcCcpO1xuXHRcdFx0dGhpcy4kJGM/LiRzZXQoeyBbYXR0cl06IHRoaXMuJCRkW2F0dHJdIH0pO1xuXHRcdH1cblxuXHRcdGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuXHRcdFx0dGhpcy4kJGNuID0gZmFsc2U7XG5cdFx0XHQvLyBJbiBhIG1pY3JvdGFzaywgYmVjYXVzZSB0aGlzIGNvdWxkIGJlIGEgbW92ZSB3aXRoaW4gdGhlIERPTVxuXHRcdFx0UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG5cdFx0XHRcdGlmICghdGhpcy4kJGNuKSB7XG5cdFx0XHRcdFx0dGhpcy4kJGMuJGRlc3Ryb3koKTtcblx0XHRcdFx0XHR0aGlzLiQkYyA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0JCRnX3AoYXR0cmlidXRlX25hbWUpIHtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdE9iamVjdC5rZXlzKHRoaXMuJCRwX2QpLmZpbmQoXG5cdFx0XHRcdFx0KGtleSkgPT5cblx0XHRcdFx0XHRcdHRoaXMuJCRwX2Rba2V5XS5hdHRyaWJ1dGUgPT09IGF0dHJpYnV0ZV9uYW1lIHx8XG5cdFx0XHRcdFx0XHQoIXRoaXMuJCRwX2Rba2V5XS5hdHRyaWJ1dGUgJiYga2V5LnRvTG93ZXJDYXNlKCkgPT09IGF0dHJpYnV0ZV9uYW1lKVxuXHRcdFx0XHQpIHx8IGF0dHJpYnV0ZV9uYW1lXG5cdFx0XHQpO1xuXHRcdH1cblx0fTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcFxuICogQHBhcmFtIHthbnl9IHZhbHVlXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIEN1c3RvbUVsZW1lbnRQcm9wRGVmaW5pdGlvbj59IHByb3BzX2RlZmluaXRpb25cbiAqIEBwYXJhbSB7J3RvQXR0cmlidXRlJyB8ICd0b1Byb3AnfSBbdHJhbnNmb3JtXVxuICovXG5mdW5jdGlvbiBnZXRfY3VzdG9tX2VsZW1lbnRfdmFsdWUocHJvcCwgdmFsdWUsIHByb3BzX2RlZmluaXRpb24sIHRyYW5zZm9ybSkge1xuXHRjb25zdCB0eXBlID0gcHJvcHNfZGVmaW5pdGlvbltwcm9wXT8udHlwZTtcblx0dmFsdWUgPSB0eXBlID09PSAnQm9vbGVhbicgJiYgdHlwZW9mIHZhbHVlICE9PSAnYm9vbGVhbicgPyB2YWx1ZSAhPSBudWxsIDogdmFsdWU7XG5cdGlmICghdHJhbnNmb3JtIHx8ICFwcm9wc19kZWZpbml0aW9uW3Byb3BdKSB7XG5cdFx0cmV0dXJuIHZhbHVlO1xuXHR9IGVsc2UgaWYgKHRyYW5zZm9ybSA9PT0gJ3RvQXR0cmlidXRlJykge1xuXHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0Y2FzZSAnT2JqZWN0Jzpcblx0XHRcdGNhc2UgJ0FycmF5Jzpcblx0XHRcdFx0cmV0dXJuIHZhbHVlID09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuXHRcdFx0Y2FzZSAnQm9vbGVhbic6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA/ICcnIDogbnVsbDtcblx0XHRcdGNhc2UgJ051bWJlcic6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRzd2l0Y2ggKHR5cGUpIHtcblx0XHRcdGNhc2UgJ09iamVjdCc6XG5cdFx0XHRjYXNlICdBcnJheSc6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSAmJiBKU09OLnBhcnNlKHZhbHVlKTtcblx0XHRcdGNhc2UgJ0Jvb2xlYW4nOlxuXHRcdFx0XHRyZXR1cm4gdmFsdWU7IC8vIGNvbnZlcnNpb24gYWxyZWFkeSBoYW5kbGVkIGFib3ZlXG5cdFx0XHRjYXNlICdOdW1iZXInOlxuXHRcdFx0XHRyZXR1cm4gdmFsdWUgIT0gbnVsbCA/ICt2YWx1ZSA6IHZhbHVlO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICpcbiAqIFR1cm4gYSBTdmVsdGUgY29tcG9uZW50IGludG8gYSBjdXN0b20gZWxlbWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLkNvbXBvbmVudFR5cGV9IENvbXBvbmVudCAgQSBTdmVsdGUgY29tcG9uZW50IGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIEN1c3RvbUVsZW1lbnRQcm9wRGVmaW5pdGlvbj59IHByb3BzX2RlZmluaXRpb24gIFRoZSBwcm9wcyB0byBvYnNlcnZlXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBzbG90cyAgVGhlIHNsb3RzIHRvIGNyZWF0ZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gYWNjZXNzb3JzICBPdGhlciBhY2Nlc3NvcnMgYmVzaWRlcyB0aGUgb25lcyBmb3IgcHJvcHMgdGhlIGNvbXBvbmVudCBoYXNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gdXNlX3NoYWRvd19kb20gIFdoZXRoZXIgdG8gdXNlIHNoYWRvdyBET01cbiAqIEBwYXJhbSB7KGNlOiBuZXcgKCkgPT4gSFRNTEVsZW1lbnQpID0+IG5ldyAoKSA9PiBIVE1MRWxlbWVudH0gW2V4dGVuZF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZV9jdXN0b21fZWxlbWVudChcblx0Q29tcG9uZW50LFxuXHRwcm9wc19kZWZpbml0aW9uLFxuXHRzbG90cyxcblx0YWNjZXNzb3JzLFxuXHR1c2Vfc2hhZG93X2RvbSxcblx0ZXh0ZW5kXG4pIHtcblx0bGV0IENsYXNzID0gY2xhc3MgZXh0ZW5kcyBTdmVsdGVFbGVtZW50IHtcblx0XHRjb25zdHJ1Y3RvcigpIHtcblx0XHRcdHN1cGVyKENvbXBvbmVudCwgc2xvdHMsIHVzZV9zaGFkb3dfZG9tKTtcblx0XHRcdHRoaXMuJCRwX2QgPSBwcm9wc19kZWZpbml0aW9uO1xuXHRcdH1cblx0XHRzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcblx0XHRcdHJldHVybiBPYmplY3Qua2V5cyhwcm9wc19kZWZpbml0aW9uKS5tYXAoKGtleSkgPT5cblx0XHRcdFx0KHByb3BzX2RlZmluaXRpb25ba2V5XS5hdHRyaWJ1dGUgfHwga2V5KS50b0xvd2VyQ2FzZSgpXG5cdFx0XHQpO1xuXHRcdH1cblx0fTtcblx0T2JqZWN0LmtleXMocHJvcHNfZGVmaW5pdGlvbikuZm9yRWFjaCgocHJvcCkgPT4ge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDbGFzcy5wcm90b3R5cGUsIHByb3AsIHtcblx0XHRcdGdldCgpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuJCRjICYmIHByb3AgaW4gdGhpcy4kJGMgPyB0aGlzLiQkY1twcm9wXSA6IHRoaXMuJCRkW3Byb3BdO1xuXHRcdFx0fSxcblx0XHRcdHNldCh2YWx1ZSkge1xuXHRcdFx0XHR2YWx1ZSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShwcm9wLCB2YWx1ZSwgcHJvcHNfZGVmaW5pdGlvbik7XG5cdFx0XHRcdHRoaXMuJCRkW3Byb3BdID0gdmFsdWU7XG5cdFx0XHRcdHRoaXMuJCRjPy4kc2V0KHsgW3Byb3BdOiB2YWx1ZSB9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdGFjY2Vzc29ycy5mb3JFYWNoKChhY2Nlc3NvcikgPT4ge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDbGFzcy5wcm90b3R5cGUsIGFjY2Vzc29yLCB7XG5cdFx0XHRnZXQoKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLiQkYz8uW2FjY2Vzc29yXTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdGlmIChleHRlbmQpIHtcblx0XHQvLyBAdHMtZXhwZWN0LWVycm9yIC0gYXNzaWduaW5nIGhlcmUgaXMgZmluZVxuXHRcdENsYXNzID0gZXh0ZW5kKENsYXNzKTtcblx0fVxuXHRDb21wb25lbnQuZWxlbWVudCA9IC8qKiBAdHlwZSB7YW55fSAqLyAoQ2xhc3MpO1xuXHRyZXR1cm4gQ2xhc3M7XG59XG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgU3ZlbHRlIGNvbXBvbmVudHMuIFVzZWQgd2hlbiBkZXY9ZmFsc2UuXG4gKlxuICogQHRlbXBsYXRlIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbUHJvcHM9YW55XVxuICogQHRlbXBsYXRlIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbRXZlbnRzPWFueV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN2ZWx0ZUNvbXBvbmVudCB7XG5cdC8qKlxuXHQgKiAjIyMgUFJJVkFURSBBUElcblx0ICpcblx0ICogRG8gbm90IHVzZSwgbWF5IGNoYW5nZSBhdCBhbnkgdGltZVxuXHQgKlxuXHQgKiBAdHlwZSB7YW55fVxuXHQgKi9cblx0JCQgPSB1bmRlZmluZWQ7XG5cdC8qKlxuXHQgKiAjIyMgUFJJVkFURSBBUElcblx0ICpcblx0ICogRG8gbm90IHVzZSwgbWF5IGNoYW5nZSBhdCBhbnkgdGltZVxuXHQgKlxuXHQgKiBAdHlwZSB7YW55fVxuXHQgKi9cblx0JCRzZXQgPSB1bmRlZmluZWQ7XG5cblx0LyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHQkZGVzdHJveSgpIHtcblx0XHRkZXN0cm95X2NvbXBvbmVudCh0aGlzLCAxKTtcblx0XHR0aGlzLiRkZXN0cm95ID0gbm9vcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAdGVtcGxhdGUge0V4dHJhY3Q8a2V5b2YgRXZlbnRzLCBzdHJpbmc+fSBLXG5cdCAqIEBwYXJhbSB7S30gdHlwZVxuXHQgKiBAcGFyYW0geygoZTogRXZlbnRzW0tdKSA9PiB2b2lkKSB8IG51bGwgfCB1bmRlZmluZWR9IGNhbGxiYWNrXG5cdCAqIEByZXR1cm5zIHsoKSA9PiB2b2lkfVxuXHQgKi9cblx0JG9uKHR5cGUsIGNhbGxiYWNrKSB7XG5cdFx0aWYgKCFpc19mdW5jdGlvbihjYWxsYmFjaykpIHtcblx0XHRcdHJldHVybiBub29wO1xuXHRcdH1cblx0XHRjb25zdCBjYWxsYmFja3MgPSB0aGlzLiQkLmNhbGxiYWNrc1t0eXBlXSB8fCAodGhpcy4kJC5jYWxsYmFja3NbdHlwZV0gPSBbXSk7XG5cdFx0Y2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRjb25zdCBpbmRleCA9IGNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKTtcblx0XHRcdGlmIChpbmRleCAhPT0gLTEpIGNhbGxiYWNrcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtQYXJ0aWFsPFByb3BzPn0gcHJvcHNcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHQkc2V0KHByb3BzKSB7XG5cdFx0aWYgKHRoaXMuJCRzZXQgJiYgIWlzX2VtcHR5KHByb3BzKSkge1xuXHRcdFx0dGhpcy4kJC5za2lwX2JvdW5kID0gdHJ1ZTtcblx0XHRcdHRoaXMuJCRzZXQocHJvcHMpO1xuXHRcdFx0dGhpcy4kJC5za2lwX2JvdW5kID0gZmFsc2U7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQ3VzdG9tRWxlbWVudFByb3BEZWZpbml0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2F0dHJpYnV0ZV1cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3JlZmxlY3RdXG4gKiBAcHJvcGVydHkgeydTdHJpbmcnfCdCb29sZWFuJ3wnTnVtYmVyJ3wnQXJyYXknfCdPYmplY3QnfSBbdHlwZV1cbiAqL1xuIiwgIi8vIGdlbmVyYXRlZCBkdXJpbmcgcmVsZWFzZSwgZG8gbm90IG1vZGlmeVxuXG4vKipcbiAqIFRoZSBjdXJyZW50IHZlcnNpb24sIGFzIHNldCBpbiBwYWNrYWdlLmpzb24uXG4gKlxuICogaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3Mvc3ZlbHRlLWNvbXBpbGVyI3N2ZWx0ZS12ZXJzaW9uXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9ICc0LjIuMTEnO1xuZXhwb3J0IGNvbnN0IFBVQkxJQ19WRVJTSU9OID0gJzQnO1xuIiwgImltcG9ydCB7IFBVQkxJQ19WRVJTSU9OIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3ZlcnNpb24uanMnO1xuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpXG5cdC8vIEB0cy1pZ25vcmVcblx0KHdpbmRvdy5fX3N2ZWx0ZSB8fCAod2luZG93Ll9fc3ZlbHRlID0geyB2OiBuZXcgU2V0KCkgfSkpLnYuYWRkKFBVQkxJQ19WRVJTSU9OKTtcbiIsICI8c2NyaXB0IGxhbmc9XCJ0c1wiPlxuXHRpbXBvcnQgeyB0eXBlIEV2ZW50UmVmLCB0eXBlIFZhdWx0LCB0eXBlIFdvcmtzcGFjZSB9IGZyb20gXCJvYnNpZGlhblwiO1xuXHRpbXBvcnQgeyBjcmVhdGVUYXNrc1N0b3JlIH0gZnJvbSBcIi4vdGFza3Mvc3RvcmVcIjtcblx0aW1wb3J0IHtcblx0XHRjb2x1bW5UYWdUYWJsZVN0b3JlLFxuXHRcdGNyZWF0ZUNvbHVtblRhZ1RhYmxlLFxuXHRcdHR5cGUgQ29sdW1uQ29uZmlnLFxuXHRcdHR5cGUgQ29sdW1uVGFnLFxuXHRcdHR5cGUgRGVmYXVsdENvbHVtbnMsXG5cdH0gZnJvbSBcIi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuL3Rhc2tzL3Rhc2tcIjtcblx0aW1wb3J0IENvbHVtbiBmcm9tIFwiLi9jb21wb25lbnRzL2NvbHVtbi5zdmVsdGVcIjtcblxuXHRleHBvcnQgbGV0IHZhdWx0OiBWYXVsdDtcblx0ZXhwb3J0IGxldCB3b3Jrc3BhY2U6IFdvcmtzcGFjZTtcblx0ZXhwb3J0IGxldCByZWdpc3RlckV2ZW50OiAoZXZlbnRSZWY6IEV2ZW50UmVmKSA9PiB2b2lkO1xuXHRleHBvcnQgbGV0IGNvbHVtbkNvbmZpZzogQ29sdW1uQ29uZmlnID0ge1xuXHRcdGNvbHVtbnM6IFtcIkxhdGVyXCIsIFwiTmV4dCB3ZWVrXCIsIFwiVGhpcyB3ZWVrXCIsIFwiVG9kYXlcIiwgXCJQZW5kaW5nXCJdLFxuXHR9O1xuXG5cdCQ6IGNvbHVtblRhZ1RhYmxlU3RvcmUuc2V0KGNyZWF0ZUNvbHVtblRhZ1RhYmxlKGNvbHVtbkNvbmZpZykpO1xuXG5cdGNvbnN0IHsgdGFza3NTdG9yZSwgdGFza0FjdGlvbnMgfSA9IGNyZWF0ZVRhc2tzU3RvcmUoXG5cdFx0dmF1bHQsXG5cdFx0d29ya3NwYWNlLFxuXHRcdHJlZ2lzdGVyRXZlbnQsXG5cdFx0Y29sdW1uVGFnVGFibGVTdG9yZSxcblx0KTtcblxuXHRmdW5jdGlvbiBncm91cEJ5Q29sdW1uVGFnKFxuXHRcdHRhc2tzOiBUYXNrW10sXG5cdCk6IFJlY29yZDxDb2x1bW5UYWcgfCBEZWZhdWx0Q29sdW1ucywgVGFza1tdPiB7XG5cdFx0Y29uc3Qgb3V0cHV0OiBSZWNvcmQ8Q29sdW1uVGFnIHwgRGVmYXVsdENvbHVtbnMsIFRhc2tbXT4gPSB7XG5cdFx0XHR1bmNhdGVnb3Jpc2VkOiBbXSxcblx0XHRcdGRvbmU6IFtdLFxuXHRcdH07XG5cdFx0Zm9yIChjb25zdCB0YXNrIG9mIHRhc2tzKSB7XG5cdFx0XHRpZiAodGFzay5kb25lKSB7XG5cdFx0XHRcdG91dHB1dFtcImRvbmVcIl0gPSBvdXRwdXRbXCJkb25lXCJdLmNvbmNhdCh0YXNrKTtcblx0XHRcdH0gZWxzZSBpZiAodGFzay5jb2x1bW4pIHtcblx0XHRcdFx0b3V0cHV0W3Rhc2suY29sdW1uXSA9IChvdXRwdXRbdGFzay5jb2x1bW5dID8/IFtdKS5jb25jYXQodGFzayk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXRbXCJ1bmNhdGVnb3Jpc2VkXCJdID0gb3V0cHV0W1widW5jYXRlZ29yaXNlZFwiXS5jb25jYXQodGFzayk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH1cblxuXHRsZXQgY29sdW1uczogKFwidW5jYXRlZ29yaXNlZFwiIHwgQ29sdW1uVGFnKVtdO1xuXHQkOiBjb2x1bW5zID0gT2JqZWN0LmtleXMoJGNvbHVtblRhZ1RhYmxlU3RvcmUpIGFzIENvbHVtblRhZ1tdO1xuXG5cdCQ6IHRhc2tzQnlDb2x1bW4gPSBncm91cEJ5Q29sdW1uVGFnKCR0YXNrc1N0b3JlKTtcbjwvc2NyaXB0PlxuXG48c2VjdGlvbj5cblx0PGgxPlByb2plY3QgUGxhbm5lcjwvaDE+XG5cdDxkaXYgY2xhc3M9XCJjb2x1bW5zXCI+XG5cdFx0PGRpdj5cblx0XHRcdDxDb2x1bW5cblx0XHRcdFx0Y29sdW1uPXtcInVuY2F0ZWdvcmlzZWRcIn1cblx0XHRcdFx0aGlkZU9uRW1wdHk9e3RydWV9XG5cdFx0XHRcdHRhc2tzPXt0YXNrc0J5Q29sdW1uW1widW5jYXRlZ29yaXNlZFwiXX1cblx0XHRcdFx0e3Rhc2tBY3Rpb25zfVxuXHRcdFx0Lz5cblx0XHRcdHsjZWFjaCBjb2x1bW5zIGFzIGNvbHVtbn1cblx0XHRcdFx0PENvbHVtblxuXHRcdFx0XHRcdHtjb2x1bW59XG5cdFx0XHRcdFx0dGFza3M9e3Rhc2tzQnlDb2x1bW5bY29sdW1uXSA/PyBbXX1cblx0XHRcdFx0XHR7dGFza0FjdGlvbnN9XG5cdFx0XHRcdC8+XG5cdFx0XHR7L2VhY2h9XG5cdFx0XHQ8Q29sdW1uXG5cdFx0XHRcdGNvbHVtbj1cImRvbmVcIlxuXHRcdFx0XHR0YXNrcz17dGFza3NCeUNvbHVtbltcImRvbmVcIl0gPz8gW119XG5cdFx0XHRcdHt0YXNrQWN0aW9uc31cblx0XHRcdC8+XG5cdFx0PC9kaXY+XG5cdDwvZGl2PlxuPC9zZWN0aW9uPlxuXG48c3R5bGU+XG5cdC5jb2x1bW5zIHtcblx0XHRtYXgtd2lkdGg6IDEwMHZ3O1xuXHRcdG92ZXJmbG93LXg6IHNjcm9sbDtcblx0XHRwYWRkaW5nLWJvdHRvbTogdmFyKC0tc2l6ZS00LTMpO1xuXHR9XG5cblx0LmNvbHVtbnMgPiBkaXYge1xuXHRcdGRpc3BsYXk6IGZsZXg7XG5cdFx0Z2FwOiB2YXIoLS1zaXplLTQtMyk7XG5cdH1cbjwvc3R5bGU+XG4iLCAiaW1wb3J0IHsgVEZpbGUsIFZhdWx0LCB0eXBlIEV2ZW50UmVmLCBXb3Jrc3BhY2UgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IHVwZGF0ZU1hcHNGcm9tRmlsZSwgdHlwZSBNZXRhZGF0YSB9IGZyb20gXCIuL3Rhc2tzXCI7XG5pbXBvcnQgeyBUYXNrIH0gZnJvbSBcIi4vdGFza1wiO1xuaW1wb3J0IHsgd3JpdGFibGUsIHR5cGUgV3JpdGFibGUgfSBmcm9tIFwic3ZlbHRlL3N0b3JlXCI7XG5pbXBvcnQgdHlwZSB7IENvbHVtblRhZ1RhYmxlIH0gZnJvbSBcIi4uL2NvbHVtbnMvY29sdW1uc1wiO1xuaW1wb3J0IHsgY3JlYXRlVGFza0FjdGlvbnMsIHR5cGUgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi9hY3Rpb25zXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUYXNrc1N0b3JlKFxuXHR2YXVsdDogVmF1bHQsXG5cdHdvcmtzcGFjZTogV29ya3NwYWNlLFxuXHRyZWdpc3RlckV2ZW50OiAoZXZlbnRSZWY6IEV2ZW50UmVmKSA9PiB2b2lkLFxuXHRjb2x1bW5UYWdUYWJsZVN0b3JlOiBXcml0YWJsZTxDb2x1bW5UYWdUYWJsZT5cbik6IHsgdGFza3NTdG9yZTogV3JpdGFibGU8VGFza1tdPjsgdGFza0FjdGlvbnM6IFRhc2tBY3Rpb25zIH0ge1xuXHRjb25zdCB0YXNrc1N0b3JlID0gd3JpdGFibGU8VGFza1tdPihbXSk7XG5cdGxldCB0aW1lcjogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG5cdGNvbnN0IHRhc2tzQnlUYXNrSWQgPSBuZXcgTWFwPHN0cmluZywgVGFzaz4oKTtcblx0Y29uc3QgbWV0YWRhdGFCeVRhc2tJZCA9IG5ldyBNYXA8c3RyaW5nLCBNZXRhZGF0YT4oKTtcblx0Y29uc3QgdGFza0lkc0J5RmlsZUhhbmRsZSA9IG5ldyBNYXA8VEZpbGUsIFNldDxzdHJpbmc+PigpO1xuXG5cdGNvbnN0IGZpbGVIYW5kbGVzID0gdmF1bHQuZ2V0TWFya2Rvd25GaWxlcygpO1xuXG5cdGZ1bmN0aW9uIGRlYm91bmNlU2V0VGFza3MoKSB7XG5cdFx0aWYgKCF0aW1lcikge1xuXHRcdFx0dGltZXIgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdHRpbWVyID0gdW5kZWZpbmVkO1xuXHRcdFx0XHR0YXNrc1N0b3JlLnNldChbLi4udGFza3NCeVRhc2tJZC52YWx1ZXMoKV0pO1xuXHRcdFx0fSwgNTApO1xuXHRcdH1cblx0fVxuXG5cdGZvciAoY29uc3QgZmlsZUhhbmRsZSBvZiBmaWxlSGFuZGxlcykge1xuXHRcdHVwZGF0ZU1hcHNGcm9tRmlsZSh7XG5cdFx0XHRmaWxlSGFuZGxlLFxuXHRcdFx0dGFza3NCeVRhc2tJZCxcblx0XHRcdG1ldGFkYXRhQnlUYXNrSWQsXG5cdFx0XHR0YXNrSWRzQnlGaWxlSGFuZGxlLFxuXHRcdFx0dmF1bHQsXG5cdFx0XHRjb2x1bW5UYWdUYWJsZVN0b3JlLFxuXHRcdH0pLnRoZW4oKCkgPT4ge1xuXHRcdFx0ZGVib3VuY2VTZXRUYXNrcygpO1xuXHRcdH0pO1xuXHR9XG5cblx0cmVnaXN0ZXJFdmVudChcblx0XHR2YXVsdC5vbihcIm1vZGlmeVwiLCAoZmlsZUhhbmRsZSkgPT4ge1xuXHRcdFx0aWYgKGZpbGVIYW5kbGUgaW5zdGFuY2VvZiBURmlsZSkge1xuXHRcdFx0XHR1cGRhdGVNYXBzRnJvbUZpbGUoe1xuXHRcdFx0XHRcdGZpbGVIYW5kbGUsXG5cdFx0XHRcdFx0dGFza3NCeVRhc2tJZCxcblx0XHRcdFx0XHRtZXRhZGF0YUJ5VGFza0lkLFxuXHRcdFx0XHRcdHRhc2tJZHNCeUZpbGVIYW5kbGUsXG5cdFx0XHRcdFx0dmF1bHQsXG5cdFx0XHRcdFx0Y29sdW1uVGFnVGFibGVTdG9yZSxcblx0XHRcdFx0fSkudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0ZGVib3VuY2VTZXRUYXNrcygpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KVxuXHQpO1xuXG5cdHJlZ2lzdGVyRXZlbnQoXG5cdFx0dmF1bHQub24oXCJjcmVhdGVcIiwgKGZpbGVIYW5kbGUpID0+IHtcblx0XHRcdGlmIChmaWxlSGFuZGxlIGluc3RhbmNlb2YgVEZpbGUpIHtcblx0XHRcdFx0dXBkYXRlTWFwc0Zyb21GaWxlKHtcblx0XHRcdFx0XHRmaWxlSGFuZGxlLFxuXHRcdFx0XHRcdHRhc2tzQnlUYXNrSWQsXG5cdFx0XHRcdFx0bWV0YWRhdGFCeVRhc2tJZCxcblx0XHRcdFx0XHR0YXNrSWRzQnlGaWxlSGFuZGxlLFxuXHRcdFx0XHRcdHZhdWx0LFxuXHRcdFx0XHRcdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG5cdFx0XHRcdH0pLnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdGRlYm91bmNlU2V0VGFza3MoKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRyZWdpc3RlckV2ZW50KFxuXHRcdHZhdWx0Lm9uKFwiZGVsZXRlXCIsIChmaWxlSGFuZGxlKSA9PiB7XG5cdFx0XHRpZiAoZmlsZUhhbmRsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XG5cdFx0XHRcdC8vIFRPRE8gaW1wbGVtZW50XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRyZWdpc3RlckV2ZW50KFxuXHRcdHZhdWx0Lm9uKFwicmVuYW1lXCIsIChmaWxlSGFuZGxlKSA9PiB7XG5cdFx0XHRpZiAoZmlsZUhhbmRsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XG5cdFx0XHRcdC8vIFRPRE8gaW1wbGVtZW50XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRjb25zdCB0YXNrQWN0aW9ucyA9IGNyZWF0ZVRhc2tBY3Rpb25zKHtcblx0XHR0YXNrc0J5VGFza0lkLFxuXHRcdG1ldGFkYXRhQnlUYXNrSWQsXG5cdFx0dmF1bHQsXG5cdFx0d29ya3NwYWNlLFxuXHR9KTtcblxuXHRyZXR1cm4geyB0YXNrc1N0b3JlLCB0YXNrQWN0aW9ucyB9O1xufVxuIiwgImltcG9ydCBzaGEyNTYgZnJvbSBcImNyeXB0by1qcy9zaGEyNTZcIjtcbmltcG9ydCB0eXBlIHsgQnJhbmQgfSBmcm9tIFwic3JjL2JyYW5kXCI7XG5pbXBvcnQgdHlwZSB7XG5cdENvbHVtblRhZyxcblx0Q29sdW1uVGFnVGFibGUsXG5cdERlZmF1bHRDb2x1bW5zLFxufSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cbmV4cG9ydCBjbGFzcyBUYXNrIHtcblx0cmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cmVhZG9ubHkgY29udGVudDogc3RyaW5nO1xuXHRyZWFkb25seSBkb25lOiBib29sZWFuO1xuXHRyZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJvd0luZGV4OiBudW1iZXI7XG5cdHJlYWRvbmx5IGNvbHVtbjpcblx0XHR8IENvbHVtblRhZ1xuXHRcdHwgRXhjbHVkZTxEZWZhdWx0Q29sdW1ucywgXCJ1bmNhdGVnb3Jpc2VkXCI+XG5cdFx0fCB1bmRlZmluZWQ7XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cmF3Q29udGVudDogVGFza1N0cmluZyxcblx0XHRmaWxlSGFuZGxlOiB7IHBhdGg6IHN0cmluZyB9LFxuXHRcdHJvd0luZGV4OiBudW1iZXIsXG5cdFx0Y29sdW1uVGFnVGFibGU6IENvbHVtblRhZ1RhYmxlXG5cdCkge1xuXHRcdGNvbnN0IHRhc2sgPSB0aGlzLl9kZXNlcmlhbGlzZShyYXdDb250ZW50LCBmaWxlSGFuZGxlLCByb3dJbmRleCk7XG5cdFx0dGhpcy5pZCA9IHRhc2suaWQ7XG5cdFx0dGhpcy5jb250ZW50ID0gdGFzay5jb250ZW50O1xuXHRcdHRoaXMuZG9uZSA9IHRhc2suZG9uZTtcblx0XHR0aGlzLnBhdGggPSBmaWxlSGFuZGxlLnBhdGg7XG5cdFx0dGhpcy5yb3dJbmRleCA9IHJvd0luZGV4O1xuXG5cdFx0bGV0IGNvbHVtbjogQ29sdW1uVGFnIHwgdW5kZWZpbmVkO1xuXHRcdGZvciAoY29uc3QgdGFnIG9mIHRhc2sudGFncykge1xuXHRcdFx0aWYgKHRhZyBpbiBjb2x1bW5UYWdUYWJsZSB8fCB0YWcgPT09IFwiZG9uZVwiKSB7XG5cdFx0XHRcdGNvbHVtbiA9IHRhZyBhcyBDb2x1bW5UYWc7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuY29sdW1uID0gY29sdW1uO1xuXHR9XG5cblx0cHJpdmF0ZSBfZGVzZXJpYWxpc2UoXG5cdFx0cmF3Q29udGVudDogVGFza1N0cmluZyxcblx0XHRmaWxlSGFuZGxlOiB7IHBhdGg6IHN0cmluZyB9LFxuXHRcdHJvd0luZGV4OiBudW1iZXJcblx0KToge1xuXHRcdGlkOiBzdHJpbmc7XG5cdFx0Y29udGVudDogc3RyaW5nO1xuXHRcdGRvbmU6IGJvb2xlYW47XG5cdFx0dGFnczogc3RyaW5nW107XG5cdH0ge1xuXHRcdGNvbnN0IFssIHJlbWFpbmRlciA9IFwiXCJdID0gcmF3Q29udGVudC5zcGxpdChcIi0gW1wiKTtcblx0XHRjb25zdCBbc3RhdHVzLCBjb250ZW50ID0gXCJcIl0gPSByZW1haW5kZXIuc3BsaXQoXCJdIFwiKTtcblxuXHRcdGNvbnN0IHsgdGFncywgY2xlYW5lZENvbnRlbnQgfSA9IGdldFRhZ3MoY29udGVudCk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0aWQ6IHNoYTI1Nihjb250ZW50ICsgZmlsZUhhbmRsZS5wYXRoICsgcm93SW5kZXgpLnRvU3RyaW5nKCksXG5cdFx0XHRkb25lOiBzdGF0dXMgPT09IFwieFwiLFxuXHRcdFx0Y29udGVudDogY2xlYW5lZENvbnRlbnQsXG5cdFx0XHR0YWdzLFxuXHRcdH07XG5cdH1cblxuXHRzZXJpYWxpc2UoXG5cdFx0ZGF0YTogUGFydGlhbDx7XG5cdFx0XHRjb2x1bW46IENvbHVtblRhZyB8IEV4Y2x1ZGU8RGVmYXVsdENvbHVtbnMsIFwidW5jYXRlZ29yaXNlZFwiPjtcblx0XHR9PlxuXHQpOiBzdHJpbmcge1xuXHRcdGNvbnN0IGRvbmUgPSBkYXRhLmNvbHVtbiA9PT0gXCJkb25lXCIgfHwgdGhpcy5kb25lO1xuXHRcdGNvbnN0IGNvbHVtbjpcblx0XHRcdHwgQ29sdW1uVGFnXG5cdFx0XHR8IEV4Y2x1ZGU8RGVmYXVsdENvbHVtbnMsIFwidW5jYXRlZ29yaXNlZFwiPlxuXHRcdFx0fCB1bmRlZmluZWQgPSBkYXRhLmNvbHVtbiA/PyB0aGlzLmNvbHVtbjtcblxuXHRcdHJldHVybiBgLSBbJHtkb25lID8gXCJ4XCIgOiBcIiBcIn1dICR7dGhpcy5jb250ZW50fSR7XG5cdFx0XHRjb2x1bW4gPyBgICMke2NvbHVtbn1gIDogXCJcIlxuXHRcdH1gO1xuXHR9XG59XG5cbnR5cGUgVGFza1N0cmluZyA9IEJyYW5kPHN0cmluZywgXCJUYXNrU3RyaW5nXCI+O1xuXG5leHBvcnQgZnVuY3Rpb24gaXNUYXNrU3RyaW5nKGlucHV0OiBzdHJpbmcpOiBpbnB1dCBpcyBUYXNrU3RyaW5nIHtcblx0cmV0dXJuIHRhc2tTdHJpbmdSZWdleC50ZXN0KGlucHV0KTtcbn1cblxuLy8gYmVnaW5zIHdpdGggMCBvciBtb3JlIHdoaXRlc3BhY2UgY2hhcnNcbi8vIHRoZW4gZm9sbG93cyB0aGUgcGF0dGVybiBcIi0gWyBdXCIgT1IgXCItIFt4XVwiXG4vLyB0aGVuIGNvbnRhaW5zIGFuIGFkZGl0aW9uYWwgd2hpdGVzcGFjZSBiZWZvcmUgYW55IHRyYWlsaW5nIGNvbnRlbnRcbmNvbnN0IHRhc2tTdHJpbmdSZWdleCA9IC9eXFxzKi1cXHNcXFtbeFxcc11cXF1cXHMvO1xuXG5mdW5jdGlvbiBnZXRUYWdzKGNvbnRlbnQ6IHN0cmluZyk6IHsgdGFnczogc3RyaW5nW107IGNsZWFuZWRDb250ZW50OiBzdHJpbmcgfSB7XG5cdGNvbnN0IHRhZ3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcblx0bGV0IGNsZWFuZWRDb250ZW50ID0gY29udGVudDtcblxuXHQvLyBzdGFydHMgd2l0aCBcIiNcIiwgZW5kcyB3aXRoIFwiIFwiLCBvbmx5IGNvbnRhaW5zIGFscGhhbnVtZXJpY3Mgb3IgXCItXCJcblx0Y29uc3QgYWxsTWF0Y2hlcyA9IGNvbnRlbnQubWF0Y2hBbGwoLyMoW1xcdy1dKykvZyk7XG5cdGZvciAoY29uc3QgbWF0Y2ggb2YgWy4uLmFsbE1hdGNoZXNdKSB7XG5cdFx0Y29uc3QgbWF5YmVUYWcgPSBtYXRjaFsxXTtcblx0XHRpZiAobWF5YmVUYWcpIHtcblx0XHRcdHRhZ3MuYWRkKG1heWJlVGFnKTtcblxuXHRcdFx0Y2xlYW5lZENvbnRlbnQgPSBjbGVhbmVkQ29udGVudC5yZXBsYWNlQWxsKGAjJHttYXliZVRhZ31gLCBcIlwiKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4geyB0YWdzOiBbLi4udGFnc10sIGNsZWFuZWRDb250ZW50OiBjbGVhbmVkQ29udGVudC50cmltKCkgfTtcbn1cbiIsICJpbXBvcnQge1xuXHRydW5fYWxsLFxuXHRzdWJzY3JpYmUsXG5cdG5vb3AsXG5cdHNhZmVfbm90X2VxdWFsLFxuXHRpc19mdW5jdGlvbixcblx0Z2V0X3N0b3JlX3ZhbHVlXG59IGZyb20gJy4uL2ludGVybmFsL2luZGV4LmpzJztcblxuY29uc3Qgc3Vic2NyaWJlcl9xdWV1ZSA9IFtdO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBgUmVhZGFibGVgIHN0b3JlIHRoYXQgYWxsb3dzIHJlYWRpbmcgYnkgc3Vic2NyaXB0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNyZWFkYWJsZVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7VH0gW3ZhbHVlXSBpbml0aWFsIHZhbHVlXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdGFydFN0b3BOb3RpZmllcjxUPn0gW3N0YXJ0XVxuICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5SZWFkYWJsZTxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRhYmxlKHZhbHVlLCBzdGFydCkge1xuXHRyZXR1cm4ge1xuXHRcdHN1YnNjcmliZTogd3JpdGFibGUodmFsdWUsIHN0YXJ0KS5zdWJzY3JpYmVcblx0fTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBgV3JpdGFibGVgIHN0b3JlIHRoYXQgYWxsb3dzIGJvdGggdXBkYXRpbmcgYW5kIHJlYWRpbmcgYnkgc3Vic2NyaXB0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSN3cml0YWJsZVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7VH0gW3ZhbHVlXSBpbml0aWFsIHZhbHVlXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdGFydFN0b3BOb3RpZmllcjxUPn0gW3N0YXJ0XVxuICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5Xcml0YWJsZTxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRhYmxlKHZhbHVlLCBzdGFydCA9IG5vb3ApIHtcblx0LyoqIEB0eXBlIHtpbXBvcnQoJy4vcHVibGljLmpzJykuVW5zdWJzY3JpYmVyfSAqL1xuXHRsZXQgc3RvcDtcblx0LyoqIEB0eXBlIHtTZXQ8aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdWJzY3JpYmVJbnZhbGlkYXRlVHVwbGU8VD4+fSAqL1xuXHRjb25zdCBzdWJzY3JpYmVycyA9IG5ldyBTZXQoKTtcblx0LyoqIEBwYXJhbSB7VH0gbmV3X3ZhbHVlXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0ZnVuY3Rpb24gc2V0KG5ld192YWx1ZSkge1xuXHRcdGlmIChzYWZlX25vdF9lcXVhbCh2YWx1ZSwgbmV3X3ZhbHVlKSkge1xuXHRcdFx0dmFsdWUgPSBuZXdfdmFsdWU7XG5cdFx0XHRpZiAoc3RvcCkge1xuXHRcdFx0XHQvLyBzdG9yZSBpcyByZWFkeVxuXHRcdFx0XHRjb25zdCBydW5fcXVldWUgPSAhc3Vic2NyaWJlcl9xdWV1ZS5sZW5ndGg7XG5cdFx0XHRcdGZvciAoY29uc3Qgc3Vic2NyaWJlciBvZiBzdWJzY3JpYmVycykge1xuXHRcdFx0XHRcdHN1YnNjcmliZXJbMV0oKTtcblx0XHRcdFx0XHRzdWJzY3JpYmVyX3F1ZXVlLnB1c2goc3Vic2NyaWJlciwgdmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChydW5fcXVldWUpIHtcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHN1YnNjcmliZXJfcXVldWUubGVuZ3RoOyBpICs9IDIpIHtcblx0XHRcdFx0XHRcdHN1YnNjcmliZXJfcXVldWVbaV1bMF0oc3Vic2NyaWJlcl9xdWV1ZVtpICsgMV0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzdWJzY3JpYmVyX3F1ZXVlLmxlbmd0aCA9IDA7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtpbXBvcnQoJy4vcHVibGljLmpzJykuVXBkYXRlcjxUPn0gZm5cblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRmdW5jdGlvbiB1cGRhdGUoZm4pIHtcblx0XHRzZXQoZm4odmFsdWUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdWJzY3JpYmVyPFQ+fSBydW5cblx0ICogQHBhcmFtIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkludmFsaWRhdG9yPFQ+fSBbaW52YWxpZGF0ZV1cblx0ICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5VbnN1YnNjcmliZXJ9XG5cdCAqL1xuXHRmdW5jdGlvbiBzdWJzY3JpYmUocnVuLCBpbnZhbGlkYXRlID0gbm9vcCkge1xuXHRcdC8qKiBAdHlwZSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdWJzY3JpYmVJbnZhbGlkYXRlVHVwbGU8VD59ICovXG5cdFx0Y29uc3Qgc3Vic2NyaWJlciA9IFtydW4sIGludmFsaWRhdGVdO1xuXHRcdHN1YnNjcmliZXJzLmFkZChzdWJzY3JpYmVyKTtcblx0XHRpZiAoc3Vic2NyaWJlcnMuc2l6ZSA9PT0gMSkge1xuXHRcdFx0c3RvcCA9IHN0YXJ0KHNldCwgdXBkYXRlKSB8fCBub29wO1xuXHRcdH1cblx0XHRydW4odmFsdWUpO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRzdWJzY3JpYmVycy5kZWxldGUoc3Vic2NyaWJlcik7XG5cdFx0XHRpZiAoc3Vic2NyaWJlcnMuc2l6ZSA9PT0gMCAmJiBzdG9wKSB7XG5cdFx0XHRcdHN0b3AoKTtcblx0XHRcdFx0c3RvcCA9IG51bGw7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXHRyZXR1cm4geyBzZXQsIHVwZGF0ZSwgc3Vic2NyaWJlIH07XG59XG5cbi8qKlxuICogRGVyaXZlZCB2YWx1ZSBzdG9yZSBieSBzeW5jaHJvbml6aW5nIG9uZSBvciBtb3JlIHJlYWRhYmxlIHN0b3JlcyBhbmRcbiAqIGFwcGx5aW5nIGFuIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIG92ZXIgaXRzIGlucHV0IHZhbHVlcy5cbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUtc3RvcmUjZGVyaXZlZFxuICogQHRlbXBsYXRlIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc30gU1xuICogQHRlbXBsYXRlIFRcbiAqIEBvdmVybG9hZFxuICogQHBhcmFtIHtTfSBzdG9yZXMgLSBpbnB1dCBzdG9yZXNcbiAqIEBwYXJhbSB7KHZhbHVlczogaW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdG9yZXNWYWx1ZXM8Uz4sIHNldDogKHZhbHVlOiBUKSA9PiB2b2lkLCB1cGRhdGU6IChmbjogaW1wb3J0KCcuL3B1YmxpYy5qcycpLlVwZGF0ZXI8VD4pID0+IHZvaWQpID0+IGltcG9ydCgnLi9wdWJsaWMuanMnKS5VbnN1YnNjcmliZXIgfCB2b2lkfSBmbiAtIGZ1bmN0aW9uIGNhbGxiYWNrIHRoYXQgYWdncmVnYXRlcyB0aGUgdmFsdWVzXG4gKiBAcGFyYW0ge1R9IFtpbml0aWFsX3ZhbHVlXSAtIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8VD59XG4gKi9cblxuLyoqXG4gKiBEZXJpdmVkIHZhbHVlIHN0b3JlIGJ5IHN5bmNocm9uaXppbmcgb25lIG9yIG1vcmUgcmVhZGFibGUgc3RvcmVzIGFuZFxuICogYXBwbHlpbmcgYW4gYWdncmVnYXRpb24gZnVuY3Rpb24gb3ZlciBpdHMgaW5wdXQgdmFsdWVzLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNkZXJpdmVkXG4gKiBAdGVtcGxhdGUge2ltcG9ydCgnLi9wcml2YXRlLmpzJykuU3RvcmVzfSBTXG4gKiBAdGVtcGxhdGUgVFxuICogQG92ZXJsb2FkXG4gKiBAcGFyYW0ge1N9IHN0b3JlcyAtIGlucHV0IHN0b3Jlc1xuICogQHBhcmFtIHsodmFsdWVzOiBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc1ZhbHVlczxTPikgPT4gVH0gZm4gLSBmdW5jdGlvbiBjYWxsYmFjayB0aGF0IGFnZ3JlZ2F0ZXMgdGhlIHZhbHVlc1xuICogQHBhcmFtIHtUfSBbaW5pdGlhbF92YWx1ZV0gLSBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fVxuICovXG5cbi8qKlxuICogQHRlbXBsYXRlIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc30gU1xuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7U30gc3RvcmVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHBhcmFtIHtUfSBbaW5pdGlhbF92YWx1ZV1cbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8VD59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVkKHN0b3JlcywgZm4sIGluaXRpYWxfdmFsdWUpIHtcblx0Y29uc3Qgc2luZ2xlID0gIUFycmF5LmlzQXJyYXkoc3RvcmVzKTtcblx0LyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8YW55Pj59ICovXG5cdGNvbnN0IHN0b3Jlc19hcnJheSA9IHNpbmdsZSA/IFtzdG9yZXNdIDogc3RvcmVzO1xuXHRpZiAoIXN0b3Jlc19hcnJheS5ldmVyeShCb29sZWFuKSkge1xuXHRcdHRocm93IG5ldyBFcnJvcignZGVyaXZlZCgpIGV4cGVjdHMgc3RvcmVzIGFzIGlucHV0LCBnb3QgYSBmYWxzeSB2YWx1ZScpO1xuXHR9XG5cdGNvbnN0IGF1dG8gPSBmbi5sZW5ndGggPCAyO1xuXHRyZXR1cm4gcmVhZGFibGUoaW5pdGlhbF92YWx1ZSwgKHNldCwgdXBkYXRlKSA9PiB7XG5cdFx0bGV0IHN0YXJ0ZWQgPSBmYWxzZTtcblx0XHRjb25zdCB2YWx1ZXMgPSBbXTtcblx0XHRsZXQgcGVuZGluZyA9IDA7XG5cdFx0bGV0IGNsZWFudXAgPSBub29wO1xuXHRcdGNvbnN0IHN5bmMgPSAoKSA9PiB7XG5cdFx0XHRpZiAocGVuZGluZykge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjbGVhbnVwKCk7XG5cdFx0XHRjb25zdCByZXN1bHQgPSBmbihzaW5nbGUgPyB2YWx1ZXNbMF0gOiB2YWx1ZXMsIHNldCwgdXBkYXRlKTtcblx0XHRcdGlmIChhdXRvKSB7XG5cdFx0XHRcdHNldChyZXN1bHQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y2xlYW51cCA9IGlzX2Z1bmN0aW9uKHJlc3VsdCkgPyByZXN1bHQgOiBub29wO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Y29uc3QgdW5zdWJzY3JpYmVycyA9IHN0b3Jlc19hcnJheS5tYXAoKHN0b3JlLCBpKSA9PlxuXHRcdFx0c3Vic2NyaWJlKFxuXHRcdFx0XHRzdG9yZSxcblx0XHRcdFx0KHZhbHVlKSA9PiB7XG5cdFx0XHRcdFx0dmFsdWVzW2ldID0gdmFsdWU7XG5cdFx0XHRcdFx0cGVuZGluZyAmPSB+KDEgPDwgaSk7XG5cdFx0XHRcdFx0aWYgKHN0YXJ0ZWQpIHtcblx0XHRcdFx0XHRcdHN5bmMoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdCgpID0+IHtcblx0XHRcdFx0XHRwZW5kaW5nIHw9IDEgPDwgaTtcblx0XHRcdFx0fVxuXHRcdFx0KVxuXHRcdCk7XG5cdFx0c3RhcnRlZCA9IHRydWU7XG5cdFx0c3luYygpO1xuXHRcdHJldHVybiBmdW5jdGlvbiBzdG9wKCkge1xuXHRcdFx0cnVuX2FsbCh1bnN1YnNjcmliZXJzKTtcblx0XHRcdGNsZWFudXAoKTtcblx0XHRcdC8vIFdlIG5lZWQgdG8gc2V0IHRoaXMgdG8gZmFsc2UgYmVjYXVzZSBjYWxsYmFja3MgY2FuIHN0aWxsIGhhcHBlbiBkZXNwaXRlIGhhdmluZyB1bnN1YnNjcmliZWQ6XG5cdFx0XHQvLyBDYWxsYmFja3MgbWlnaHQgYWxyZWFkeSBiZSBwbGFjZWQgaW4gdGhlIHF1ZXVlIHdoaWNoIGRvZXNuJ3Qga25vdyBpdCBzaG91bGQgbm8gbG9uZ2VyXG5cdFx0XHQvLyBpbnZva2UgdGhpcyBkZXJpdmVkIHN0b3JlLlxuXHRcdFx0c3RhcnRlZCA9IGZhbHNlO1xuXHRcdH07XG5cdH0pO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc3RvcmUgYW5kIHJldHVybnMgYSBuZXcgb25lIGRlcml2ZWQgZnJvbSB0aGUgb2xkIG9uZSB0aGF0IGlzIHJlYWRhYmxlLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNyZWFkb25seVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fSBzdG9yZSAgLSBzdG9yZSB0byBtYWtlIHJlYWRvbmx5XG4gKiBAcmV0dXJucyB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZG9ubHkoc3RvcmUpIHtcblx0cmV0dXJuIHtcblx0XHRzdWJzY3JpYmU6IHN0b3JlLnN1YnNjcmliZS5iaW5kKHN0b3JlKVxuXHR9O1xufVxuXG5leHBvcnQgeyBnZXRfc3RvcmVfdmFsdWUgYXMgZ2V0IH07XG4iLCAiaW1wb3J0IHR5cGUgeyBURmlsZSwgVmF1bHQgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IGlzVGFza1N0cmluZywgVGFzayB9IGZyb20gXCIuL3Rhc2tcIjtcbmltcG9ydCB0eXBlIHsgQ29sdW1uVGFnVGFibGUgfSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5pbXBvcnQgeyBnZXQsIHR5cGUgV3JpdGFibGUgfSBmcm9tIFwic3ZlbHRlL3N0b3JlXCI7XG5cbmV4cG9ydCB0eXBlIE1ldGFkYXRhID0ge1xuXHRyb3dJbmRleDogbnVtYmVyO1xuXHRmaWxlSGFuZGxlOiBURmlsZTtcbn07XG5cbi8qKlxuICogbXV0YXRlcyB0aGUgc3VwcGxpZWQgTWFwc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlTWFwc0Zyb21GaWxlKHtcblx0ZmlsZUhhbmRsZSxcblx0dGFza0lkc0J5RmlsZUhhbmRsZSxcblx0dGFza3NCeVRhc2tJZCxcblx0bWV0YWRhdGFCeVRhc2tJZCxcblx0dmF1bHQsXG5cdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG59OiB7XG5cdGZpbGVIYW5kbGU6IFRGaWxlO1xuXHR0YXNrc0J5VGFza0lkOiBNYXA8c3RyaW5nLCBUYXNrPjtcblx0bWV0YWRhdGFCeVRhc2tJZDogTWFwPHN0cmluZywgTWV0YWRhdGE+O1xuXHR0YXNrSWRzQnlGaWxlSGFuZGxlOiBNYXA8VEZpbGUsIFNldDxzdHJpbmc+Pjtcblx0dmF1bHQ6IFZhdWx0O1xuXHRjb2x1bW5UYWdUYWJsZVN0b3JlOiBXcml0YWJsZTxDb2x1bW5UYWdUYWJsZT47XG59KSB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgcHJldmlvdXNUYXNrSWRzID1cblx0XHRcdHRhc2tJZHNCeUZpbGVIYW5kbGUuZ2V0KGZpbGVIYW5kbGUpID8/IG5ldyBTZXQoKTtcblx0XHRjb25zdCBuZXdUYXNrSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cblx0XHRjb25zdCBjb250ZW50cyA9IGF3YWl0IHZhdWx0LnJlYWQoZmlsZUhhbmRsZSk7XG5cdFx0Y29uc3Qgcm93cyA9IGNvbnRlbnRzLnNwbGl0KFwiXFxuXCIpO1xuXHRcdGNvbnN0IGNvbHVtblRhZ1RhYmxlID0gZ2V0KGNvbHVtblRhZ1RhYmxlU3RvcmUpO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCByb3dzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCByb3cgPSByb3dzW2ldO1xuXHRcdFx0aWYgKCFyb3cpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChpc1Rhc2tTdHJpbmcocm93KSkge1xuXHRcdFx0XHRjb25zdCB0YXNrID0gbmV3IFRhc2socm93LCBmaWxlSGFuZGxlLCBpLCBjb2x1bW5UYWdUYWJsZSk7XG5cblx0XHRcdFx0bmV3VGFza0lkcy5hZGQodGFzay5pZCk7XG5cdFx0XHRcdHRhc2tzQnlUYXNrSWQuc2V0KHRhc2suaWQsIHRhc2spO1xuXHRcdFx0XHRtZXRhZGF0YUJ5VGFza0lkLnNldCh0YXNrLmlkLCB7IHJvd0luZGV4OiBpLCBmaWxlSGFuZGxlIH0pO1xuXHRcdFx0XHRwcmV2aW91c1Rhc2tJZHMuZGVsZXRlKHRhc2suaWQpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvciAoY29uc3QgcHJldklkIG9mIHByZXZpb3VzVGFza0lkcykge1xuXHRcdFx0dGFza3NCeVRhc2tJZC5kZWxldGUocHJldklkKTtcblx0XHRcdG1ldGFkYXRhQnlUYXNrSWQuZGVsZXRlKHByZXZJZCk7XG5cdFx0fVxuXG5cdFx0dGFza0lkc0J5RmlsZUhhbmRsZS5zZXQoZmlsZUhhbmRsZSwgbmV3VGFza0lkcyk7XG5cdH0gY2F0Y2gge1xuXHRcdC8vXG5cdH1cbn1cbiIsICJpbXBvcnQgeyBNYXJrZG93blZpZXcsIHR5cGUgVEZpbGUsIHR5cGUgVmF1bHQsIHR5cGUgV29ya3NwYWNlIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi90YXNrXCI7XG5pbXBvcnQgdHlwZSB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vdGFza3NcIjtcbmltcG9ydCB0eXBlIHsgQ29sdW1uVGFnLCBEZWZhdWx0Q29sdW1ucyB9IGZyb20gXCIuLi9jb2x1bW5zL2NvbHVtbnNcIjtcblxuZXhwb3J0IHR5cGUgVGFza0FjdGlvbnMgPSB7XG5cdGNoYW5nZUNvbHVtbjogKFxuXHRcdGlkOiBzdHJpbmcsXG5cdFx0bmV3Q29sdW1uOiBDb2x1bW5UYWcgfCBFeGNsdWRlPERlZmF1bHRDb2x1bW5zLCBcInVuY2F0ZWdvcmlzZWRcIj5cblx0KSA9PiBQcm9taXNlPHZvaWQ+O1xuXHR2aWV3RmlsZTogKGlkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGFza0FjdGlvbnMoe1xuXHR0YXNrc0J5VGFza0lkLFxuXHRtZXRhZGF0YUJ5VGFza0lkLFxuXHR2YXVsdCxcblx0d29ya3NwYWNlLFxufToge1xuXHR0YXNrc0J5VGFza0lkOiBNYXA8c3RyaW5nLCBUYXNrPjtcblx0bWV0YWRhdGFCeVRhc2tJZDogTWFwPHN0cmluZywgTWV0YWRhdGE+O1xuXHR2YXVsdDogVmF1bHQ7XG5cdHdvcmtzcGFjZTogV29ya3NwYWNlO1xufSk6IFRhc2tBY3Rpb25zIHtcblx0YXN5bmMgZnVuY3Rpb24gY2hhbmdlQ29sdW1uKFxuXHRcdGlkOiBzdHJpbmcsXG5cdFx0bmV3Q29sdW1uOiBDb2x1bW5UYWcgfCBFeGNsdWRlPERlZmF1bHRDb2x1bW5zLCBcInVuY2F0ZWdvcmlzZWRcIj5cblx0KSB7XG5cdFx0Y29uc3QgbWV0YWRhdGEgPSBtZXRhZGF0YUJ5VGFza0lkLmdldChpZCk7XG5cdFx0Y29uc3QgdGFzayA9IHRhc2tzQnlUYXNrSWQuZ2V0KGlkKTtcblxuXHRcdGlmICghbWV0YWRhdGEgfHwgIXRhc2spIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBuZXdUYXNrU3RyaW5nID0gdGFzay5zZXJpYWxpc2UoeyBjb2x1bW46IG5ld0NvbHVtbiB9KTtcblx0XHRhd2FpdCB1cGRhdGVSb3coXG5cdFx0XHR2YXVsdCxcblx0XHRcdG1ldGFkYXRhLmZpbGVIYW5kbGUsXG5cdFx0XHRtZXRhZGF0YS5yb3dJbmRleCxcblx0XHRcdG5ld1Rhc2tTdHJpbmdcblx0XHQpO1xuXHR9XG5cblx0YXN5bmMgZnVuY3Rpb24gdmlld0ZpbGUoaWQ6IHN0cmluZykge1xuXHRcdGNvbnN0IG1ldGFkYXRhID0gbWV0YWRhdGFCeVRhc2tJZC5nZXQoaWQpO1xuXG5cdFx0aWYgKCFtZXRhZGF0YSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IHsgZmlsZUhhbmRsZSwgcm93SW5kZXggfSA9IG1ldGFkYXRhO1xuXG5cdFx0Y29uc3QgbGVhZiA9IHdvcmtzcGFjZS5nZXRMZWFmKFwidGFiXCIpO1xuXHRcdGF3YWl0IGxlYWYub3BlbkZpbGUoZmlsZUhhbmRsZSk7XG5cdFx0Y29uc3QgZWRpdG9yVmlldyA9IHdvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG5cdFx0ZWRpdG9yVmlldz8uZWRpdG9yLnNldEN1cnNvcihyb3dJbmRleCk7XG5cdH1cblxuXHRyZXR1cm4geyBjaGFuZ2VDb2x1bW4sIHZpZXdGaWxlIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVJvdyhcblx0dmF1bHQ6IFZhdWx0LFxuXHRmaWxlSGFuZGxlOiBURmlsZSxcblx0cm93OiBudW1iZXIsXG5cdG5ld1RleHQ6IHN0cmluZ1xuKSB7XG5cdGNvbnN0IGZpbGUgPSBhd2FpdCB2YXVsdC5yZWFkKGZpbGVIYW5kbGUpO1xuXHRjb25zdCByb3dzID0gZmlsZS5zcGxpdChcIlxcblwiKTtcblxuXHRpZiAocm93cy5sZW5ndGggPCByb3cpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRyb3dzW3Jvd10gPSBuZXdUZXh0O1xuXHRjb25zdCBuZXdGaWxlID0gcm93cy5qb2luKFwiXFxuXCIpO1xuXHRhd2FpdCB2YXVsdC5tb2RpZnkoZmlsZUhhbmRsZSwgbmV3RmlsZSk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBCcmFuZCB9IGZyb20gXCJzcmMvYnJhbmRcIjtcbmltcG9ydCB7IHdyaXRhYmxlIH0gZnJvbSBcInN2ZWx0ZS9zdG9yZVwiO1xuXG5leHBvcnQgdHlwZSBDb2x1bW5Db25maWcgPSB7XG5cdGNvbHVtbnM6IHN0cmluZ1tdO1xufTtcblxuZXhwb3J0IHR5cGUgRGVmYXVsdENvbHVtbnMgPSBcInVuY2F0ZWdvcmlzZWRcIiB8IFwiZG9uZVwiO1xuZXhwb3J0IHR5cGUgQ29sdW1uVGFnID0gQnJhbmQ8c3RyaW5nLCBcIkNvbHVtblRhZ1wiPjtcblxuZXhwb3J0IHR5cGUgQ29sdW1uVGFnVGFibGUgPSBSZWNvcmQ8Q29sdW1uVGFnLCBzdHJpbmc+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29sdW1uVGFnVGFibGUoe1xuXHRjb2x1bW5zLFxufTogQ29sdW1uQ29uZmlnKTogQ29sdW1uVGFnVGFibGUge1xuXHRjb25zdCBvdXRwdXQ6IENvbHVtblRhZ1RhYmxlID0ge307XG5cblx0Zm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuXHRcdG91dHB1dFtrZWJhYihjb2x1bW4pXSA9IGNvbHVtbjtcblx0fVxuXG5cdHJldHVybiBvdXRwdXQ7XG59XG5cbmZ1bmN0aW9uIGtlYmFiKGlucHV0OiBzdHJpbmcpOiBDb2x1bW5UYWcge1xuXHRyZXR1cm4gaW5wdXRcblx0XHQudG9Mb3dlckNhc2UoKSAvLyBhbGwgYWxwaGFudW1lcmljIGNoYXJzIHRvIGxvd2VyIGNhc2Vcblx0XHQucmVwbGFjZUFsbCgvXFxzL2csIFwiLVwiKSAvLyByZXBsYWNlIGFsbCB3aGl0ZXNwYWNlIHdpdGggXCItXCJcblx0XHQucmVwbGFjZUFsbCgvW15hLXowLTktXS9nLCBcIlwiKSAvLyByZXBsYWNlIGFsbCBvdGhlciBjaGFycyB3aXRoIFwiXCJcblx0XHQucmVwbGFjZUFsbCgvLSsvZywgXCItXCIpIGFzIENvbHVtblRhZzsgLy8gY29sbGFwc2UgYW55IGNvbnNlY3V0aXZlIFwiLVwiIGludG8gYSBzaW5nbGUgXCItXCJcbn1cblxuZXhwb3J0IGNvbnN0IGNvbHVtblRhZ1RhYmxlU3RvcmUgPSB3cml0YWJsZTxDb2x1bW5UYWdUYWJsZT4oe30pO1xuIiwgIjxzY3JpcHQgbGFuZz1cInRzXCI+XG5cdGltcG9ydCB7IE1lbnUsIHNldEljb24gfSBmcm9tIFwib2JzaWRpYW5cIjtcblx0aW1wb3J0IHsgY29sdW1uVGFnVGFibGVTdG9yZSwgdHlwZSBDb2x1bW5UYWcgfSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuLi90YXNrcy90YXNrXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi4vdGFza3MvYWN0aW9uc1wiO1xuXG5cdGV4cG9ydCBsZXQgdGFzazogVGFzaztcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG5cblx0bGV0IGVsZW1lbnQ6IEhUTUxTcGFuRWxlbWVudDtcblx0JDoge1xuXHRcdGlmIChlbGVtZW50KSB7XG5cdFx0XHRzZXRJY29uKGVsZW1lbnQsIFwibHVjaWRlLW1vcmUtdmVydGljYWxcIik7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gc2hvd01lbnUoZTogTW91c2VFdmVudCkge1xuXHRcdGNvbnN0IG1lbnUgPSBuZXcgTWVudSgpO1xuXG5cdFx0bWVudS5hZGRJdGVtKChpKSA9PiB7XG5cdFx0XHRpLnNldFRpdGxlKGBHbyB0byBmaWxlYCkub25DbGljaygoKSA9PlxuXHRcdFx0XHR0YXNrQWN0aW9ucy52aWV3RmlsZSh0YXNrLmlkKSxcblx0XHRcdCk7XG5cdFx0fSk7XG5cblx0XHRtZW51LmFkZFNlcGFyYXRvcigpO1xuXG5cdFx0Zm9yIChjb25zdCBbdGFnLCBsYWJlbF0gb2YgT2JqZWN0LmVudHJpZXMoJGNvbHVtblRhZ1RhYmxlU3RvcmUpKSB7XG5cdFx0XHRtZW51LmFkZEl0ZW0oKGkpID0+IHtcblx0XHRcdFx0aS5zZXRUaXRsZShgTW92ZSB0byAke2xhYmVsfWApLm9uQ2xpY2soKCkgPT5cblx0XHRcdFx0XHR0YXNrQWN0aW9ucy5jaGFuZ2VDb2x1bW4odGFzay5pZCwgdGFnIGFzIENvbHVtblRhZyksXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGlmICh0YXNrLmNvbHVtbiA9PT0gdGFnKSB7XG5cdFx0XHRcdFx0aS5zZXREaXNhYmxlZCh0cnVlKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0bWVudS5hZGRTZXBhcmF0b3IoKTtcblxuXHRcdG1lbnUuYWRkSXRlbSgoaSkgPT4ge1xuXHRcdFx0aS5zZXRUaXRsZShgTW92ZSB0byBkb25lYCkub25DbGljaygoKSA9PlxuXHRcdFx0XHR0YXNrQWN0aW9ucy5jaGFuZ2VDb2x1bW4odGFzay5pZCwgXCJkb25lXCIpLFxuXHRcdFx0KTtcblx0XHRcdGlmICh0YXNrLmNvbHVtbiA9PT0gXCJkb25lXCIpIHtcblx0XHRcdFx0aS5zZXREaXNhYmxlZCh0cnVlKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdG1lbnUuc2hvd0F0TW91c2VFdmVudChlKTtcblx0fVxuPC9zY3JpcHQ+XG5cbjwhLS0gc3ZlbHRlLWlnbm9yZSBhMTF5LWNsaWNrLWV2ZW50cy1oYXZlLWtleS1ldmVudHMgLS0+XG48c3BhblxuXHRiaW5kOnRoaXM9e2VsZW1lbnR9XG5cdHJvbGU9XCJidXR0b25cIlxuXHR0YWJpbmRleD1cIjBcIlxuXHRvbjpjbGljaz17KGUpID0+IHNob3dNZW51KGUpfVxuPjwvc3Bhbj5cblxuPHN0eWxlIGxhbmc9XCJzY3NzXCI+XG5cdHNwYW4ge1xuXHRcdHdpZHRoOiAyNHB4O1xuXHRcdGhlaWdodDogMjRweDtcblx0XHRkaXNwbGF5OiBmbGV4O1xuXHRcdGp1c3RpZnktY29udGVudDogY2VudGVyO1xuXHRcdGFsaWduLWl0ZW1zOiBjZW50ZXI7XG5cdFx0Ym9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLXMpO1xuXHRcdHRyYW5zaXRpb246IGJhY2tncm91bmQgbGluZWFyIDEwMG1zO1xuXHRcdGN1cnNvcjogcG9pbnRlcjtcblxuXHRcdCY6aG92ZXIge1xuXHRcdFx0YmFja2dyb3VuZDogdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ob3Zlcik7XG5cdFx0fVxuXHR9XG48L3N0eWxlPlxuIiwgIjxzY3JpcHQgbGFuZz1cInRzXCI+XG5cdGltcG9ydCB0eXBlIHsgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi4vdGFza3MvYWN0aW9uc1wiO1xuXHRpbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza3MvdGFza1wiO1xuXHRpbXBvcnQgVGFza01lbnUgZnJvbSBcIi4vdGFza19tZW51LnN2ZWx0ZVwiO1xuXG5cdGV4cG9ydCBsZXQgdGFzazogVGFzaztcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG48L3NjcmlwdD5cblxuPGRpdiBjbGFzcz1cInRhc2tcIj5cblx0PGRpdiBjbGFzcz1cInRhc2stY29udGVudFwiPlxuXHRcdDxwPnt0YXNrLmNvbnRlbnR9PC9wPlxuXHQ8L2Rpdj5cblx0PFRhc2tNZW51IHt0YXNrfSB7dGFza0FjdGlvbnN9IC8+XG48L2Rpdj5cblxuPHN0eWxlIGxhbmc9XCJzY3NzXCI+XG5cdC50YXNrIHtcblx0XHRiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXByaW1hcnktYWx0KTtcblx0XHRib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtbSk7XG5cdFx0Ym9yZGVyOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcblx0XHRwYWRkaW5nOiB2YXIoLS1zaXplLTQtMik7XG5cdFx0ZGlzcGxheTogZ3JpZDtcblx0XHRncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmciBhdXRvO1xuXG5cdFx0cCB7XG5cdFx0XHRtYXJnaW4tdG9wOiAwO1xuXG5cdFx0XHQmOmxhc3QtY2hpbGQge1xuXHRcdFx0XHRtYXJnaW4tYm90dG9tOiAwO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuPC9zdHlsZT5cbiIsICI8c2NyaXB0IGxhbmc9XCJ0c1wiPlxuXHRpbXBvcnQge1xuXHRcdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG5cdFx0dHlwZSBDb2x1bW5UYWcsXG5cdFx0dHlwZSBEZWZhdWx0Q29sdW1ucyxcblx0XHR0eXBlIENvbHVtblRhZ1RhYmxlLFxuXHR9IGZyb20gXCIuLi9jb2x1bW5zL2NvbHVtbnNcIjtcblx0aW1wb3J0IHR5cGUgeyBUYXNrQWN0aW9ucyB9IGZyb20gXCIuLi90YXNrcy9hY3Rpb25zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuLi90YXNrcy90YXNrXCI7XG5cdGltcG9ydCBUYXNrQ29tcG9uZW50IGZyb20gXCIuL3Rhc2suc3ZlbHRlXCI7XG5cblx0ZXhwb3J0IGxldCBjb2x1bW46IENvbHVtblRhZyB8IERlZmF1bHRDb2x1bW5zO1xuXHRleHBvcnQgbGV0IGhpZGVPbkVtcHR5OiBib29sZWFuID0gZmFsc2U7XG5cdGV4cG9ydCBsZXQgdGFza3M6IFRhc2tbXTtcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG5cblx0ZnVuY3Rpb24gZ2V0Q29sdW1uVGl0bGUoXG5cdFx0Y29sdW1uOiBDb2x1bW5UYWcgfCBEZWZhdWx0Q29sdW1ucyxcblx0XHRjb2x1bW5UYWdUYWJsZTogQ29sdW1uVGFnVGFibGUsXG5cdCkge1xuXHRcdHN3aXRjaCAoY29sdW1uKSB7XG5cdFx0XHRjYXNlIFwiZG9uZVwiOlxuXHRcdFx0XHRyZXR1cm4gXCJEb25lXCI7XG5cdFx0XHRjYXNlIFwidW5jYXRlZ29yaXNlZFwiOlxuXHRcdFx0XHRyZXR1cm4gXCJVbmNhdGVnb3Jpc2VkXCI7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRyZXR1cm4gY29sdW1uVGFnVGFibGVbY29sdW1uXTtcblx0XHR9XG5cdH1cblxuXHQkOiBjb2x1bW5UaXRsZSA9IGdldENvbHVtblRpdGxlKGNvbHVtbiwgJGNvbHVtblRhZ1RhYmxlU3RvcmUpO1xuXG5cdCQ6IHNvcnRlZFRhc2tzID0gdGFza3Muc29ydCgoYSwgYikgPT4ge1xuXHRcdGlmIChhLnBhdGggPT09IGIucGF0aCkge1xuXHRcdFx0cmV0dXJuIGEucm93SW5kZXggLSBiLnJvd0luZGV4O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gYS5wYXRoLmxvY2FsZUNvbXBhcmUoYi5wYXRoKTtcblx0XHR9XG5cdH0pO1xuPC9zY3JpcHQ+XG5cbnsjaWYgIWhpZGVPbkVtcHR5IHx8IHRhc2tzLmxlbmd0aH1cblx0PGRpdiBjbGFzcz1cImNvbHVtblwiPlxuXHRcdDxoMj57Y29sdW1uVGl0bGV9PC9oMj5cblx0XHQ8ZGl2IGNsYXNzPVwiZGl2aWRlXCIgLz5cblx0XHQ8ZGl2IGNsYXNzPVwidGFza3NcIj5cblx0XHRcdHsjZWFjaCBzb3J0ZWRUYXNrcyBhcyB0YXNrfVxuXHRcdFx0XHQ8VGFza0NvbXBvbmVudCB7dGFza30ge3Rhc2tBY3Rpb25zfSAvPlxuXHRcdFx0ey9lYWNofVxuXHRcdDwvZGl2PlxuXHQ8L2Rpdj5cbnsvaWZ9XG5cbjxzdHlsZT5cblx0LmNvbHVtbiB7XG5cdFx0d2lkdGg6IDIyMHB4O1xuXHRcdGZsZXgtc2hyaW5rOiAwO1xuXHRcdHBhZGRpbmc6IHZhcigtLXNpemUtNC0zKTtcblx0XHRib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtbSk7XG5cdFx0Ym9yZGVyOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcblx0XHRiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXByaW1hcnkpO1xuXHR9XG5cblx0LmNvbHVtbiBoMiB7XG5cdFx0Zm9udC1zaXplOiB2YXIoLS1mb250LXVpLWxhcmdlcik7XG5cdFx0Zm9udC13ZWlnaHQ6IHZhcigtLWZvbnQtYm9sZCk7XG5cdFx0bWFyZ2luOiAwO1xuXHR9XG5cblx0LmNvbHVtbiAuZGl2aWRlIHtcblx0XHR3aWR0aDogY2FsYygxMDAlICsgY2FsYygyICogdmFyKC0tc2l6ZS00LTMpKSk7XG5cdFx0Ym9yZGVyLWJvdHRvbTogdmFyKC0tYm9yZGVyLXdpZHRoKSBzb2xpZFxuXHRcdFx0dmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xuXHRcdG1hcmdpbjogdmFyKC0tc2l6ZS00LTMpIGNhbGMoLTEgKiB2YXIoLS1zaXplLTQtMykpO1xuXHR9XG5cblx0LmNvbHVtbiAudGFza3Mge1xuXHRcdGRpc3BsYXk6IGZsZXg7XG5cdFx0ZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcblx0XHRnYXA6IHZhcigtLXNpemUtNC0yKTtcblx0fVxuPC9zdHlsZT5cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBLDRDQUFBQSxTQUFBO0FBQUMsS0FBQyxTQUFVLE1BQU0sU0FBUztBQUMxQixVQUFJLE9BQU8sWUFBWSxVQUFVO0FBRWhDLFFBQUFBLFFBQU8sVUFBVSxVQUFVLFFBQVE7QUFBQSxNQUNwQyxXQUNTLE9BQU8sV0FBVyxjQUFjLE9BQU8sS0FBSztBQUVwRCxlQUFPLENBQUMsR0FBRyxPQUFPO0FBQUEsTUFDbkIsT0FDSztBQUVKLGFBQUssV0FBVyxRQUFRO0FBQUEsTUFDekI7QUFBQSxJQUNELEdBQUUsU0FBTSxXQUFZO0FBT25CLFVBQUksV0FBVyxZQUFhLFNBQVVDLE9BQU1DLFlBQVc7QUFFbkQsWUFBSTtBQUdKLFlBQUksT0FBTyxXQUFXLGVBQWUsT0FBTyxRQUFRO0FBQ2hELG1CQUFTLE9BQU87QUFBQSxRQUNwQjtBQUdBLFlBQUksT0FBTyxTQUFTLGVBQWUsS0FBSyxRQUFRO0FBQzVDLG1CQUFTLEtBQUs7QUFBQSxRQUNsQjtBQUdBLFlBQUksT0FBTyxlQUFlLGVBQWUsV0FBVyxRQUFRO0FBQ3hELG1CQUFTLFdBQVc7QUFBQSxR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UjtBQUFBLEVBRUEsTUFBTSxTQUFTO0FBQ2QsU0FBSyxZQUFZLElBQUksYUFBSztBQUFBLE1BQ3pCLFFBQVEsS0FBSztBQUFBLE1BQ2IsT0FBTztBQUFBLFFBQ04sV0FBVyxLQUFLLElBQUk7QUFBQSxRQUNwQixPQUFPLEtBQUssSUFBSTtBQUFBLFFBQ2hCLGVBQWUsS0FBSyxjQUFjLEtBQUssSUFBSTtBQUFBLE1BQzVDO0FBQUEsSUFDRCxDQUFDO0FBQUEsRUFDRjtBQUFBLEVBRUEsTUFBTSxVQUFVO0FBOUJqQjtBQStCRSxlQUFLLGNBQUwsbUJBQWdCO0FBQUEsRUFDakI7QUFDRDs7O0FEOUJBLElBQXFCLE9BQXJCLGNBQWtDLHdCQUFPO0FBQUEsRUFDeEMsTUFBTSxTQUFTO0FBQ2QsU0FBSyxhQUFhLGVBQWUsQ0FBQyxTQUFTLElBQUksUUFBUSxJQUFJLENBQUM7QUFDNUQsU0FBSztBQUFBLE1BQWM7QUFBQSxNQUFpQjtBQUFBLE1BQWUsTUFDbEQsS0FBSyxhQUFhO0FBQUEsSUFDbkI7QUFBQSxFQUNEO0FBQUEsRUFFQSxXQUFXO0FBQUEsRUFBQztBQUFBLEVBRVosTUFBTSxlQUFlO0FBQ3BCLFVBQU0sRUFBRSxVQUFVLElBQUksS0FBSztBQUUzQixRQUFJO0FBQ0osVUFBTSxTQUFTLFVBQVUsZ0JBQWdCLGFBQWE7QUFFdEQsUUFBSSxPQUFPLFNBQVMsR0FBRztBQUV0QixhQUFPLE9BQU8sQ0FBQztBQUFBLElBQ2hCLE9BQU87QUFHTixhQUFPLFVBQVUsUUFBUSxLQUFLO0FBQzlCLFlBQU0sS0FBSyxhQUFhLEVBQUUsTUFBTSxlQUFlLFFBQVEsS0FBSyxDQUFDO0FBQUEsSUFDOUQ7QUFHQSxZQUFRLFVBQVUsV0FBVyxJQUFJO0FBQUEsRUFDbEM7QUFDRDsiLAogICJuYW1lcyI6IFsibW9kdWxlIiwgIk1hdGgiLCAidW5kZWZpbmVkIiwgIkJhc2UiLCAiaW5zdGFuY2UiLCAibW9kdWxlIiwgIk1hdGgiLCAibiIsICJIIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiZWxlbWVudCIsICJfYSIsICJlbGVtZW50IiwgInRleHQiLCAiZWxlbWVudCIsICJkZXRhY2giLCAiaW5zdGFuY2UiLCAiY3JlYXRlX2ZyYWdtZW50IiwgImFwcGVuZF9zdHlsZXMiLCAiYXR0ciIsICJpbXBvcnRfb2JzaWRpYW4iLCAic2hhMjU2IiwgInVwZGF0ZSIsICJzdWJzY3JpYmUiLCAicnVuIiwgImNvbHVtblRhZ1RhYmxlU3RvcmUiLCAiY29sdW1uVGFnVGFibGVTdG9yZSIsICJlbGVtZW50IiwgImN0eCIsICJjdHgiLCAiX2EiLCAiY3R4Il0KfQo= diff --git a/package-lock.json b/package-lock.json index e6a1879db..158344eff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "obsidian-sample-plugin", + "name": "obsidian-project-kanban", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "obsidian-sample-plugin", + "name": "obsidian-project-kanban", "version": "1.0.0", "license": "MIT", "dependencies": { From 06ff07a91d754b19729048fcafb5d78e339c2608 Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Wed, 21 Feb 2024 20:57:21 +1000 Subject: [PATCH 003/195] fixed git ignore --- .gitignore | 4 + main.js | 2660 ------------------------------------------------- versions.json | 2 +- 3 files changed, 5 insertions(+), 2661 deletions(-) delete mode 100644 main.js diff --git a/.gitignore b/.gitignore index 18fe88c95..e09a007eb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,10 @@ # npm node_modules +# Don't include the compiled main.js file in the repo. +# They should be uploaded to GitHub releases instead. +main.js + # Exclude sourcemaps *.map diff --git a/main.js b/main.js deleted file mode 100644 index 2267016f8..000000000 --- a/main.js +++ /dev/null @@ -1,2660 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -"use strict"; -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; -}; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -var __publicField = (obj, key, value) => { - __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - return value; -}; - -// node_modules/crypto-js/core.js -var require_core = __commonJS({ - "node_modules/crypto-js/core.js"(exports, module2) { - (function(root, factory) { - if (typeof exports === "object") { - module2.exports = exports = factory(); - } else if (typeof define === "function" && define.amd) { - define([], factory); - } else { - root.CryptoJS = factory(); - } - })(exports, function() { - var CryptoJS = CryptoJS || function(Math2, undefined2) { - var crypto; - if (typeof window !== "undefined" && window.crypto) { - crypto = window.crypto; - } - if (typeof self !== "undefined" && self.crypto) { - crypto = self.crypto; - } - if (typeof globalThis !== "undefined" && globalThis.crypto) { - crypto = globalThis.crypto; - } - if (!crypto && typeof window !== "undefined" && window.msCrypto) { - crypto = window.msCrypto; - } - if (!crypto && typeof global !== "undefined" && global.crypto) { - crypto = global.crypto; - } - if (!crypto && typeof require === "function") { - try { - crypto = require("crypto"); - } catch (err) { - } - } - var cryptoSecureRandomInt = function() { - if (crypto) { - if (typeof crypto.getRandomValues === "function") { - try { - return crypto.getRandomValues(new Uint32Array(1))[0]; - } catch (err) { - } - } - if (typeof crypto.randomBytes === "function") { - try { - return crypto.randomBytes(4).readInt32LE(); - } catch (err) { - } - } - } - throw new Error("Native crypto module could not be used to get secure random number."); - }; - var create = Object.create || /* @__PURE__ */ function() { - function F() { - } - return function(obj) { - var subtype; - F.prototype = obj; - subtype = new F(); - F.prototype = null; - return subtype; - }; - }(); - var C = {}; - var C_lib = C.lib = {}; - var Base2 = C_lib.Base = /* @__PURE__ */ function() { - return { - /** - * Creates a new object that inherits from this object. - * - * @param {Object} overrides Properties to copy into the new object. - * - * @return {Object} The new object. - * - * @static - * - * @example - * - * var MyType = CryptoJS.lib.Base.extend({ - * field: 'value', - * - * method: function () { - * } - * }); - */ - extend: function(overrides) { - var subtype = create(this); - if (overrides) { - subtype.mixIn(overrides); - } - if (!subtype.hasOwnProperty("init") || this.init === subtype.init) { - subtype.init = function() { - subtype.$super.init.apply(this, arguments); - }; - } - subtype.init.prototype = subtype; - subtype.$super = this; - return subtype; - }, - /** - * Extends this object and runs the init method. - * Arguments to create() will be passed to init(). - * - * @return {Object} The new object. - * - * @static - * - * @example - * - * var instance = MyType.create(); - */ - create: function() { - var instance5 = this.extend(); - instance5.init.apply(instance5, arguments); - return instance5; - }, - /** - * Initializes a newly created object. - * Override this method to add some logic when your objects are created. - * - * @example - * - * var MyType = CryptoJS.lib.Base.extend({ - * init: function () { - * // ... - * } - * }); - */ - init: function() { - }, - /** - * Copies properties into this object. - * - * @param {Object} properties The properties to mix in. - * - * @example - * - * MyType.mixIn({ - * field: 'value' - * }); - */ - mixIn: function(properties) { - for (var propertyName in properties) { - if (properties.hasOwnProperty(propertyName)) { - this[propertyName] = properties[propertyName]; - } - } - if (properties.hasOwnProperty("toString")) { - this.toString = properties.toString; - } - }, - /** - * Creates a copy of this object. - * - * @return {Object} The clone. - * - * @example - * - * var clone = instance.clone(); - */ - clone: function() { - return this.init.prototype.extend(this); - } - }; - }(); - var WordArray = C_lib.WordArray = Base2.extend({ - /** - * Initializes a newly created word array. - * - * @param {Array} words (Optional) An array of 32-bit words. - * @param {number} sigBytes (Optional) The number of significant bytes in the words. - * - * @example - * - * var wordArray = CryptoJS.lib.WordArray.create(); - * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); - * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); - */ - init: function(words, sigBytes) { - words = this.words = words || []; - if (sigBytes != undefined2) { - this.sigBytes = sigBytes; - } else { - this.sigBytes = words.length * 4; - } - }, - /** - * Converts this word array to a string. - * - * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex - * - * @return {string} The stringified word array. - * - * @example - * - * var string = wordArray + ''; - * var string = wordArray.toString(); - * var string = wordArray.toString(CryptoJS.enc.Utf8); - */ - toString: function(encoder) { - return (encoder || Hex).stringify(this); - }, - /** - * Concatenates a word array to this word array. - * - * @param {WordArray} wordArray The word array to append. - * - * @return {WordArray} This word array. - * - * @example - * - * wordArray1.concat(wordArray2); - */ - concat: function(wordArray) { - var thisWords = this.words; - var thatWords = wordArray.words; - var thisSigBytes = this.sigBytes; - var thatSigBytes = wordArray.sigBytes; - this.clamp(); - if (thisSigBytes % 4) { - for (var i = 0; i < thatSigBytes; i++) { - var thatByte = thatWords[i >>> 2] >>> 24 - i % 4 * 8 & 255; - thisWords[thisSigBytes + i >>> 2] |= thatByte << 24 - (thisSigBytes + i) % 4 * 8; - } - } else { - for (var j = 0; j < thatSigBytes; j += 4) { - thisWords[thisSigBytes + j >>> 2] = thatWords[j >>> 2]; - } - } - this.sigBytes += thatSigBytes; - return this; - }, - /** - * Removes insignificant bits. - * - * @example - * - * wordArray.clamp(); - */ - clamp: function() { - var words = this.words; - var sigBytes = this.sigBytes; - words[sigBytes >>> 2] &= 4294967295 << 32 - sigBytes % 4 * 8; - words.length = Math2.ceil(sigBytes / 4); - }, - /** - * Creates a copy of this word array. - * - * @return {WordArray} The clone. - * - * @example - * - * var clone = wordArray.clone(); - */ - clone: function() { - var clone = Base2.clone.call(this); - clone.words = this.words.slice(0); - return clone; - }, - /** - * Creates a word array filled with random bytes. - * - * @param {number} nBytes The number of random bytes to generate. - * - * @return {WordArray} The random word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.lib.WordArray.random(16); - */ - random: function(nBytes) { - var words = []; - for (var i = 0; i < nBytes; i += 4) { - words.push(cryptoSecureRandomInt()); - } - return new WordArray.init(words, nBytes); - } - }); - var C_enc = C.enc = {}; - var Hex = C_enc.Hex = { - /** - * Converts a word array to a hex string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The hex string. - * - * @static - * - * @example - * - * var hexString = CryptoJS.enc.Hex.stringify(wordArray); - */ - stringify: function(wordArray) { - var words = wordArray.words; - var sigBytes = wordArray.sigBytes; - var hexChars = []; - for (var i = 0; i < sigBytes; i++) { - var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255; - hexChars.push((bite >>> 4).toString(16)); - hexChars.push((bite & 15).toString(16)); - } - return hexChars.join(""); - }, - /** - * Converts a hex string to a word array. - * - * @param {string} hexStr The hex string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Hex.parse(hexString); - */ - parse: function(hexStr) { - var hexStrLength = hexStr.length; - var words = []; - for (var i = 0; i < hexStrLength; i += 2) { - words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << 24 - i % 8 * 4; - } - return new WordArray.init(words, hexStrLength / 2); - } - }; - var Latin1 = C_enc.Latin1 = { - /** - * Converts a word array to a Latin1 string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The Latin1 string. - * - * @static - * - * @example - * - * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); - */ - stringify: function(wordArray) { - var words = wordArray.words; - var sigBytes = wordArray.sigBytes; - var latin1Chars = []; - for (var i = 0; i < sigBytes; i++) { - var bite = words[i >>> 2] >>> 24 - i % 4 * 8 & 255; - latin1Chars.push(String.fromCharCode(bite)); - } - return latin1Chars.join(""); - }, - /** - * Converts a Latin1 string to a word array. - * - * @param {string} latin1Str The Latin1 string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); - */ - parse: function(latin1Str) { - var latin1StrLength = latin1Str.length; - var words = []; - for (var i = 0; i < latin1StrLength; i++) { - words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << 24 - i % 4 * 8; - } - return new WordArray.init(words, latin1StrLength); - } - }; - var Utf8 = C_enc.Utf8 = { - /** - * Converts a word array to a UTF-8 string. - * - * @param {WordArray} wordArray The word array. - * - * @return {string} The UTF-8 string. - * - * @static - * - * @example - * - * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); - */ - stringify: function(wordArray) { - try { - return decodeURIComponent(escape(Latin1.stringify(wordArray))); - } catch (e) { - throw new Error("Malformed UTF-8 data"); - } - }, - /** - * Converts a UTF-8 string to a word array. - * - * @param {string} utf8Str The UTF-8 string. - * - * @return {WordArray} The word array. - * - * @static - * - * @example - * - * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); - */ - parse: function(utf8Str) { - return Latin1.parse(unescape(encodeURIComponent(utf8Str))); - } - }; - var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base2.extend({ - /** - * Resets this block algorithm's data buffer to its initial state. - * - * @example - * - * bufferedBlockAlgorithm.reset(); - */ - reset: function() { - this._data = new WordArray.init(); - this._nDataBytes = 0; - }, - /** - * Adds new data to this block algorithm's buffer. - * - * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. - * - * @example - * - * bufferedBlockAlgorithm._append('data'); - * bufferedBlockAlgorithm._append(wordArray); - */ - _append: function(data) { - if (typeof data == "string") { - data = Utf8.parse(data); - } - this._data.concat(data); - this._nDataBytes += data.sigBytes; - }, - /** - * Processes available data blocks. - * - * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. - * - * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. - * - * @return {WordArray} The processed data. - * - * @example - * - * var processedData = bufferedBlockAlgorithm._process(); - * var processedData = bufferedBlockAlgorithm._process(!!'flush'); - */ - _process: function(doFlush) { - var processedWords; - var data = this._data; - var dataWords = data.words; - var dataSigBytes = data.sigBytes; - var blockSize = this.blockSize; - var blockSizeBytes = blockSize * 4; - var nBlocksReady = dataSigBytes / blockSizeBytes; - if (doFlush) { - nBlocksReady = Math2.ceil(nBlocksReady); - } else { - nBlocksReady = Math2.max((nBlocksReady | 0) - this._minBufferSize, 0); - } - var nWordsReady = nBlocksReady * blockSize; - var nBytesReady = Math2.min(nWordsReady * 4, dataSigBytes); - if (nWordsReady) { - for (var offset = 0; offset < nWordsReady; offset += blockSize) { - this._doProcessBlock(dataWords, offset); - } - processedWords = dataWords.splice(0, nWordsReady); - data.sigBytes -= nBytesReady; - } - return new WordArray.init(processedWords, nBytesReady); - }, - /** - * Creates a copy of this object. - * - * @return {Object} The clone. - * - * @example - * - * var clone = bufferedBlockAlgorithm.clone(); - */ - clone: function() { - var clone = Base2.clone.call(this); - clone._data = this._data.clone(); - return clone; - }, - _minBufferSize: 0 - }); - var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ - /** - * Configuration options. - */ - cfg: Base2.extend(), - /** - * Initializes a newly created hasher. - * - * @param {Object} cfg (Optional) The configuration options to use for this hash computation. - * - * @example - * - * var hasher = CryptoJS.algo.SHA256.create(); - */ - init: function(cfg) { - this.cfg = this.cfg.extend(cfg); - this.reset(); - }, - /** - * Resets this hasher to its initial state. - * - * @example - * - * hasher.reset(); - */ - reset: function() { - BufferedBlockAlgorithm.reset.call(this); - this._doReset(); - }, - /** - * Updates this hasher with a message. - * - * @param {WordArray|string} messageUpdate The message to append. - * - * @return {Hasher} This hasher. - * - * @example - * - * hasher.update('message'); - * hasher.update(wordArray); - */ - update: function(messageUpdate) { - this._append(messageUpdate); - this._process(); - return this; - }, - /** - * Finalizes the hash computation. - * Note that the finalize operation is effectively a destructive, read-once operation. - * - * @param {WordArray|string} messageUpdate (Optional) A final message update. - * - * @return {WordArray} The hash. - * - * @example - * - * var hash = hasher.finalize(); - * var hash = hasher.finalize('message'); - * var hash = hasher.finalize(wordArray); - */ - finalize: function(messageUpdate) { - if (messageUpdate) { - this._append(messageUpdate); - } - var hash = this._doFinalize(); - return hash; - }, - blockSize: 512 / 32, - /** - * Creates a shortcut function to a hasher's object interface. - * - * @param {Hasher} hasher The hasher to create a helper for. - * - * @return {Function} The shortcut function. - * - * @static - * - * @example - * - * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); - */ - _createHelper: function(hasher) { - return function(message, cfg) { - return new hasher.init(cfg).finalize(message); - }; - }, - /** - * Creates a shortcut function to the HMAC's object interface. - * - * @param {Hasher} hasher The hasher to use in this HMAC helper. - * - * @return {Function} The shortcut function. - * - * @static - * - * @example - * - * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); - */ - _createHmacHelper: function(hasher) { - return function(message, key) { - return new C_algo.HMAC.init(hasher, key).finalize(message); - }; - } - }); - var C_algo = C.algo = {}; - return C; - }(Math); - return CryptoJS; - }); - } -}); - -// node_modules/crypto-js/sha256.js -var require_sha256 = __commonJS({ - "node_modules/crypto-js/sha256.js"(exports, module2) { - (function(root, factory) { - if (typeof exports === "object") { - module2.exports = exports = factory(require_core()); - } else if (typeof define === "function" && define.amd) { - define(["./core"], factory); - } else { - factory(root.CryptoJS); - } - })(exports, function(CryptoJS) { - (function(Math2) { - var C = CryptoJS; - var C_lib = C.lib; - var WordArray = C_lib.WordArray; - var Hasher = C_lib.Hasher; - var C_algo = C.algo; - var H = []; - var K = []; - (function() { - function isPrime(n2) { - var sqrtN = Math2.sqrt(n2); - for (var factor = 2; factor <= sqrtN; factor++) { - if (!(n2 % factor)) { - return false; - } - } - return true; - } - function getFractionalBits(n2) { - return (n2 - (n2 | 0)) * 4294967296 | 0; - } - var n = 2; - var nPrime = 0; - while (nPrime < 64) { - if (isPrime(n)) { - if (nPrime < 8) { - H[nPrime] = getFractionalBits(Math2.pow(n, 1 / 2)); - } - K[nPrime] = getFractionalBits(Math2.pow(n, 1 / 3)); - nPrime++; - } - n++; - } - })(); - var W = []; - var SHA256 = C_algo.SHA256 = Hasher.extend({ - _doReset: function() { - this._hash = new WordArray.init(H.slice(0)); - }, - _doProcessBlock: function(M, offset) { - var H2 = this._hash.words; - var a = H2[0]; - var b = H2[1]; - var c = H2[2]; - var d = H2[3]; - var e = H2[4]; - var f = H2[5]; - var g = H2[6]; - var h = H2[7]; - for (var i = 0; i < 64; i++) { - if (i < 16) { - W[i] = M[offset + i] | 0; - } else { - var gamma0x = W[i - 15]; - var gamma0 = (gamma0x << 25 | gamma0x >>> 7) ^ (gamma0x << 14 | gamma0x >>> 18) ^ gamma0x >>> 3; - var gamma1x = W[i - 2]; - var gamma1 = (gamma1x << 15 | gamma1x >>> 17) ^ (gamma1x << 13 | gamma1x >>> 19) ^ gamma1x >>> 10; - W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; - } - var ch = e & f ^ ~e & g; - var maj = a & b ^ a & c ^ b & c; - var sigma0 = (a << 30 | a >>> 2) ^ (a << 19 | a >>> 13) ^ (a << 10 | a >>> 22); - var sigma1 = (e << 26 | e >>> 6) ^ (e << 21 | e >>> 11) ^ (e << 7 | e >>> 25); - var t1 = h + sigma1 + ch + K[i] + W[i]; - var t2 = sigma0 + maj; - h = g; - g = f; - f = e; - e = d + t1 | 0; - d = c; - c = b; - b = a; - a = t1 + t2 | 0; - } - H2[0] = H2[0] + a | 0; - H2[1] = H2[1] + b | 0; - H2[2] = H2[2] + c | 0; - H2[3] = H2[3] + d | 0; - H2[4] = H2[4] + e | 0; - H2[5] = H2[5] + f | 0; - H2[6] = H2[6] + g | 0; - H2[7] = H2[7] + h | 0; - }, - _doFinalize: function() { - var data = this._data; - var dataWords = data.words; - var nBitsTotal = this._nDataBytes * 8; - var nBitsLeft = data.sigBytes * 8; - dataWords[nBitsLeft >>> 5] |= 128 << 24 - nBitsLeft % 32; - dataWords[(nBitsLeft + 64 >>> 9 << 4) + 14] = Math2.floor(nBitsTotal / 4294967296); - dataWords[(nBitsLeft + 64 >>> 9 << 4) + 15] = nBitsTotal; - data.sigBytes = dataWords.length * 4; - this._process(); - return this._hash; - }, - clone: function() { - var clone = Hasher.clone.call(this); - clone._hash = this._hash.clone(); - return clone; - } - }); - C.SHA256 = Hasher._createHelper(SHA256); - C.HmacSHA256 = Hasher._createHmacHelper(SHA256); - })(Math); - return CryptoJS.SHA256; - }); - } -}); - -// src/entry.ts -var entry_exports = {}; -__export(entry_exports, { - default: () => Base -}); -module.exports = __toCommonJS(entry_exports); -var import_obsidian6 = require("obsidian"); - -// src/ui/entry.ts -var import_obsidian5 = require("obsidian"); - -// node_modules/svelte/src/runtime/internal/utils.js -function noop() { -} -function run(fn) { - return fn(); -} -function blank_object() { - return /* @__PURE__ */ Object.create(null); -} -function run_all(fns) { - fns.forEach(run); -} -function is_function(thing) { - return typeof thing === "function"; -} -function safe_not_equal(a, b) { - return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function"; -} -function is_empty(obj) { - return Object.keys(obj).length === 0; -} -function subscribe(store, ...callbacks) { - if (store == null) { - for (const callback of callbacks) { - callback(void 0); - } - return noop; - } - const unsub = store.subscribe(...callbacks); - return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; -} -function get_store_value(store) { - let value; - subscribe(store, (_) => value = _)(); - return value; -} -function component_subscribe(component, store, callback) { - component.$$.on_destroy.push(subscribe(store, callback)); -} - -// node_modules/svelte/src/runtime/internal/globals.js -var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : ( - // @ts-ignore Node typings have this - global -); - -// node_modules/svelte/src/runtime/internal/ResizeObserverSingleton.js -var ResizeObserverSingleton = class _ResizeObserverSingleton { - /** @param {ResizeObserverOptions} options */ - constructor(options) { - /** - * @private - * @readonly - * @type {WeakMap} - */ - __publicField(this, "_listeners", "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0); - /** - * @private - * @type {ResizeObserver} - */ - __publicField(this, "_observer"); - /** @type {ResizeObserverOptions} */ - __publicField(this, "options"); - this.options = options; - } - /** - * @param {Element} element - * @param {import('./private.js').Listener} listener - * @returns {() => void} - */ - observe(element2, listener) { - this._listeners.set(element2, listener); - this._getObserver().observe(element2, this.options); - return () => { - this._listeners.delete(element2); - this._observer.unobserve(element2); - }; - } - /** - * @private - */ - _getObserver() { - var _a; - return (_a = this._observer) != null ? _a : this._observer = new ResizeObserver((entries) => { - var _a2; - for (const entry of entries) { - _ResizeObserverSingleton.entries.set(entry.target, entry); - (_a2 = this._listeners.get(entry.target)) == null ? void 0 : _a2(entry); - } - }); - } -}; -ResizeObserverSingleton.entries = "WeakMap" in globals ? /* @__PURE__ */ new WeakMap() : void 0; - -// node_modules/svelte/src/runtime/internal/dom.js -var is_hydrating = false; -function start_hydrating() { - is_hydrating = true; -} -function end_hydrating() { - is_hydrating = false; -} -function append(target, node) { - target.appendChild(node); -} -function append_styles(target, style_sheet_id, styles) { - const append_styles_to = get_root_for_style(target); - if (!append_styles_to.getElementById(style_sheet_id)) { - const style = element("style"); - style.id = style_sheet_id; - style.textContent = styles; - append_stylesheet(append_styles_to, style); - } -} -function get_root_for_style(node) { - if (!node) - return document; - const root = node.getRootNode ? node.getRootNode() : node.ownerDocument; - if (root && /** @type {ShadowRoot} */ - root.host) { - return ( - /** @type {ShadowRoot} */ - root - ); - } - return node.ownerDocument; -} -function append_stylesheet(node, style) { - append( - /** @type {Document} */ - node.head || node, - style - ); - return style.sheet; -} -function insert(target, node, anchor) { - target.insertBefore(node, anchor || null); -} -function detach(node) { - if (node.parentNode) { - node.parentNode.removeChild(node); - } -} -function destroy_each(iterations, detaching) { - for (let i = 0; i < iterations.length; i += 1) { - if (iterations[i]) - iterations[i].d(detaching); - } -} -function element(name) { - return document.createElement(name); -} -function text(data) { - return document.createTextNode(data); -} -function space() { - return text(" "); -} -function empty() { - return text(""); -} -function listen(node, event, handler, options) { - node.addEventListener(event, handler, options); - return () => node.removeEventListener(event, handler, options); -} -function attr(node, attribute, value) { - if (value == null) - node.removeAttribute(attribute); - else if (node.getAttribute(attribute) !== value) - node.setAttribute(attribute, value); -} -function children(element2) { - return Array.from(element2.childNodes); -} -function set_data(text2, data) { - data = "" + data; - if (text2.data === data) - return; - text2.data = /** @type {string} */ - data; -} -function get_custom_elements_slots(element2) { - const result = {}; - element2.childNodes.forEach( - /** @param {Element} node */ - (node) => { - result[node.slot || "default"] = true; - } - ); - return result; -} - -// node_modules/svelte/src/runtime/internal/lifecycle.js -var current_component; -function set_current_component(component) { - current_component = component; -} - -// node_modules/svelte/src/runtime/internal/scheduler.js -var dirty_components = []; -var binding_callbacks = []; -var render_callbacks = []; -var flush_callbacks = []; -var resolved_promise = /* @__PURE__ */ Promise.resolve(); -var update_scheduled = false; -function schedule_update() { - if (!update_scheduled) { - update_scheduled = true; - resolved_promise.then(flush); - } -} -function add_render_callback(fn) { - render_callbacks.push(fn); -} -var seen_callbacks = /* @__PURE__ */ new Set(); -var flushidx = 0; -function flush() { - if (flushidx !== 0) { - return; - } - const saved_component = current_component; - do { - try { - while (flushidx < dirty_components.length) { - const component = dirty_components[flushidx]; - flushidx++; - set_current_component(component); - update(component.$$); - } - } catch (e) { - dirty_components.length = 0; - flushidx = 0; - throw e; - } - set_current_component(null); - dirty_components.length = 0; - flushidx = 0; - while (binding_callbacks.length) - binding_callbacks.pop()(); - for (let i = 0; i < render_callbacks.length; i += 1) { - const callback = render_callbacks[i]; - if (!seen_callbacks.has(callback)) { - seen_callbacks.add(callback); - callback(); - } - } - render_callbacks.length = 0; - } while (dirty_components.length); - while (flush_callbacks.length) { - flush_callbacks.pop()(); - } - update_scheduled = false; - seen_callbacks.clear(); - set_current_component(saved_component); -} -function update($$) { - if ($$.fragment !== null) { - $$.update(); - run_all($$.before_update); - const dirty = $$.dirty; - $$.dirty = [-1]; - $$.fragment && $$.fragment.p($$.ctx, dirty); - $$.after_update.forEach(add_render_callback); - } -} -function flush_render_callbacks(fns) { - const filtered = []; - const targets = []; - render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c)); - targets.forEach((c) => c()); - render_callbacks = filtered; -} - -// node_modules/svelte/src/runtime/internal/transitions.js -var outroing = /* @__PURE__ */ new Set(); -var outros; -function group_outros() { - outros = { - r: 0, - c: [], - p: outros - // parent group - }; -} -function check_outros() { - if (!outros.r) { - run_all(outros.c); - } - outros = outros.p; -} -function transition_in(block, local) { - if (block && block.i) { - outroing.delete(block); - block.i(local); - } -} -function transition_out(block, local, detach2, callback) { - if (block && block.o) { - if (outroing.has(block)) - return; - outroing.add(block); - outros.c.push(() => { - outroing.delete(block); - if (callback) { - if (detach2) - block.d(1); - callback(); - } - }); - block.o(local); - } else if (callback) { - callback(); - } -} - -// node_modules/svelte/src/runtime/internal/each.js -function ensure_array_like(array_like_or_iterator) { - return (array_like_or_iterator == null ? void 0 : array_like_or_iterator.length) !== void 0 ? array_like_or_iterator : Array.from(array_like_or_iterator); -} - -// node_modules/svelte/src/shared/boolean_attributes.js -var _boolean_attributes = ( - /** @type {const} */ - [ - "allowfullscreen", - "allowpaymentrequest", - "async", - "autofocus", - "autoplay", - "checked", - "controls", - "default", - "defer", - "disabled", - "formnovalidate", - "hidden", - "inert", - "ismap", - "loop", - "multiple", - "muted", - "nomodule", - "novalidate", - "open", - "playsinline", - "readonly", - "required", - "reversed", - "selected" - ] -); -var boolean_attributes = /* @__PURE__ */ new Set([..._boolean_attributes]); - -// node_modules/svelte/src/runtime/internal/Component.js -function create_component(block) { - block && block.c(); -} -function mount_component(component, target, anchor) { - const { fragment, after_update } = component.$$; - fragment && fragment.m(target, anchor); - add_render_callback(() => { - const new_on_destroy = component.$$.on_mount.map(run).filter(is_function); - if (component.$$.on_destroy) { - component.$$.on_destroy.push(...new_on_destroy); - } else { - run_all(new_on_destroy); - } - component.$$.on_mount = []; - }); - after_update.forEach(add_render_callback); -} -function destroy_component(component, detaching) { - const $$ = component.$$; - if ($$.fragment !== null) { - flush_render_callbacks($$.after_update); - run_all($$.on_destroy); - $$.fragment && $$.fragment.d(detaching); - $$.on_destroy = $$.fragment = null; - $$.ctx = []; - } -} -function make_dirty(component, i) { - if (component.$$.dirty[0] === -1) { - dirty_components.push(component); - schedule_update(); - component.$$.dirty.fill(0); - } - component.$$.dirty[i / 31 | 0] |= 1 << i % 31; -} -function init(component, options, instance5, create_fragment5, not_equal, props, append_styles2 = null, dirty = [-1]) { - const parent_component = current_component; - set_current_component(component); - const $$ = component.$$ = { - fragment: null, - ctx: [], - // state - props, - update: noop, - not_equal, - bound: blank_object(), - // lifecycle - on_mount: [], - on_destroy: [], - on_disconnect: [], - before_update: [], - after_update: [], - context: new Map(options.context || (parent_component ? parent_component.$$.context : [])), - // everything else - callbacks: blank_object(), - dirty, - skip_bound: false, - root: options.target || parent_component.$$.root - }; - append_styles2 && append_styles2($$.root); - let ready = false; - $$.ctx = instance5 ? instance5(component, options.props || {}, (i, ret, ...rest) => { - const value = rest.length ? rest[0] : ret; - if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) { - if (!$$.skip_bound && $$.bound[i]) - $$.bound[i](value); - if (ready) - make_dirty(component, i); - } - return ret; - }) : []; - $$.update(); - ready = true; - run_all($$.before_update); - $$.fragment = create_fragment5 ? create_fragment5($$.ctx) : false; - if (options.target) { - if (options.hydrate) { - start_hydrating(); - const nodes = children(options.target); - $$.fragment && $$.fragment.l(nodes); - nodes.forEach(detach); - } else { - $$.fragment && $$.fragment.c(); - } - if (options.intro) - transition_in(component.$$.fragment); - mount_component(component, options.target, options.anchor); - end_hydrating(); - flush(); - } - set_current_component(parent_component); -} -var SvelteElement; -if (typeof HTMLElement === "function") { - SvelteElement = class extends HTMLElement { - constructor($$componentCtor, $$slots, use_shadow_dom) { - super(); - /** The Svelte component constructor */ - __publicField(this, "$$ctor"); - /** Slots */ - __publicField(this, "$$s"); - /** The Svelte component instance */ - __publicField(this, "$$c"); - /** Whether or not the custom element is connected */ - __publicField(this, "$$cn", false); - /** Component props data */ - __publicField(this, "$$d", {}); - /** `true` if currently in the process of reflecting component props back to attributes */ - __publicField(this, "$$r", false); - /** @type {Record} Props definition (name, reflected, type etc) */ - __publicField(this, "$$p_d", {}); - /** @type {Record} Event listeners */ - __publicField(this, "$$l", {}); - /** @type {Map} Event listener unsubscribe functions */ - __publicField(this, "$$l_u", /* @__PURE__ */ new Map()); - this.$$ctor = $$componentCtor; - this.$$s = $$slots; - if (use_shadow_dom) { - this.attachShadow({ mode: "open" }); - } - } - addEventListener(type, listener, options) { - this.$$l[type] = this.$$l[type] || []; - this.$$l[type].push(listener); - if (this.$$c) { - const unsub = this.$$c.$on(type, listener); - this.$$l_u.set(listener, unsub); - } - super.addEventListener(type, listener, options); - } - removeEventListener(type, listener, options) { - super.removeEventListener(type, listener, options); - if (this.$$c) { - const unsub = this.$$l_u.get(listener); - if (unsub) { - unsub(); - this.$$l_u.delete(listener); - } - } - } - async connectedCallback() { - this.$$cn = true; - if (!this.$$c) { - let create_slot = function(name) { - return () => { - let node; - const obj = { - c: function create() { - node = element("slot"); - if (name !== "default") { - attr(node, "name", name); - } - }, - /** - * @param {HTMLElement} target - * @param {HTMLElement} [anchor] - */ - m: function mount(target, anchor) { - insert(target, node, anchor); - }, - d: function destroy(detaching) { - if (detaching) { - detach(node); - } - } - }; - return obj; - }; - }; - await Promise.resolve(); - if (!this.$$cn || this.$$c) { - return; - } - const $$slots = {}; - const existing_slots = get_custom_elements_slots(this); - for (const name of this.$$s) { - if (name in existing_slots) { - $$slots[name] = [create_slot(name)]; - } - } - for (const attribute of this.attributes) { - const name = this.$$g_p(attribute.name); - if (!(name in this.$$d)) { - this.$$d[name] = get_custom_element_value(name, attribute.value, this.$$p_d, "toProp"); - } - } - for (const key in this.$$p_d) { - if (!(key in this.$$d) && this[key] !== void 0) { - this.$$d[key] = this[key]; - delete this[key]; - } - } - this.$$c = new this.$$ctor({ - target: this.shadowRoot || this, - props: { - ...this.$$d, - $$slots, - $$scope: { - ctx: [] - } - } - }); - const reflect_attributes = () => { - this.$$r = true; - for (const key in this.$$p_d) { - this.$$d[key] = this.$$c.$$.ctx[this.$$c.$$.props[key]]; - if (this.$$p_d[key].reflect) { - const attribute_value = get_custom_element_value( - key, - this.$$d[key], - this.$$p_d, - "toAttribute" - ); - if (attribute_value == null) { - this.removeAttribute(this.$$p_d[key].attribute || key); - } else { - this.setAttribute(this.$$p_d[key].attribute || key, attribute_value); - } - } - } - this.$$r = false; - }; - this.$$c.$$.after_update.push(reflect_attributes); - reflect_attributes(); - for (const type in this.$$l) { - for (const listener of this.$$l[type]) { - const unsub = this.$$c.$on(type, listener); - this.$$l_u.set(listener, unsub); - } - } - this.$$l = {}; - } - } - // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte - // and setting attributes through setAttribute etc, this is helpful - attributeChangedCallback(attr2, _oldValue, newValue) { - var _a; - if (this.$$r) - return; - attr2 = this.$$g_p(attr2); - this.$$d[attr2] = get_custom_element_value(attr2, newValue, this.$$p_d, "toProp"); - (_a = this.$$c) == null ? void 0 : _a.$set({ [attr2]: this.$$d[attr2] }); - } - disconnectedCallback() { - this.$$cn = false; - Promise.resolve().then(() => { - if (!this.$$cn) { - this.$$c.$destroy(); - this.$$c = void 0; - } - }); - } - $$g_p(attribute_name) { - return Object.keys(this.$$p_d).find( - (key) => this.$$p_d[key].attribute === attribute_name || !this.$$p_d[key].attribute && key.toLowerCase() === attribute_name - ) || attribute_name; - } - }; -} -function get_custom_element_value(prop, value, props_definition, transform) { - var _a; - const type = (_a = props_definition[prop]) == null ? void 0 : _a.type; - value = type === "Boolean" && typeof value !== "boolean" ? value != null : value; - if (!transform || !props_definition[prop]) { - return value; - } else if (transform === "toAttribute") { - switch (type) { - case "Object": - case "Array": - return value == null ? null : JSON.stringify(value); - case "Boolean": - return value ? "" : null; - case "Number": - return value == null ? null : value; - default: - return value; - } - } else { - switch (type) { - case "Object": - case "Array": - return value && JSON.parse(value); - case "Boolean": - return value; - case "Number": - return value != null ? +value : value; - default: - return value; - } - } -} -var SvelteComponent = class { - constructor() { - /** - * ### PRIVATE API - * - * Do not use, may change at any time - * - * @type {any} - */ - __publicField(this, "$$"); - /** - * ### PRIVATE API - * - * Do not use, may change at any time - * - * @type {any} - */ - __publicField(this, "$$set"); - } - /** @returns {void} */ - $destroy() { - destroy_component(this, 1); - this.$destroy = noop; - } - /** - * @template {Extract} K - * @param {K} type - * @param {((e: Events[K]) => void) | null | undefined} callback - * @returns {() => void} - */ - $on(type, callback) { - if (!is_function(callback)) { - return noop; - } - const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []); - callbacks.push(callback); - return () => { - const index = callbacks.indexOf(callback); - if (index !== -1) - callbacks.splice(index, 1); - }; - } - /** - * @param {Partial} props - * @returns {void} - */ - $set(props) { - if (this.$$set && !is_empty(props)) { - this.$$.skip_bound = true; - this.$$set(props); - this.$$.skip_bound = false; - } - } -}; - -// node_modules/svelte/src/shared/version.js -var PUBLIC_VERSION = "4"; - -// node_modules/svelte/src/runtime/internal/disclose-version/index.js -if (typeof window !== "undefined") - (window.__svelte || (window.__svelte = { v: /* @__PURE__ */ new Set() })).v.add(PUBLIC_VERSION); - -// src/ui/main.svelte -var import_obsidian4 = require("obsidian"); - -// src/ui/tasks/store.ts -var import_obsidian2 = require("obsidian"); - -// src/ui/tasks/task.ts -var import_sha256 = __toESM(require_sha256()); -var Task = class { - constructor(rawContent, fileHandle, rowIndex, columnTagTable) { - const task = this._deserialise(rawContent, fileHandle, rowIndex); - this.id = task.id; - this.content = task.content; - this.done = task.done; - this.path = fileHandle.path; - this.rowIndex = rowIndex; - let column; - for (const tag of task.tags) { - if (tag in columnTagTable || tag === "done") { - column = tag; - break; - } - } - this.column = column; - } - _deserialise(rawContent, fileHandle, rowIndex) { - const [, remainder = ""] = rawContent.split("- ["); - const [status, content = ""] = remainder.split("] "); - const { tags, cleanedContent } = getTags(content); - return { - id: (0, import_sha256.default)(content + fileHandle.path + rowIndex).toString(), - done: status === "x", - content: cleanedContent, - tags - }; - } - serialise(data) { - var _a; - const done = data.column === "done" || this.done; - const column = (_a = data.column) != null ? _a : this.column; - return `- [${done ? "x" : " "}] ${this.content}${column ? ` #${column}` : ""}`; - } -}; -function isTaskString(input) { - return taskStringRegex.test(input); -} -var taskStringRegex = /^\s*-\s\[[x\s]\]\s/; -function getTags(content) { - const tags = /* @__PURE__ */ new Set(); - let cleanedContent = content; - const allMatches = content.matchAll(/#([\w-]+)/g); - for (const match of [...allMatches]) { - const maybeTag = match[1]; - if (maybeTag) { - tags.add(maybeTag); - cleanedContent = cleanedContent.replaceAll(`#${maybeTag}`, ""); - } - } - return { tags: [...tags], cleanedContent: cleanedContent.trim() }; -} - -// node_modules/svelte/src/runtime/store/index.js -var subscriber_queue = []; -function writable(value, start = noop) { - let stop; - const subscribers = /* @__PURE__ */ new Set(); - function set(new_value) { - if (safe_not_equal(value, new_value)) { - value = new_value; - if (stop) { - const run_queue = !subscriber_queue.length; - for (const subscriber of subscribers) { - subscriber[1](); - subscriber_queue.push(subscriber, value); - } - if (run_queue) { - for (let i = 0; i < subscriber_queue.length; i += 2) { - subscriber_queue[i][0](subscriber_queue[i + 1]); - } - subscriber_queue.length = 0; - } - } - } - } - function update2(fn) { - set(fn(value)); - } - function subscribe2(run2, invalidate = noop) { - const subscriber = [run2, invalidate]; - subscribers.add(subscriber); - if (subscribers.size === 1) { - stop = start(set, update2) || noop; - } - run2(value); - return () => { - subscribers.delete(subscriber); - if (subscribers.size === 0 && stop) { - stop(); - stop = null; - } - }; - } - return { set, update: update2, subscribe: subscribe2 }; -} - -// src/ui/tasks/tasks.ts -async function updateMapsFromFile({ - fileHandle, - taskIdsByFileHandle, - tasksByTaskId, - metadataByTaskId, - vault, - columnTagTableStore: columnTagTableStore2 -}) { - var _a; - try { - const previousTaskIds = (_a = taskIdsByFileHandle.get(fileHandle)) != null ? _a : /* @__PURE__ */ new Set(); - const newTaskIds = /* @__PURE__ */ new Set(); - const contents = await vault.read(fileHandle); - const rows = contents.split("\n"); - const columnTagTable = get_store_value(columnTagTableStore2); - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - if (!row) { - continue; - } - if (isTaskString(row)) { - const task = new Task(row, fileHandle, i, columnTagTable); - newTaskIds.add(task.id); - tasksByTaskId.set(task.id, task); - metadataByTaskId.set(task.id, { rowIndex: i, fileHandle }); - previousTaskIds.delete(task.id); - } - } - for (const prevId of previousTaskIds) { - tasksByTaskId.delete(prevId); - metadataByTaskId.delete(prevId); - } - taskIdsByFileHandle.set(fileHandle, newTaskIds); - } catch (e) { - } -} - -// src/ui/tasks/actions.ts -var import_obsidian = require("obsidian"); -function createTaskActions({ - tasksByTaskId, - metadataByTaskId, - vault, - workspace -}) { - async function changeColumn(id, newColumn) { - const metadata = metadataByTaskId.get(id); - const task = tasksByTaskId.get(id); - if (!metadata || !task) { - return; - } - const newTaskString = task.serialise({ column: newColumn }); - await updateRow( - vault, - metadata.fileHandle, - metadata.rowIndex, - newTaskString - ); - } - async function viewFile(id) { - const metadata = metadataByTaskId.get(id); - if (!metadata) { - return; - } - const { fileHandle, rowIndex } = metadata; - const leaf = workspace.getLeaf("tab"); - await leaf.openFile(fileHandle); - const editorView = workspace.getActiveViewOfType(import_obsidian.MarkdownView); - editorView == null ? void 0 : editorView.editor.setCursor(rowIndex); - } - return { changeColumn, viewFile }; -} -async function updateRow(vault, fileHandle, row, newText) { - const file = await vault.read(fileHandle); - const rows = file.split("\n"); - if (rows.length < row) { - return; - } - rows[row] = newText; - const newFile = rows.join("\n"); - await vault.modify(fileHandle, newFile); -} - -// src/ui/tasks/store.ts -function createTasksStore(vault, workspace, registerEvent, columnTagTableStore2) { - const tasksStore = writable([]); - let timer; - const tasksByTaskId = /* @__PURE__ */ new Map(); - const metadataByTaskId = /* @__PURE__ */ new Map(); - const taskIdsByFileHandle = /* @__PURE__ */ new Map(); - const fileHandles = vault.getMarkdownFiles(); - function debounceSetTasks() { - if (!timer) { - timer = window.setTimeout(() => { - timer = void 0; - tasksStore.set([...tasksByTaskId.values()]); - }, 50); - } - } - for (const fileHandle of fileHandles) { - updateMapsFromFile({ - fileHandle, - tasksByTaskId, - metadataByTaskId, - taskIdsByFileHandle, - vault, - columnTagTableStore: columnTagTableStore2 - }).then(() => { - debounceSetTasks(); - }); - } - registerEvent( - vault.on("modify", (fileHandle) => { - if (fileHandle instanceof import_obsidian2.TFile) { - updateMapsFromFile({ - fileHandle, - tasksByTaskId, - metadataByTaskId, - taskIdsByFileHandle, - vault, - columnTagTableStore: columnTagTableStore2 - }).then(() => { - debounceSetTasks(); - }); - } - }) - ); - registerEvent( - vault.on("create", (fileHandle) => { - if (fileHandle instanceof import_obsidian2.TFile) { - updateMapsFromFile({ - fileHandle, - tasksByTaskId, - metadataByTaskId, - taskIdsByFileHandle, - vault, - columnTagTableStore: columnTagTableStore2 - }).then(() => { - debounceSetTasks(); - }); - } - }) - ); - registerEvent( - vault.on("delete", (fileHandle) => { - if (fileHandle instanceof import_obsidian2.TFile) { - } - }) - ); - registerEvent( - vault.on("rename", (fileHandle) => { - if (fileHandle instanceof import_obsidian2.TFile) { - } - }) - ); - const taskActions = createTaskActions({ - tasksByTaskId, - metadataByTaskId, - vault, - workspace - }); - return { tasksStore, taskActions }; -} - -// src/ui/columns/columns.ts -function createColumnTagTable({ - columns -}) { - const output = {}; - for (const column of columns) { - output[kebab(column)] = column; - } - return output; -} -function kebab(input) { - return input.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z0-9-]/g, "").replaceAll(/-+/g, "-"); -} -var columnTagTableStore = writable({}); - -// src/ui/components/task_menu.svelte -var import_obsidian3 = require("obsidian"); -function add_css(target) { - append_styles(target, "svelte-aq3t9y", "span.svelte-aq3t9y{width:24px;height:24px;display:flex;justify-content:center;align-items:center;border-radius:var(--radius-s);transition:background linear 100ms;cursor:pointer}span.svelte-aq3t9y:hover{background:var(--background-modifier-hover)}"); -} -function create_fragment(ctx) { - let span; - let mounted; - let dispose; - return { - c() { - span = element("span"); - attr(span, "role", "button"); - attr(span, "tabindex", "0"); - attr(span, "class", "svelte-aq3t9y"); - }, - m(target, anchor) { - insert(target, span, anchor); - ctx[4](span); - if (!mounted) { - dispose = listen( - span, - "click", - /*click_handler*/ - ctx[5] - ); - mounted = true; - } - }, - p: noop, - i: noop, - o: noop, - d(detaching) { - if (detaching) { - detach(span); - } - ctx[4](null); - mounted = false; - dispose(); - } - }; -} -function instance($$self, $$props, $$invalidate) { - let $columnTagTableStore; - component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(6, $columnTagTableStore = $$value)); - let { task } = $$props; - let { taskActions } = $$props; - let element2; - function showMenu(e) { - const menu = new import_obsidian3.Menu(); - menu.addItem((i) => { - i.setTitle(`Go to file`).onClick(() => taskActions.viewFile(task.id)); - }); - menu.addSeparator(); - for (const [tag, label] of Object.entries($columnTagTableStore)) { - menu.addItem((i) => { - i.setTitle(`Move to ${label}`).onClick(() => taskActions.changeColumn(task.id, tag)); - if (task.column === tag) { - i.setDisabled(true); - } - }); - } - menu.addSeparator(); - menu.addItem((i) => { - i.setTitle(`Move to done`).onClick(() => taskActions.changeColumn(task.id, "done")); - if (task.column === "done") { - i.setDisabled(true); - } - }); - menu.showAtMouseEvent(e); - } - function span_binding($$value) { - binding_callbacks[$$value ? "unshift" : "push"](() => { - element2 = $$value; - $$invalidate(0, element2); - }); - } - const click_handler = (e) => showMenu(e); - $$self.$$set = ($$props2) => { - if ("task" in $$props2) - $$invalidate(2, task = $$props2.task); - if ("taskActions" in $$props2) - $$invalidate(3, taskActions = $$props2.taskActions); - }; - $$self.$$.update = () => { - if ($$self.$$.dirty & /*element*/ - 1) { - $: { - if (element2) { - (0, import_obsidian3.setIcon)(element2, "lucide-more-vertical"); - } - } - } - }; - return [element2, showMenu, task, taskActions, span_binding, click_handler]; -} -var Task_menu = class extends SvelteComponent { - constructor(options) { - super(); - init(this, options, instance, create_fragment, safe_not_equal, { task: 2, taskActions: 3 }, add_css); - } -}; -var task_menu_default = Task_menu; - -// src/ui/components/task.svelte -function add_css2(target) { - append_styles(target, "svelte-1mufstf", ".task.svelte-1mufstf.svelte-1mufstf{background-color:var(--background-primary-alt);border-radius:var(--radius-m);border:var(--border-width) solid var(--background-modifier-border);padding:var(--size-4-2);display:grid;grid-template-columns:1fr auto}.task.svelte-1mufstf p.svelte-1mufstf{margin-top:0}.task.svelte-1mufstf p.svelte-1mufstf:last-child{margin-bottom:0}"); -} -function create_fragment2(ctx) { - let div1; - let div0; - let p; - let t0_value = ( - /*task*/ - ctx[0].content + "" - ); - let t0; - let t1; - let taskmenu; - let current; - taskmenu = new task_menu_default({ - props: { - task: ( - /*task*/ - ctx[0] - ), - taskActions: ( - /*taskActions*/ - ctx[1] - ) - } - }); - return { - c() { - div1 = element("div"); - div0 = element("div"); - p = element("p"); - t0 = text(t0_value); - t1 = space(); - create_component(taskmenu.$$.fragment); - attr(p, "class", "svelte-1mufstf"); - attr(div0, "class", "task-content"); - attr(div1, "class", "task svelte-1mufstf"); - }, - m(target, anchor) { - insert(target, div1, anchor); - append(div1, div0); - append(div0, p); - append(p, t0); - append(div1, t1); - mount_component(taskmenu, div1, null); - current = true; - }, - p(ctx2, [dirty]) { - if ((!current || dirty & /*task*/ - 1) && t0_value !== (t0_value = /*task*/ - ctx2[0].content + "")) - set_data(t0, t0_value); - const taskmenu_changes = {}; - if (dirty & /*task*/ - 1) - taskmenu_changes.task = /*task*/ - ctx2[0]; - if (dirty & /*taskActions*/ - 2) - taskmenu_changes.taskActions = /*taskActions*/ - ctx2[1]; - taskmenu.$set(taskmenu_changes); - }, - i(local) { - if (current) - return; - transition_in(taskmenu.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(taskmenu.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) { - detach(div1); - } - destroy_component(taskmenu); - } - }; -} -function instance2($$self, $$props, $$invalidate) { - let { task } = $$props; - let { taskActions } = $$props; - $$self.$$set = ($$props2) => { - if ("task" in $$props2) - $$invalidate(0, task = $$props2.task); - if ("taskActions" in $$props2) - $$invalidate(1, taskActions = $$props2.taskActions); - }; - return [task, taskActions]; -} -var Task3 = class extends SvelteComponent { - constructor(options) { - super(); - init(this, options, instance2, create_fragment2, safe_not_equal, { task: 0, taskActions: 1 }, add_css2); - } -}; -var task_default = Task3; - -// src/ui/components/column.svelte -function add_css3(target) { - append_styles(target, "svelte-e4tnso", ".column.svelte-e4tnso.svelte-e4tnso{width:220px;flex-shrink:0;padding:var(--size-4-3);border-radius:var(--radius-m);border:var(--border-width) solid var(--background-modifier-border);background-color:var(--background-primary)}.column.svelte-e4tnso h2.svelte-e4tnso{font-size:var(--font-ui-larger);font-weight:var(--font-bold);margin:0}.column.svelte-e4tnso .divide.svelte-e4tnso{width:calc(100% + calc(2 * var(--size-4-3)));border-bottom:var(--border-width) solid\n var(--background-modifier-border);margin:var(--size-4-3) calc(-1 * var(--size-4-3))}.column.svelte-e4tnso .tasks.svelte-e4tnso{display:flex;flex-direction:column;gap:var(--size-4-2)}"); -} -function get_each_context(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[7] = list[i]; - return child_ctx; -} -function create_if_block(ctx) { - let div2; - let h2; - let t0; - let t1; - let div0; - let t2; - let div1; - let current; - let each_value = ensure_array_like( - /*sortedTasks*/ - ctx[3] - ); - let each_blocks = []; - for (let i = 0; i < each_value.length; i += 1) { - each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i)); - } - const out = (i) => transition_out(each_blocks[i], 1, 1, () => { - each_blocks[i] = null; - }); - return { - c() { - div2 = element("div"); - h2 = element("h2"); - t0 = text( - /*columnTitle*/ - ctx[4] - ); - t1 = space(); - div0 = element("div"); - t2 = space(); - div1 = element("div"); - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - attr(h2, "class", "svelte-e4tnso"); - attr(div0, "class", "divide svelte-e4tnso"); - attr(div1, "class", "tasks svelte-e4tnso"); - attr(div2, "class", "column svelte-e4tnso"); - }, - m(target, anchor) { - insert(target, div2, anchor); - append(div2, h2); - append(h2, t0); - append(div2, t1); - append(div2, div0); - append(div2, t2); - append(div2, div1); - for (let i = 0; i < each_blocks.length; i += 1) { - if (each_blocks[i]) { - each_blocks[i].m(div1, null); - } - } - current = true; - }, - p(ctx2, dirty) { - if (!current || dirty & /*columnTitle*/ - 16) - set_data( - t0, - /*columnTitle*/ - ctx2[4] - ); - if (dirty & /*sortedTasks, taskActions*/ - 12) { - each_value = ensure_array_like( - /*sortedTasks*/ - ctx2[3] - ); - let i; - for (i = 0; i < each_value.length; i += 1) { - const child_ctx = get_each_context(ctx2, each_value, i); - if (each_blocks[i]) { - each_blocks[i].p(child_ctx, dirty); - transition_in(each_blocks[i], 1); - } else { - each_blocks[i] = create_each_block(child_ctx); - each_blocks[i].c(); - transition_in(each_blocks[i], 1); - each_blocks[i].m(div1, null); - } - } - group_outros(); - for (i = each_value.length; i < each_blocks.length; i += 1) { - out(i); - } - check_outros(); - } - }, - i(local) { - if (current) - return; - for (let i = 0; i < each_value.length; i += 1) { - transition_in(each_blocks[i]); - } - current = true; - }, - o(local) { - each_blocks = each_blocks.filter(Boolean); - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - current = false; - }, - d(detaching) { - if (detaching) { - detach(div2); - } - destroy_each(each_blocks, detaching); - } - }; -} -function create_each_block(ctx) { - let taskcomponent; - let current; - taskcomponent = new task_default({ - props: { - task: ( - /*task*/ - ctx[7] - ), - taskActions: ( - /*taskActions*/ - ctx[2] - ) - } - }); - return { - c() { - create_component(taskcomponent.$$.fragment); - }, - m(target, anchor) { - mount_component(taskcomponent, target, anchor); - current = true; - }, - p(ctx2, dirty) { - const taskcomponent_changes = {}; - if (dirty & /*sortedTasks*/ - 8) - taskcomponent_changes.task = /*task*/ - ctx2[7]; - if (dirty & /*taskActions*/ - 4) - taskcomponent_changes.taskActions = /*taskActions*/ - ctx2[2]; - taskcomponent.$set(taskcomponent_changes); - }, - i(local) { - if (current) - return; - transition_in(taskcomponent.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(taskcomponent.$$.fragment, local); - current = false; - }, - d(detaching) { - destroy_component(taskcomponent, detaching); - } - }; -} -function create_fragment3(ctx) { - let if_block_anchor; - let current; - let if_block = (!/*hideOnEmpty*/ - ctx[0] || /*tasks*/ - ctx[1].length) && create_if_block(ctx); - return { - c() { - if (if_block) - if_block.c(); - if_block_anchor = empty(); - }, - m(target, anchor) { - if (if_block) - if_block.m(target, anchor); - insert(target, if_block_anchor, anchor); - current = true; - }, - p(ctx2, [dirty]) { - if (!/*hideOnEmpty*/ - ctx2[0] || /*tasks*/ - ctx2[1].length) { - if (if_block) { - if_block.p(ctx2, dirty); - if (dirty & /*hideOnEmpty, tasks*/ - 3) { - transition_in(if_block, 1); - } - } else { - if_block = create_if_block(ctx2); - if_block.c(); - transition_in(if_block, 1); - if_block.m(if_block_anchor.parentNode, if_block_anchor); - } - } else if (if_block) { - group_outros(); - transition_out(if_block, 1, 1, () => { - if_block = null; - }); - check_outros(); - } - }, - i(local) { - if (current) - return; - transition_in(if_block); - current = true; - }, - o(local) { - transition_out(if_block); - current = false; - }, - d(detaching) { - if (detaching) { - detach(if_block_anchor); - } - if (if_block) - if_block.d(detaching); - } - }; -} -function getColumnTitle(column, columnTagTable) { - switch (column) { - case "done": - return "Done"; - case "uncategorised": - return "Uncategorised"; - default: - return columnTagTable[column]; - } -} -function instance3($$self, $$props, $$invalidate) { - let columnTitle; - let sortedTasks; - let $columnTagTableStore; - component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(6, $columnTagTableStore = $$value)); - let { column } = $$props; - let { hideOnEmpty = false } = $$props; - let { tasks } = $$props; - let { taskActions } = $$props; - $$self.$$set = ($$props2) => { - if ("column" in $$props2) - $$invalidate(5, column = $$props2.column); - if ("hideOnEmpty" in $$props2) - $$invalidate(0, hideOnEmpty = $$props2.hideOnEmpty); - if ("tasks" in $$props2) - $$invalidate(1, tasks = $$props2.tasks); - if ("taskActions" in $$props2) - $$invalidate(2, taskActions = $$props2.taskActions); - }; - $$self.$$.update = () => { - if ($$self.$$.dirty & /*column, $columnTagTableStore*/ - 96) { - $: - $$invalidate(4, columnTitle = getColumnTitle(column, $columnTagTableStore)); - } - if ($$self.$$.dirty & /*tasks*/ - 2) { - $: - $$invalidate(3, sortedTasks = tasks.sort((a, b) => { - if (a.path === b.path) { - return a.rowIndex - b.rowIndex; - } else { - return a.path.localeCompare(b.path); - } - })); - } - }; - return [ - hideOnEmpty, - tasks, - taskActions, - sortedTasks, - columnTitle, - column, - $columnTagTableStore - ]; -} -var Column = class extends SvelteComponent { - constructor(options) { - super(); - init( - this, - options, - instance3, - create_fragment3, - safe_not_equal, - { - column: 5, - hideOnEmpty: 0, - tasks: 1, - taskActions: 2 - }, - add_css3 - ); - } -}; -var column_default = Column; - -// src/ui/main.svelte -function add_css4(target) { - append_styles(target, "svelte-3rjjgi", ".columns.svelte-3rjjgi.svelte-3rjjgi{max-width:100vw;overflow-x:scroll;padding-bottom:var(--size-4-3)}.columns.svelte-3rjjgi>div.svelte-3rjjgi{display:flex;gap:var(--size-4-3)}"); -} -function get_each_context2(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[10] = list[i]; - return child_ctx; -} -function create_each_block2(ctx) { - var _a; - let column_1; - let current; - column_1 = new column_default({ - props: { - column: ( - /*column*/ - ctx[10] - ), - tasks: ( - /*tasksByColumn*/ - (_a = ctx[1][ - /*column*/ - ctx[10] - ]) != null ? _a : [] - ), - taskActions: ( - /*taskActions*/ - ctx[3] - ) - } - }); - return { - c() { - create_component(column_1.$$.fragment); - }, - m(target, anchor) { - mount_component(column_1, target, anchor); - current = true; - }, - p(ctx2, dirty) { - var _a2; - const column_1_changes = {}; - if (dirty & /*columns*/ - 1) - column_1_changes.column = /*column*/ - ctx2[10]; - if (dirty & /*tasksByColumn, columns*/ - 3) - column_1_changes.tasks = /*tasksByColumn*/ - (_a2 = ctx2[1][ - /*column*/ - ctx2[10] - ]) != null ? _a2 : []; - column_1.$set(column_1_changes); - }, - i(local) { - if (current) - return; - transition_in(column_1.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(column_1.$$.fragment, local); - current = false; - }, - d(detaching) { - destroy_component(column_1, detaching); - } - }; -} -function create_fragment4(ctx) { - var _a; - let section; - let h1; - let t1; - let div1; - let div0; - let column0; - let t2; - let t3; - let column1; - let current; - column0 = new column_default({ - props: { - column: "uncategorised", - hideOnEmpty: true, - tasks: ( - /*tasksByColumn*/ - ctx[1]["uncategorised"] - ), - taskActions: ( - /*taskActions*/ - ctx[3] - ) - } - }); - let each_value = ensure_array_like( - /*columns*/ - ctx[0] - ); - let each_blocks = []; - for (let i = 0; i < each_value.length; i += 1) { - each_blocks[i] = create_each_block2(get_each_context2(ctx, each_value, i)); - } - const out = (i) => transition_out(each_blocks[i], 1, 1, () => { - each_blocks[i] = null; - }); - column1 = new column_default({ - props: { - column: "done", - tasks: ( - /*tasksByColumn*/ - (_a = ctx[1]["done"]) != null ? _a : [] - ), - taskActions: ( - /*taskActions*/ - ctx[3] - ) - } - }); - return { - c() { - section = element("section"); - h1 = element("h1"); - h1.textContent = "Project Planner"; - t1 = space(); - div1 = element("div"); - div0 = element("div"); - create_component(column0.$$.fragment); - t2 = space(); - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - t3 = space(); - create_component(column1.$$.fragment); - attr(div0, "class", "svelte-3rjjgi"); - attr(div1, "class", "columns svelte-3rjjgi"); - }, - m(target, anchor) { - insert(target, section, anchor); - append(section, h1); - append(section, t1); - append(section, div1); - append(div1, div0); - mount_component(column0, div0, null); - append(div0, t2); - for (let i = 0; i < each_blocks.length; i += 1) { - if (each_blocks[i]) { - each_blocks[i].m(div0, null); - } - } - append(div0, t3); - mount_component(column1, div0, null); - current = true; - }, - p(ctx2, [dirty]) { - var _a2; - const column0_changes = {}; - if (dirty & /*tasksByColumn*/ - 2) - column0_changes.tasks = /*tasksByColumn*/ - ctx2[1]["uncategorised"]; - column0.$set(column0_changes); - if (dirty & /*columns, tasksByColumn, taskActions*/ - 11) { - each_value = ensure_array_like( - /*columns*/ - ctx2[0] - ); - let i; - for (i = 0; i < each_value.length; i += 1) { - const child_ctx = get_each_context2(ctx2, each_value, i); - if (each_blocks[i]) { - each_blocks[i].p(child_ctx, dirty); - transition_in(each_blocks[i], 1); - } else { - each_blocks[i] = create_each_block2(child_ctx); - each_blocks[i].c(); - transition_in(each_blocks[i], 1); - each_blocks[i].m(div0, t3); - } - } - group_outros(); - for (i = each_value.length; i < each_blocks.length; i += 1) { - out(i); - } - check_outros(); - } - const column1_changes = {}; - if (dirty & /*tasksByColumn*/ - 2) - column1_changes.tasks = /*tasksByColumn*/ - (_a2 = ctx2[1]["done"]) != null ? _a2 : []; - column1.$set(column1_changes); - }, - i(local) { - if (current) - return; - transition_in(column0.$$.fragment, local); - for (let i = 0; i < each_value.length; i += 1) { - transition_in(each_blocks[i]); - } - transition_in(column1.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(column0.$$.fragment, local); - each_blocks = each_blocks.filter(Boolean); - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - transition_out(column1.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) { - detach(section); - } - destroy_component(column0); - destroy_each(each_blocks, detaching); - destroy_component(column1); - } - }; -} -function groupByColumnTag(tasks) { - var _a; - const output = { uncategorised: [], done: [] }; - for (const task of tasks) { - if (task.done) { - output["done"] = output["done"].concat(task); - } else if (task.column) { - output[task.column] = ((_a = output[task.column]) != null ? _a : []).concat(task); - } else { - output["uncategorised"] = output["uncategorised"].concat(task); - } - } - return output; -} -function instance4($$self, $$props, $$invalidate) { - let tasksByColumn; - let $tasksStore; - let $columnTagTableStore; - component_subscribe($$self, columnTagTableStore, ($$value) => $$invalidate(9, $columnTagTableStore = $$value)); - let { vault } = $$props; - let { workspace } = $$props; - let { registerEvent } = $$props; - let { columnConfig = { - columns: ["Later", "Next week", "This week", "Today", "Pending"] - } } = $$props; - const { tasksStore, taskActions } = createTasksStore(vault, workspace, registerEvent, columnTagTableStore); - component_subscribe($$self, tasksStore, (value) => $$invalidate(8, $tasksStore = value)); - let columns; - $$self.$$set = ($$props2) => { - if ("vault" in $$props2) - $$invalidate(4, vault = $$props2.vault); - if ("workspace" in $$props2) - $$invalidate(5, workspace = $$props2.workspace); - if ("registerEvent" in $$props2) - $$invalidate(6, registerEvent = $$props2.registerEvent); - if ("columnConfig" in $$props2) - $$invalidate(7, columnConfig = $$props2.columnConfig); - }; - $$self.$$.update = () => { - if ($$self.$$.dirty & /*columnConfig*/ - 128) { - $: - columnTagTableStore.set(createColumnTagTable(columnConfig)); - } - if ($$self.$$.dirty & /*$columnTagTableStore*/ - 512) { - $: - $$invalidate(0, columns = Object.keys($columnTagTableStore)); - } - if ($$self.$$.dirty & /*$tasksStore*/ - 256) { - $: - $$invalidate(1, tasksByColumn = groupByColumnTag($tasksStore)); - } - }; - return [ - columns, - tasksByColumn, - tasksStore, - taskActions, - vault, - workspace, - registerEvent, - columnConfig, - $tasksStore, - $columnTagTableStore - ]; -} -var Main = class extends SvelteComponent { - constructor(options) { - super(); - init( - this, - options, - instance4, - create_fragment4, - safe_not_equal, - { - vault: 4, - workspace: 5, - registerEvent: 6, - columnConfig: 7 - }, - add_css4 - ); - } -}; -var main_default = Main; - -// src/ui/entry.ts -var APP_VIEW_NAME = "project-plan"; -var AppView = class extends import_obsidian5.ItemView { - constructor() { - super(...arguments); - this.icon = "kanban-square"; - } - getViewType() { - this.leaf.openFile; - return APP_VIEW_NAME; - } - getDisplayText() { - return "Project Planner"; - } - async onOpen() { - this.component = new main_default({ - target: this.contentEl, - props: { - workspace: this.app.workspace, - vault: this.app.vault, - registerEvent: this.registerEvent.bind(this) - } - }); - } - async onClose() { - var _a; - (_a = this.component) == null ? void 0 : _a.$destroy(); - } -}; - -// src/entry.ts -var Base = class extends import_obsidian6.Plugin { - async onload() { - this.registerView(APP_VIEW_NAME, (leaf) => new AppView(leaf)); - this.addRibbonIcon( - "kanban-square", - "Open Kanban", - () => this.activateView() - ); - } - onunload() { - } - async activateView() { - const { workspace } = this.app; - let leaf; - const leaves = workspace.getLeavesOfType(APP_VIEW_NAME); - if (leaves.length > 0) { - leaf = leaves[0]; - } else { - leaf = workspace.getLeaf("tab"); - await leaf.setViewState({ type: APP_VIEW_NAME, active: true }); - } - leaf && workspace.revealLeaf(leaf); - } -}; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9jb3JlLmpzIiwgIm5vZGVfbW9kdWxlcy9jcnlwdG8tanMvc2hhMjU2LmpzIiwgInNyYy9lbnRyeS50cyIsICJzcmMvdWkvZW50cnkudHMiLCAibm9kZV9tb2R1bGVzL3N2ZWx0ZS9zcmMvcnVudGltZS9pbnRlcm5hbC91dGlscy5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2dsb2JhbHMuanMiLCAibm9kZV9tb2R1bGVzL3N2ZWx0ZS9zcmMvcnVudGltZS9pbnRlcm5hbC9SZXNpemVPYnNlcnZlclNpbmdsZXRvbi5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2RvbS5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL2xpZmVjeWNsZS5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL3NjaGVkdWxlci5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9ydW50aW1lL2ludGVybmFsL3RyYW5zaXRpb25zLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvZWFjaC5qcyIsICJub2RlX21vZHVsZXMvc3ZlbHRlL3NyYy9zaGFyZWQvYm9vbGVhbl9hdHRyaWJ1dGVzLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvQ29tcG9uZW50LmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3NoYXJlZC92ZXJzaW9uLmpzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvaW50ZXJuYWwvZGlzY2xvc2UtdmVyc2lvbi9pbmRleC5qcyIsICJzcmMvdWkvbWFpbi5zdmVsdGUiLCAic3JjL3VpL3Rhc2tzL3N0b3JlLnRzIiwgInNyYy91aS90YXNrcy90YXNrLnRzIiwgIm5vZGVfbW9kdWxlcy9zdmVsdGUvc3JjL3J1bnRpbWUvc3RvcmUvaW5kZXguanMiLCAic3JjL3VpL3Rhc2tzL3Rhc2tzLnRzIiwgInNyYy91aS90YXNrcy9hY3Rpb25zLnRzIiwgInNyYy91aS9jb2x1bW5zL2NvbHVtbnMudHMiLCAic3JjL3VpL2NvbXBvbmVudHMvdGFza19tZW51LnN2ZWx0ZSIsICJzcmMvdWkvY29tcG9uZW50cy90YXNrLnN2ZWx0ZSIsICJzcmMvdWkvY29tcG9uZW50cy9jb2x1bW4uc3ZlbHRlIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyI7KGZ1bmN0aW9uIChyb290LCBmYWN0b3J5KSB7XG5cdGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuXHRcdC8vIENvbW1vbkpTXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzID0gZmFjdG9yeSgpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0cm9vdC5DcnlwdG9KUyA9IGZhY3RvcnkoKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoKSB7XG5cblx0LypnbG9iYWxzIHdpbmRvdywgZ2xvYmFsLCByZXF1aXJlKi9cblxuXHQvKipcblx0ICogQ3J5cHRvSlMgY29yZSBjb21wb25lbnRzLlxuXHQgKi9cblx0dmFyIENyeXB0b0pTID0gQ3J5cHRvSlMgfHwgKGZ1bmN0aW9uIChNYXRoLCB1bmRlZmluZWQpIHtcblxuXHQgICAgdmFyIGNyeXB0bztcblxuXHQgICAgLy8gTmF0aXZlIGNyeXB0byBmcm9tIHdpbmRvdyAoQnJvd3Nlcilcblx0ICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuY3J5cHRvKSB7XG5cdCAgICAgICAgY3J5cHRvID0gd2luZG93LmNyeXB0bztcblx0ICAgIH1cblxuXHQgICAgLy8gTmF0aXZlIGNyeXB0byBpbiB3ZWIgd29ya2VyIChCcm93c2VyKVxuXHQgICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiBzZWxmLmNyeXB0bykge1xuXHQgICAgICAgIGNyeXB0byA9IHNlbGYuY3J5cHRvO1xuXHQgICAgfVxuXG5cdCAgICAvLyBOYXRpdmUgY3J5cHRvIGZyb20gd29ya2VyXG5cdCAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbFRoaXMuY3J5cHRvKSB7XG5cdCAgICAgICAgY3J5cHRvID0gZ2xvYmFsVGhpcy5jcnlwdG87XG5cdCAgICB9XG5cblx0ICAgIC8vIE5hdGl2ZSAoZXhwZXJpbWVudGFsIElFIDExKSBjcnlwdG8gZnJvbSB3aW5kb3cgKEJyb3dzZXIpXG5cdCAgICBpZiAoIWNyeXB0byAmJiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cubXNDcnlwdG8pIHtcblx0ICAgICAgICBjcnlwdG8gPSB3aW5kb3cubXNDcnlwdG87XG5cdCAgICB9XG5cblx0ICAgIC8vIE5hdGl2ZSBjcnlwdG8gZnJvbSBnbG9iYWwgKE5vZGVKUylcblx0ICAgIGlmICghY3J5cHRvICYmIHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbC5jcnlwdG8pIHtcblx0ICAgICAgICBjcnlwdG8gPSBnbG9iYWwuY3J5cHRvO1xuXHQgICAgfVxuXG5cdCAgICAvLyBOYXRpdmUgY3J5cHRvIGltcG9ydCB2aWEgcmVxdWlyZSAoTm9kZUpTKVxuXHQgICAgaWYgKCFjcnlwdG8gJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicpIHtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKTtcblx0ICAgICAgICB9IGNhdGNoIChlcnIpIHt9XG5cdCAgICB9XG5cblx0ICAgIC8qXG5cdCAgICAgKiBDcnlwdG9ncmFwaGljYWxseSBzZWN1cmUgcHNldWRvcmFuZG9tIG51bWJlciBnZW5lcmF0b3Jcblx0ICAgICAqXG5cdCAgICAgKiBBcyBNYXRoLnJhbmRvbSgpIGlzIGNyeXB0b2dyYXBoaWNhbGx5IG5vdCBzYWZlIHRvIHVzZVxuXHQgICAgICovXG5cdCAgICB2YXIgY3J5cHRvU2VjdXJlUmFuZG9tSW50ID0gZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIGlmIChjcnlwdG8pIHtcblx0ICAgICAgICAgICAgLy8gVXNlIGdldFJhbmRvbVZhbHVlcyBtZXRob2QgKEJyb3dzZXIpXG5cdCAgICAgICAgICAgIGlmICh0eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDMyQXJyYXkoMSkpWzBdO1xuXHQgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7fVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gVXNlIHJhbmRvbUJ5dGVzIG1ldGhvZCAoTm9kZUpTKVxuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGNyeXB0by5yYW5kb21CeXRlcyA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3J5cHRvLnJhbmRvbUJ5dGVzKDQpLnJlYWRJbnQzMkxFKCk7XG5cdCAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHt9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05hdGl2ZSBjcnlwdG8gbW9kdWxlIGNvdWxkIG5vdCBiZSB1c2VkIHRvIGdldCBzZWN1cmUgcmFuZG9tIG51bWJlci4nKTtcblx0ICAgIH07XG5cblx0ICAgIC8qXG5cdCAgICAgKiBMb2NhbCBwb2x5ZmlsbCBvZiBPYmplY3QuY3JlYXRlXG5cblx0ICAgICAqL1xuXHQgICAgdmFyIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgKGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICBmdW5jdGlvbiBGKCkge31cblxuXHQgICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqKSB7XG5cdCAgICAgICAgICAgIHZhciBzdWJ0eXBlO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gb2JqO1xuXG5cdCAgICAgICAgICAgIHN1YnR5cGUgPSBuZXcgRigpO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gbnVsbDtcblxuXHQgICAgICAgICAgICByZXR1cm4gc3VidHlwZTtcblx0ICAgICAgICB9O1xuXHQgICAgfSgpKTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBDcnlwdG9KUyBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogTGlicmFyeSBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX2xpYiA9IEMubGliID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogQmFzZSBvYmplY3QgZm9yIHByb3RvdHlwYWwgaW5oZXJpdGFuY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBCYXNlID0gQ19saWIuQmFzZSA9IChmdW5jdGlvbiAoKSB7XG5cblxuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gdGhpcyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdmVycmlkZXMgUHJvcGVydGllcyB0byBjb3B5IGludG8gdGhlIG5ldyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIG5ldyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIHZhciBNeVR5cGUgPSBDcnlwdG9KUy5saWIuQmFzZS5leHRlbmQoe1xuXHQgICAgICAgICAgICAgKiAgICAgICAgIGZpZWxkOiAndmFsdWUnLFxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgICAgIG1ldGhvZDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgKiAgICAgICAgIH1cblx0ICAgICAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAgICAgKi9cblx0ICAgICAgICAgICAgZXh0ZW5kOiBmdW5jdGlvbiAob3ZlcnJpZGVzKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTcGF3blxuXHQgICAgICAgICAgICAgICAgdmFyIHN1YnR5cGUgPSBjcmVhdGUodGhpcyk7XG5cblx0ICAgICAgICAgICAgICAgIC8vIEF1Z21lbnRcblx0ICAgICAgICAgICAgICAgIGlmIChvdmVycmlkZXMpIHtcblx0ICAgICAgICAgICAgICAgICAgICBzdWJ0eXBlLm1peEluKG92ZXJyaWRlcyk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBkZWZhdWx0IGluaXRpYWxpemVyXG5cdCAgICAgICAgICAgICAgICBpZiAoIXN1YnR5cGUuaGFzT3duUHJvcGVydHkoJ2luaXQnKSB8fCB0aGlzLmluaXQgPT09IHN1YnR5cGUuaW5pdCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHN1YnR5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgc3VidHlwZS4kc3VwZXIuaW5pdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHQgICAgICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemVyJ3MgcHJvdG90eXBlIGlzIHRoZSBzdWJ0eXBlIG9iamVjdFxuXHQgICAgICAgICAgICAgICAgc3VidHlwZS5pbml0LnByb3RvdHlwZSA9IHN1YnR5cGU7XG5cblx0ICAgICAgICAgICAgICAgIC8vIFJlZmVyZW5jZSBzdXBlcnR5cGVcblx0ICAgICAgICAgICAgICAgIHN1YnR5cGUuJHN1cGVyID0gdGhpcztcblxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHN1YnR5cGU7XG5cdCAgICAgICAgICAgIH0sXG5cblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIEV4dGVuZHMgdGhpcyBvYmplY3QgYW5kIHJ1bnMgdGhlIGluaXQgbWV0aG9kLlxuXHQgICAgICAgICAgICAgKiBBcmd1bWVudHMgdG8gY3JlYXRlKCkgd2lsbCBiZSBwYXNzZWQgdG8gaW5pdCgpLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBuZXcgb2JqZWN0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICB2YXIgaW5zdGFuY2UgPSBNeVR5cGUuY3JlYXRlKCk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IHRoaXMuZXh0ZW5kKCk7XG5cdCAgICAgICAgICAgICAgICBpbnN0YW5jZS5pbml0LmFwcGx5KGluc3RhbmNlLCBhcmd1bWVudHMpO1xuXG5cdCAgICAgICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG5cdCAgICAgICAgICAgIH0sXG5cblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCBvYmplY3QuXG5cdCAgICAgICAgICAgICAqIE92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGFkZCBzb21lIGxvZ2ljIHdoZW4geW91ciBvYmplY3RzIGFyZSBjcmVhdGVkLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgdmFyIE15VHlwZSA9IENyeXB0b0pTLmxpYi5CYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgICAgICAqICAgICAgICAgaW5pdDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgKiAgICAgICAgICAgICAvLyAuLi5cblx0ICAgICAgICAgICAgICogICAgICAgICB9XG5cdCAgICAgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgICAgICovXG5cdCAgICAgICAgICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgfSxcblxuXHQgICAgICAgICAgICAvKipcblx0ICAgICAgICAgICAgICogQ29waWVzIHByb3BlcnRpZXMgaW50byB0aGlzIG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgVGhlIHByb3BlcnRpZXMgdG8gbWl4IGluLlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgTXlUeXBlLm1peEluKHtcblx0ICAgICAgICAgICAgICogICAgICAgICBmaWVsZDogJ3ZhbHVlJ1xuXHQgICAgICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBtaXhJbjogZnVuY3Rpb24gKHByb3BlcnRpZXMpIHtcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BlcnR5TmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3Byb3BlcnR5TmFtZV0gPSBwcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV07XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgICAgICAvLyBJRSB3b24ndCBjb3B5IHRvU3RyaW5nIHVzaW5nIHRoZSBsb29wIGFib3ZlXG5cdCAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eSgndG9TdHJpbmcnKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXMudG9TdHJpbmcgPSBwcm9wZXJ0aWVzLnRvU3RyaW5nO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9LFxuXG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBDcmVhdGVzIGEgY29weSBvZiB0aGlzIG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICB2YXIgY2xvbmUgPSBpbnN0YW5jZS5jbG9uZSgpO1xuXHQgICAgICAgICAgICAgKi9cblx0ICAgICAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXQucHJvdG90eXBlLmV4dGVuZCh0aGlzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9KCkpO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFuIGFycmF5IG9mIDMyLWJpdCB3b3Jkcy5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkge0FycmF5fSB3b3JkcyBUaGUgYXJyYXkgb2YgMzItYml0IHdvcmRzLlxuXHQgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IHNpZ0J5dGVzIFRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgYnl0ZXMgaW4gdGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICovXG5cdCAgICB2YXIgV29yZEFycmF5ID0gQ19saWIuV29yZEFycmF5ID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtBcnJheX0gd29yZHMgKE9wdGlvbmFsKSBBbiBhcnJheSBvZiAzMi1iaXQgd29yZHMuXG5cdCAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IHNpZ0J5dGVzIChPcHRpb25hbCkgVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBieXRlcyBpbiB0aGUgd29yZHMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5saWIuV29yZEFycmF5LmNyZWF0ZSgpO1xuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5jcmVhdGUoWzB4MDAwMTAyMDMsIDB4MDQwNTA2MDddKTtcblx0ICAgICAgICAgKiAgICAgdmFyIHdvcmRBcnJheSA9IENyeXB0b0pTLmxpYi5Xb3JkQXJyYXkuY3JlYXRlKFsweDAwMDEwMjAzLCAweDA0MDUwNjA3XSwgNik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgaW5pdDogZnVuY3Rpb24gKHdvcmRzLCBzaWdCeXRlcykge1xuXHQgICAgICAgICAgICB3b3JkcyA9IHRoaXMud29yZHMgPSB3b3JkcyB8fCBbXTtcblxuXHQgICAgICAgICAgICBpZiAoc2lnQnl0ZXMgIT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzID0gc2lnQnl0ZXM7XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzID0gd29yZHMubGVuZ3RoICogNDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIHdvcmQgYXJyYXkgdG8gYSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0VuY29kZXJ9IGVuY29kZXIgKE9wdGlvbmFsKSBUaGUgZW5jb2Rpbmcgc3RyYXRlZ3kgdG8gdXNlLiBEZWZhdWx0OiBDcnlwdG9KUy5lbmMuSGV4XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBzdHJpbmdpZmllZCB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgc3RyaW5nID0gd29yZEFycmF5ICsgJyc7XG5cdCAgICAgICAgICogICAgIHZhciBzdHJpbmcgPSB3b3JkQXJyYXkudG9TdHJpbmcoKTtcblx0ICAgICAgICAgKiAgICAgdmFyIHN0cmluZyA9IHdvcmRBcnJheS50b1N0cmluZyhDcnlwdG9KUy5lbmMuVXRmOCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIChlbmNvZGVyKSB7XG5cdCAgICAgICAgICAgIHJldHVybiAoZW5jb2RlciB8fCBIZXgpLnN0cmluZ2lmeSh0aGlzKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29uY2F0ZW5hdGVzIGEgd29yZCBhcnJheSB0byB0aGlzIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5IHRvIGFwcGVuZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB3b3JkQXJyYXkxLmNvbmNhdCh3b3JkQXJyYXkyKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjb25jYXQ6IGZ1bmN0aW9uICh3b3JkQXJyYXkpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciB0aGlzV29yZHMgPSB0aGlzLndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgdGhhdFdvcmRzID0gd29yZEFycmF5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgdGhpc1NpZ0J5dGVzID0gdGhpcy5zaWdCeXRlcztcblx0ICAgICAgICAgICAgdmFyIHRoYXRTaWdCeXRlcyA9IHdvcmRBcnJheS5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDbGFtcCBleGNlc3MgYml0c1xuXHQgICAgICAgICAgICB0aGlzLmNsYW1wKCk7XG5cblx0ICAgICAgICAgICAgLy8gQ29uY2F0XG5cdCAgICAgICAgICAgIGlmICh0aGlzU2lnQnl0ZXMgJSA0KSB7XG5cdCAgICAgICAgICAgICAgICAvLyBDb3B5IG9uZSBieXRlIGF0IGEgdGltZVxuXHQgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGF0U2lnQnl0ZXM7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgICAgIHZhciB0aGF0Qnl0ZSA9ICh0aGF0V29yZHNbaSA+Pj4gMl0gPj4+ICgyNCAtIChpICUgNCkgKiA4KSkgJiAweGZmO1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXNXb3Jkc1sodGhpc1NpZ0J5dGVzICsgaSkgPj4+IDJdIHw9IHRoYXRCeXRlIDw8ICgyNCAtICgodGhpc1NpZ0J5dGVzICsgaSkgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgLy8gQ29weSBvbmUgd29yZCBhdCBhIHRpbWVcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhhdFNpZ0J5dGVzOyBqICs9IDQpIHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzV29yZHNbKHRoaXNTaWdCeXRlcyArIGopID4+PiAyXSA9IHRoYXRXb3Jkc1tqID4+PiAyXTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0aGlzLnNpZ0J5dGVzICs9IHRoYXRTaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDaGFpbmFibGVcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJlbW92ZXMgaW5zaWduaWZpY2FudCBiaXRzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB3b3JkQXJyYXkuY2xhbXAoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjbGFtcDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gdGhpcy53b3Jkcztcblx0ICAgICAgICAgICAgdmFyIHNpZ0J5dGVzID0gdGhpcy5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDbGFtcFxuXHQgICAgICAgICAgICB3b3Jkc1tzaWdCeXRlcyA+Pj4gMl0gJj0gMHhmZmZmZmZmZiA8PCAoMzIgLSAoc2lnQnl0ZXMgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICB3b3Jkcy5sZW5ndGggPSBNYXRoLmNlaWwoc2lnQnl0ZXMgLyA0KTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIGNvcHkgb2YgdGhpcyB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjbG9uZSA9IHdvcmRBcnJheS5jbG9uZSgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNsb25lOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHZhciBjbG9uZSA9IEJhc2UuY2xvbmUuY2FsbCh0aGlzKTtcblx0ICAgICAgICAgICAgY2xvbmUud29yZHMgPSB0aGlzLndvcmRzLnNsaWNlKDApO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIHdvcmQgYXJyYXkgZmlsbGVkIHdpdGggcmFuZG9tIGJ5dGVzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IG5CeXRlcyBUaGUgbnVtYmVyIG9mIHJhbmRvbSBieXRlcyB0byBnZW5lcmF0ZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHJhbmRvbSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5yYW5kb20oMTYpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHJhbmRvbTogZnVuY3Rpb24gKG5CeXRlcykge1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSBbXTtcblxuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5CeXRlczsgaSArPSA0KSB7XG5cdCAgICAgICAgICAgICAgICB3b3Jkcy5wdXNoKGNyeXB0b1NlY3VyZVJhbmRvbUludCgpKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBuZXcgV29yZEFycmF5LmluaXQod29yZHMsIG5CeXRlcyk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogRW5jb2RlciBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX2VuYyA9IEMuZW5jID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogSGV4IGVuY29kaW5nIHN0cmF0ZWd5LlxuXHQgICAgICovXG5cdCAgICB2YXIgSGV4ID0gQ19lbmMuSGV4ID0ge1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIGEgd29yZCBhcnJheSB0byBhIGhleCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgaGV4IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhleFN0cmluZyA9IENyeXB0b0pTLmVuYy5IZXguc3RyaW5naWZ5KHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbiAod29yZEFycmF5KSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSB3b3JkQXJyYXkud29yZHM7XG5cdCAgICAgICAgICAgIHZhciBzaWdCeXRlcyA9IHdvcmRBcnJheS5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDb252ZXJ0XG5cdCAgICAgICAgICAgIHZhciBoZXhDaGFycyA9IFtdO1xuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpZ0J5dGVzOyBpKyspIHtcblx0ICAgICAgICAgICAgICAgIHZhciBiaXRlID0gKHdvcmRzW2kgPj4+IDJdID4+PiAoMjQgLSAoaSAlIDQpICogOCkpICYgMHhmZjtcblx0ICAgICAgICAgICAgICAgIGhleENoYXJzLnB1c2goKGJpdGUgPj4+IDQpLnRvU3RyaW5nKDE2KSk7XG5cdCAgICAgICAgICAgICAgICBoZXhDaGFycy5wdXNoKChiaXRlICYgMHgwZikudG9TdHJpbmcoMTYpKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBoZXhDaGFycy5qb2luKCcnKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSBoZXggc3RyaW5nIHRvIGEgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBoZXhTdHIgVGhlIGhleCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMuZW5jLkhleC5wYXJzZShoZXhTdHJpbmcpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHBhcnNlOiBmdW5jdGlvbiAoaGV4U3RyKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0XG5cdCAgICAgICAgICAgIHZhciBoZXhTdHJMZW5ndGggPSBoZXhTdHIubGVuZ3RoO1xuXG5cdCAgICAgICAgICAgIC8vIENvbnZlcnRcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gW107XG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGV4U3RyTGVuZ3RoOyBpICs9IDIpIHtcblx0ICAgICAgICAgICAgICAgIHdvcmRzW2kgPj4+IDNdIHw9IHBhcnNlSW50KGhleFN0ci5zdWJzdHIoaSwgMiksIDE2KSA8PCAoMjQgLSAoaSAlIDgpICogNCk7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICByZXR1cm4gbmV3IFdvcmRBcnJheS5pbml0KHdvcmRzLCBoZXhTdHJMZW5ndGggLyAyKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIExhdGluMSBlbmNvZGluZyBzdHJhdGVneS5cblx0ICAgICAqL1xuXHQgICAgdmFyIExhdGluMSA9IENfZW5jLkxhdGluMSA9IHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIHdvcmQgYXJyYXkgdG8gYSBMYXRpbjEgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IHdvcmRBcnJheSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIExhdGluMSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBsYXRpbjFTdHJpbmcgPSBDcnlwdG9KUy5lbmMuTGF0aW4xLnN0cmluZ2lmeSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHN0cmluZ2lmeTogZnVuY3Rpb24gKHdvcmRBcnJheSkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gd29yZEFycmF5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgc2lnQnl0ZXMgPSB3b3JkQXJyYXkuc2lnQnl0ZXM7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgbGF0aW4xQ2hhcnMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaWdCeXRlczsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgYml0ZSA9ICh3b3Jkc1tpID4+PiAyXSA+Pj4gKDI0IC0gKGkgJSA0KSAqIDgpKSAmIDB4ZmY7XG5cdCAgICAgICAgICAgICAgICBsYXRpbjFDaGFycy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYml0ZSkpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGxhdGluMUNoYXJzLmpvaW4oJycpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIExhdGluMSBzdHJpbmcgdG8gYSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGxhdGluMVN0ciBUaGUgTGF0aW4xIHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5lbmMuTGF0aW4xLnBhcnNlKGxhdGluMVN0cmluZyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChsYXRpbjFTdHIpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIGxhdGluMVN0ckxlbmd0aCA9IGxhdGluMVN0ci5sZW5ndGg7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsYXRpbjFTdHJMZW5ndGg7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgd29yZHNbaSA+Pj4gMl0gfD0gKGxhdGluMVN0ci5jaGFyQ29kZUF0KGkpICYgMHhmZikgPDwgKDI0IC0gKGkgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIG5ldyBXb3JkQXJyYXkuaW5pdCh3b3JkcywgbGF0aW4xU3RyTGVuZ3RoKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIFVURi04IGVuY29kaW5nIHN0cmF0ZWd5LlxuXHQgICAgICovXG5cdCAgICB2YXIgVXRmOCA9IENfZW5jLlV0ZjggPSB7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSB3b3JkIGFycmF5IHRvIGEgVVRGLTggc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IHdvcmRBcnJheSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIFVURi04IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHV0ZjhTdHJpbmcgPSBDcnlwdG9KUy5lbmMuVXRmOC5zdHJpbmdpZnkod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBzdHJpbmdpZnk6IGZ1bmN0aW9uICh3b3JkQXJyYXkpIHtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoZXNjYXBlKExhdGluMS5zdHJpbmdpZnkod29yZEFycmF5KSkpO1xuXHQgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01hbGZvcm1lZCBVVEYtOCBkYXRhJyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSBVVEYtOCBzdHJpbmcgdG8gYSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHV0ZjhTdHIgVGhlIFVURi04IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5lbmMuVXRmOC5wYXJzZSh1dGY4U3RyaW5nKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBwYXJzZTogZnVuY3Rpb24gKHV0ZjhTdHIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIExhdGluMS5wYXJzZSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQodXRmOFN0cikpKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFic3RyYWN0IGJ1ZmZlcmVkIGJsb2NrIGFsZ29yaXRobSB0ZW1wbGF0ZS5cblx0ICAgICAqXG5cdCAgICAgKiBUaGUgcHJvcGVydHkgYmxvY2tTaXplIG11c3QgYmUgaW1wbGVtZW50ZWQgaW4gYSBjb25jcmV0ZSBzdWJ0eXBlLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBfbWluQnVmZmVyU2l6ZSBUaGUgbnVtYmVyIG9mIGJsb2NrcyB0aGF0IHNob3VsZCBiZSBrZXB0IHVucHJvY2Vzc2VkIGluIHRoZSBidWZmZXIuIERlZmF1bHQ6IDBcblx0ICAgICAqL1xuXHQgICAgdmFyIEJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0gPSBDX2xpYi5CdWZmZXJlZEJsb2NrQWxnb3JpdGhtID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJlc2V0cyB0aGlzIGJsb2NrIGFsZ29yaXRobSdzIGRhdGEgYnVmZmVyIHRvIGl0cyBpbml0aWFsIHN0YXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBidWZmZXJlZEJsb2NrQWxnb3JpdGhtLnJlc2V0KCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgLy8gSW5pdGlhbCB2YWx1ZXNcblx0ICAgICAgICAgICAgdGhpcy5fZGF0YSA9IG5ldyBXb3JkQXJyYXkuaW5pdCgpO1xuXHQgICAgICAgICAgICB0aGlzLl9uRGF0YUJ5dGVzID0gMDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQWRkcyBuZXcgZGF0YSB0byB0aGlzIGJsb2NrIGFsZ29yaXRobSdzIGJ1ZmZlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gZGF0YSBUaGUgZGF0YSB0byBhcHBlbmQuIFN0cmluZ3MgYXJlIGNvbnZlcnRlZCB0byBhIFdvcmRBcnJheSB1c2luZyBVVEYtOC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fYXBwZW5kKCdkYXRhJyk7XG5cdCAgICAgICAgICogICAgIGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uX2FwcGVuZCh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9hcHBlbmQ6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdCAgICAgICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIFdvcmRBcnJheSwgZWxzZSBhc3N1bWUgV29yZEFycmF5IGFscmVhZHlcblx0ICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICBkYXRhID0gVXRmOC5wYXJzZShkYXRhKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIEFwcGVuZFxuXHQgICAgICAgICAgICB0aGlzLl9kYXRhLmNvbmNhdChkYXRhKTtcblx0ICAgICAgICAgICAgdGhpcy5fbkRhdGFCeXRlcyArPSBkYXRhLnNpZ0J5dGVzO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBQcm9jZXNzZXMgYXZhaWxhYmxlIGRhdGEgYmxvY2tzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogVGhpcyBtZXRob2QgaW52b2tlcyBfZG9Qcm9jZXNzQmxvY2sob2Zmc2V0KSwgd2hpY2ggbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBhIGNvbmNyZXRlIHN1YnR5cGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGRvRmx1c2ggV2hldGhlciBhbGwgYmxvY2tzIGFuZCBwYXJ0aWFsIGJsb2NrcyBzaG91bGQgYmUgcHJvY2Vzc2VkLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgcHJvY2Vzc2VkIGRhdGEuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBwcm9jZXNzZWREYXRhID0gYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fcHJvY2VzcygpO1xuXHQgICAgICAgICAqICAgICB2YXIgcHJvY2Vzc2VkRGF0YSA9IGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uX3Byb2Nlc3MoISEnZmx1c2gnKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBfcHJvY2VzczogZnVuY3Rpb24gKGRvRmx1c2gpIHtcblx0ICAgICAgICAgICAgdmFyIHByb2Nlc3NlZFdvcmRzO1xuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cdCAgICAgICAgICAgIHZhciBkYXRhV29yZHMgPSBkYXRhLndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgZGF0YVNpZ0J5dGVzID0gZGF0YS5zaWdCeXRlcztcblx0ICAgICAgICAgICAgdmFyIGJsb2NrU2l6ZSA9IHRoaXMuYmxvY2tTaXplO1xuXHQgICAgICAgICAgICB2YXIgYmxvY2tTaXplQnl0ZXMgPSBibG9ja1NpemUgKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIENvdW50IGJsb2NrcyByZWFkeVxuXHQgICAgICAgICAgICB2YXIgbkJsb2Nrc1JlYWR5ID0gZGF0YVNpZ0J5dGVzIC8gYmxvY2tTaXplQnl0ZXM7XG5cdCAgICAgICAgICAgIGlmIChkb0ZsdXNoKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBSb3VuZCB1cCB0byBpbmNsdWRlIHBhcnRpYWwgYmxvY2tzXG5cdCAgICAgICAgICAgICAgICBuQmxvY2tzUmVhZHkgPSBNYXRoLmNlaWwobkJsb2Nrc1JlYWR5KTtcblx0ICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIC8vIFJvdW5kIGRvd24gdG8gaW5jbHVkZSBvbmx5IGZ1bGwgYmxvY2tzLFxuXHQgICAgICAgICAgICAgICAgLy8gbGVzcyB0aGUgbnVtYmVyIG9mIGJsb2NrcyB0aGF0IG11c3QgcmVtYWluIGluIHRoZSBidWZmZXJcblx0ICAgICAgICAgICAgICAgIG5CbG9ja3NSZWFkeSA9IE1hdGgubWF4KChuQmxvY2tzUmVhZHkgfCAwKSAtIHRoaXMuX21pbkJ1ZmZlclNpemUsIDApO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQ291bnQgd29yZHMgcmVhZHlcblx0ICAgICAgICAgICAgdmFyIG5Xb3Jkc1JlYWR5ID0gbkJsb2Nrc1JlYWR5ICogYmxvY2tTaXplO1xuXG5cdCAgICAgICAgICAgIC8vIENvdW50IGJ5dGVzIHJlYWR5XG5cdCAgICAgICAgICAgIHZhciBuQnl0ZXNSZWFkeSA9IE1hdGgubWluKG5Xb3Jkc1JlYWR5ICogNCwgZGF0YVNpZ0J5dGVzKTtcblxuXHQgICAgICAgICAgICAvLyBQcm9jZXNzIGJsb2Nrc1xuXHQgICAgICAgICAgICBpZiAobldvcmRzUmVhZHkpIHtcblx0ICAgICAgICAgICAgICAgIGZvciAodmFyIG9mZnNldCA9IDA7IG9mZnNldCA8IG5Xb3Jkc1JlYWR5OyBvZmZzZXQgKz0gYmxvY2tTaXplKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1hbGdvcml0aG0gbG9naWNcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb1Byb2Nlc3NCbG9jayhkYXRhV29yZHMsIG9mZnNldCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBwcm9jZXNzZWQgd29yZHNcblx0ICAgICAgICAgICAgICAgIHByb2Nlc3NlZFdvcmRzID0gZGF0YVdvcmRzLnNwbGljZSgwLCBuV29yZHNSZWFkeSk7XG5cdCAgICAgICAgICAgICAgICBkYXRhLnNpZ0J5dGVzIC09IG5CeXRlc1JlYWR5O1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gUmV0dXJuIHByb2Nlc3NlZCB3b3Jkc1xuXHQgICAgICAgICAgICByZXR1cm4gbmV3IFdvcmRBcnJheS5pbml0KHByb2Nlc3NlZFdvcmRzLCBuQnl0ZXNSZWFkeSk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIHRoaXMgb2JqZWN0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgY2xvbmUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjbG9uZSA9IGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uY2xvbmUoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjbG9uZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICB2YXIgY2xvbmUgPSBCYXNlLmNsb25lLmNhbGwodGhpcyk7XG5cdCAgICAgICAgICAgIGNsb25lLl9kYXRhID0gdGhpcy5fZGF0YS5jbG9uZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgX21pbkJ1ZmZlclNpemU6IDBcblx0ICAgIH0pO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFic3RyYWN0IGhhc2hlciB0ZW1wbGF0ZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gYmxvY2tTaXplIFRoZSBudW1iZXIgb2YgMzItYml0IHdvcmRzIHRoaXMgaGFzaGVyIG9wZXJhdGVzIG9uLiBEZWZhdWx0OiAxNiAoNTEyIGJpdHMpXG5cdCAgICAgKi9cblx0ICAgIHZhciBIYXNoZXIgPSBDX2xpYi5IYXNoZXIgPSBCdWZmZXJlZEJsb2NrQWxnb3JpdGhtLmV4dGVuZCh7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29uZmlndXJhdGlvbiBvcHRpb25zLlxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNmZzogQmFzZS5leHRlbmQoKSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCBoYXNoZXIuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgaGFzaCBjb21wdXRhdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2hlciA9IENyeXB0b0pTLmFsZ28uU0hBMjU2LmNyZWF0ZSgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGluaXQ6IGZ1bmN0aW9uIChjZmcpIHtcblx0ICAgICAgICAgICAgLy8gQXBwbHkgY29uZmlnIGRlZmF1bHRzXG5cdCAgICAgICAgICAgIHRoaXMuY2ZnID0gdGhpcy5jZmcuZXh0ZW5kKGNmZyk7XG5cblx0ICAgICAgICAgICAgLy8gU2V0IGluaXRpYWwgdmFsdWVzXG5cdCAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmVzZXRzIHRoaXMgaGFzaGVyIHRvIGl0cyBpbml0aWFsIHN0YXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBoYXNoZXIucmVzZXQoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBSZXNldCBkYXRhIGJ1ZmZlclxuXHQgICAgICAgICAgICBCdWZmZXJlZEJsb2NrQWxnb3JpdGhtLnJlc2V0LmNhbGwodGhpcyk7XG5cblx0ICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1oYXNoZXIgbG9naWNcblx0ICAgICAgICAgICAgdGhpcy5fZG9SZXNldCgpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBVcGRhdGVzIHRoaXMgaGFzaGVyIHdpdGggYSBtZXNzYWdlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBtZXNzYWdlVXBkYXRlIFRoZSBtZXNzYWdlIHRvIGFwcGVuZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0hhc2hlcn0gVGhpcyBoYXNoZXIuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGhhc2hlci51cGRhdGUoJ21lc3NhZ2UnKTtcblx0ICAgICAgICAgKiAgICAgaGFzaGVyLnVwZGF0ZSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHVwZGF0ZTogZnVuY3Rpb24gKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgLy8gQXBwZW5kXG5cdCAgICAgICAgICAgIHRoaXMuX2FwcGVuZChtZXNzYWdlVXBkYXRlKTtcblxuXHQgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGhhc2hcblx0ICAgICAgICAgICAgdGhpcy5fcHJvY2VzcygpO1xuXG5cdCAgICAgICAgICAgIC8vIENoYWluYWJsZVxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogRmluYWxpemVzIHRoZSBoYXNoIGNvbXB1dGF0aW9uLlxuXHQgICAgICAgICAqIE5vdGUgdGhhdCB0aGUgZmluYWxpemUgb3BlcmF0aW9uIGlzIGVmZmVjdGl2ZWx5IGEgZGVzdHJ1Y3RpdmUsIHJlYWQtb25jZSBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2VVcGRhdGUgKE9wdGlvbmFsKSBBIGZpbmFsIG1lc3NhZ2UgdXBkYXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgaGFzaC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUoKTtcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUoJ21lc3NhZ2UnKTtcblx0ICAgICAgICAgKiAgICAgdmFyIGhhc2ggPSBoYXNoZXIuZmluYWxpemUod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBmaW5hbGl6ZTogZnVuY3Rpb24gKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgLy8gRmluYWwgbWVzc2FnZSB1cGRhdGVcblx0ICAgICAgICAgICAgaWYgKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuX2FwcGVuZChtZXNzYWdlVXBkYXRlKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIFBlcmZvcm0gY29uY3JldGUtaGFzaGVyIGxvZ2ljXG5cdCAgICAgICAgICAgIHZhciBoYXNoID0gdGhpcy5fZG9GaW5hbGl6ZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBoYXNoO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBibG9ja1NpemU6IDUxMi8zMixcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgYSBzaG9ydGN1dCBmdW5jdGlvbiB0byBhIGhhc2hlcidzIG9iamVjdCBpbnRlcmZhY2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0hhc2hlcn0gaGFzaGVyIFRoZSBoYXNoZXIgdG8gY3JlYXRlIGEgaGVscGVyIGZvci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgc2hvcnRjdXQgZnVuY3Rpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBTSEEyNTYgPSBDcnlwdG9KUy5saWIuSGFzaGVyLl9jcmVhdGVIZWxwZXIoQ3J5cHRvSlMuYWxnby5TSEEyNTYpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9jcmVhdGVIZWxwZXI6IGZ1bmN0aW9uIChoYXNoZXIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtZXNzYWdlLCBjZmcpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBuZXcgaGFzaGVyLmluaXQoY2ZnKS5maW5hbGl6ZShtZXNzYWdlKTtcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIHNob3J0Y3V0IGZ1bmN0aW9uIHRvIHRoZSBITUFDJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7SGFzaGVyfSBoYXNoZXIgVGhlIGhhc2hlciB0byB1c2UgaW4gdGhpcyBITUFDIGhlbHBlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgc2hvcnRjdXQgZnVuY3Rpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBIbWFjU0hBMjU2ID0gQ3J5cHRvSlMubGliLkhhc2hlci5fY3JlYXRlSG1hY0hlbHBlcihDcnlwdG9KUy5hbGdvLlNIQTI1Nik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgX2NyZWF0ZUhtYWNIZWxwZXI6IGZ1bmN0aW9uIChoYXNoZXIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtZXNzYWdlLCBrZXkpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ19hbGdvLkhNQUMuaW5pdChoYXNoZXIsIGtleSkuZmluYWxpemUobWVzc2FnZSk7XG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWxnb3JpdGhtIG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfYWxnbyA9IEMuYWxnbyA9IHt9O1xuXG5cdCAgICByZXR1cm4gQztcblx0fShNYXRoKSk7XG5cblxuXHRyZXR1cm4gQ3J5cHRvSlM7XG5cbn0pKTsiLCAiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuXHRpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBDb21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZShcIi4vY29yZVwiKSk7XG5cdH1cblx0ZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoW1wiLi9jb3JlXCJdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0ZmFjdG9yeShyb290LkNyeXB0b0pTKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoQ3J5cHRvSlMpIHtcblxuXHQoZnVuY3Rpb24gKE1hdGgpIHtcblx0ICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgdmFyIEMgPSBDcnlwdG9KUztcblx0ICAgIHZhciBDX2xpYiA9IEMubGliO1xuXHQgICAgdmFyIFdvcmRBcnJheSA9IENfbGliLldvcmRBcnJheTtcblx0ICAgIHZhciBIYXNoZXIgPSBDX2xpYi5IYXNoZXI7XG5cdCAgICB2YXIgQ19hbGdvID0gQy5hbGdvO1xuXG5cdCAgICAvLyBJbml0aWFsaXphdGlvbiBhbmQgcm91bmQgY29uc3RhbnRzIHRhYmxlc1xuXHQgICAgdmFyIEggPSBbXTtcblx0ICAgIHZhciBLID0gW107XG5cblx0ICAgIC8vIENvbXB1dGUgY29uc3RhbnRzXG5cdCAgICAoZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIGZ1bmN0aW9uIGlzUHJpbWUobikge1xuXHQgICAgICAgICAgICB2YXIgc3FydE4gPSBNYXRoLnNxcnQobik7XG5cdCAgICAgICAgICAgIGZvciAodmFyIGZhY3RvciA9IDI7IGZhY3RvciA8PSBzcXJ0TjsgZmFjdG9yKyspIHtcblx0ICAgICAgICAgICAgICAgIGlmICghKG4gJSBmYWN0b3IpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIHRydWU7XG5cdCAgICAgICAgfVxuXG5cdCAgICAgICAgZnVuY3Rpb24gZ2V0RnJhY3Rpb25hbEJpdHMobikge1xuXHQgICAgICAgICAgICByZXR1cm4gKChuIC0gKG4gfCAwKSkgKiAweDEwMDAwMDAwMCkgfCAwO1xuXHQgICAgICAgIH1cblxuXHQgICAgICAgIHZhciBuID0gMjtcblx0ICAgICAgICB2YXIgblByaW1lID0gMDtcblx0ICAgICAgICB3aGlsZSAoblByaW1lIDwgNjQpIHtcblx0ICAgICAgICAgICAgaWYgKGlzUHJpbWUobikpIHtcblx0ICAgICAgICAgICAgICAgIGlmIChuUHJpbWUgPCA4KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgSFtuUHJpbWVdID0gZ2V0RnJhY3Rpb25hbEJpdHMoTWF0aC5wb3cobiwgMSAvIDIpKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIEtbblByaW1lXSA9IGdldEZyYWN0aW9uYWxCaXRzKE1hdGgucG93KG4sIDEgLyAzKSk7XG5cblx0ICAgICAgICAgICAgICAgIG5QcmltZSsrO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgbisrO1xuXHQgICAgICAgIH1cblx0ICAgIH0oKSk7XG5cblx0ICAgIC8vIFJldXNhYmxlIG9iamVjdFxuXHQgICAgdmFyIFcgPSBbXTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTSEEtMjU2IGhhc2ggYWxnb3JpdGhtLlxuXHQgICAgICovXG5cdCAgICB2YXIgU0hBMjU2ID0gQ19hbGdvLlNIQTI1NiA9IEhhc2hlci5leHRlbmQoe1xuXHQgICAgICAgIF9kb1Jlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHRoaXMuX2hhc2ggPSBuZXcgV29yZEFycmF5LmluaXQoSC5zbGljZSgwKSk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb1Byb2Nlc3NCbG9jazogZnVuY3Rpb24gKE0sIG9mZnNldCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgSCA9IHRoaXMuX2hhc2gud29yZHM7XG5cblx0ICAgICAgICAgICAgLy8gV29ya2luZyB2YXJpYWJsZXNcblx0ICAgICAgICAgICAgdmFyIGEgPSBIWzBdO1xuXHQgICAgICAgICAgICB2YXIgYiA9IEhbMV07XG5cdCAgICAgICAgICAgIHZhciBjID0gSFsyXTtcblx0ICAgICAgICAgICAgdmFyIGQgPSBIWzNdO1xuXHQgICAgICAgICAgICB2YXIgZSA9IEhbNF07XG5cdCAgICAgICAgICAgIHZhciBmID0gSFs1XTtcblx0ICAgICAgICAgICAgdmFyIGcgPSBIWzZdO1xuXHQgICAgICAgICAgICB2YXIgaCA9IEhbN107XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0YXRpb25cblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA2NDsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICBpZiAoaSA8IDE2KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgV1tpXSA9IE1bb2Zmc2V0ICsgaV0gfCAwO1xuXHQgICAgICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgICAgICB2YXIgZ2FtbWEweCA9IFdbaSAtIDE1XTtcblx0ICAgICAgICAgICAgICAgICAgICB2YXIgZ2FtbWEwICA9ICgoZ2FtbWEweCA8PCAyNSkgfCAoZ2FtbWEweCA+Pj4gNykpICBeXG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKGdhbW1hMHggPDwgMTQpIHwgKGdhbW1hMHggPj4+IDE4KSkgXlxuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChnYW1tYTB4ID4+PiAzKTtcblxuXHQgICAgICAgICAgICAgICAgICAgIHZhciBnYW1tYTF4ID0gV1tpIC0gMl07XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIGdhbW1hMSAgPSAoKGdhbW1hMXggPDwgMTUpIHwgKGdhbW1hMXggPj4+IDE3KSkgXlxuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKChnYW1tYTF4IDw8IDEzKSB8IChnYW1tYTF4ID4+PiAxOSkpIF5cblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZ2FtbWExeCA+Pj4gMTApO1xuXG5cdCAgICAgICAgICAgICAgICAgICAgV1tpXSA9IGdhbW1hMCArIFdbaSAtIDddICsgZ2FtbWExICsgV1tpIC0gMTZdO1xuXHQgICAgICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgICAgICB2YXIgY2ggID0gKGUgJiBmKSBeICh+ZSAmIGcpO1xuXHQgICAgICAgICAgICAgICAgdmFyIG1haiA9IChhICYgYikgXiAoYSAmIGMpIF4gKGIgJiBjKTtcblxuXHQgICAgICAgICAgICAgICAgdmFyIHNpZ21hMCA9ICgoYSA8PCAzMCkgfCAoYSA+Pj4gMikpIF4gKChhIDw8IDE5KSB8IChhID4+PiAxMykpIF4gKChhIDw8IDEwKSB8IChhID4+PiAyMikpO1xuXHQgICAgICAgICAgICAgICAgdmFyIHNpZ21hMSA9ICgoZSA8PCAyNikgfCAoZSA+Pj4gNikpIF4gKChlIDw8IDIxKSB8IChlID4+PiAxMSkpIF4gKChlIDw8IDcpICB8IChlID4+PiAyNSkpO1xuXG5cdCAgICAgICAgICAgICAgICB2YXIgdDEgPSBoICsgc2lnbWExICsgY2ggKyBLW2ldICsgV1tpXTtcblx0ICAgICAgICAgICAgICAgIHZhciB0MiA9IHNpZ21hMCArIG1hajtcblxuXHQgICAgICAgICAgICAgICAgaCA9IGc7XG5cdCAgICAgICAgICAgICAgICBnID0gZjtcblx0ICAgICAgICAgICAgICAgIGYgPSBlO1xuXHQgICAgICAgICAgICAgICAgZSA9IChkICsgdDEpIHwgMDtcblx0ICAgICAgICAgICAgICAgIGQgPSBjO1xuXHQgICAgICAgICAgICAgICAgYyA9IGI7XG5cdCAgICAgICAgICAgICAgICBiID0gYTtcblx0ICAgICAgICAgICAgICAgIGEgPSAodDEgKyB0MikgfCAwO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gSW50ZXJtZWRpYXRlIGhhc2ggdmFsdWVcblx0ICAgICAgICAgICAgSFswXSA9IChIWzBdICsgYSkgfCAwO1xuXHQgICAgICAgICAgICBIWzFdID0gKEhbMV0gKyBiKSB8IDA7XG5cdCAgICAgICAgICAgIEhbMl0gPSAoSFsyXSArIGMpIHwgMDtcblx0ICAgICAgICAgICAgSFszXSA9IChIWzNdICsgZCkgfCAwO1xuXHQgICAgICAgICAgICBIWzRdID0gKEhbNF0gKyBlKSB8IDA7XG5cdCAgICAgICAgICAgIEhbNV0gPSAoSFs1XSArIGYpIHwgMDtcblx0ICAgICAgICAgICAgSFs2XSA9IChIWzZdICsgZykgfCAwO1xuXHQgICAgICAgICAgICBIWzddID0gKEhbN10gKyBoKSB8IDA7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb0ZpbmFsaXplOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cdCAgICAgICAgICAgIHZhciBkYXRhV29yZHMgPSBkYXRhLndvcmRzO1xuXG5cdCAgICAgICAgICAgIHZhciBuQml0c1RvdGFsID0gdGhpcy5fbkRhdGFCeXRlcyAqIDg7XG5cdCAgICAgICAgICAgIHZhciBuQml0c0xlZnQgPSBkYXRhLnNpZ0J5dGVzICogODtcblxuXHQgICAgICAgICAgICAvLyBBZGQgcGFkZGluZ1xuXHQgICAgICAgICAgICBkYXRhV29yZHNbbkJpdHNMZWZ0ID4+PiA1XSB8PSAweDgwIDw8ICgyNCAtIG5CaXRzTGVmdCAlIDMyKTtcblx0ICAgICAgICAgICAgZGF0YVdvcmRzWygoKG5CaXRzTGVmdCArIDY0KSA+Pj4gOSkgPDwgNCkgKyAxNF0gPSBNYXRoLmZsb29yKG5CaXRzVG90YWwgLyAweDEwMDAwMDAwMCk7XG5cdCAgICAgICAgICAgIGRhdGFXb3Jkc1soKChuQml0c0xlZnQgKyA2NCkgPj4+IDkpIDw8IDQpICsgMTVdID0gbkJpdHNUb3RhbDtcblx0ICAgICAgICAgICAgZGF0YS5zaWdCeXRlcyA9IGRhdGFXb3Jkcy5sZW5ndGggKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIEhhc2ggZmluYWwgYmxvY2tzXG5cdCAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3MoKTtcblxuXHQgICAgICAgICAgICAvLyBSZXR1cm4gZmluYWwgY29tcHV0ZWQgaGFzaFxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5faGFzaDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgdmFyIGNsb25lID0gSGFzaGVyLmNsb25lLmNhbGwodGhpcyk7XG5cdCAgICAgICAgICAgIGNsb25lLl9oYXNoID0gdGhpcy5faGFzaC5jbG9uZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbiB0byB0aGUgaGFzaGVyJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gaGFzaC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBoYXNoLlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIgaGFzaCA9IENyeXB0b0pTLlNIQTI1NignbWVzc2FnZScpO1xuXHQgICAgICogICAgIHZhciBoYXNoID0gQ3J5cHRvSlMuU0hBMjU2KHdvcmRBcnJheSk7XG5cdCAgICAgKi9cblx0ICAgIEMuU0hBMjU2ID0gSGFzaGVyLl9jcmVhdGVIZWxwZXIoU0hBMjU2KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbiB0byB0aGUgSE1BQydzIG9iamVjdCBpbnRlcmZhY2UuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRvIGhhc2guXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IGtleSBUaGUgc2VjcmV0IGtleS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBITUFDLlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIgaG1hYyA9IENyeXB0b0pTLkhtYWNTSEEyNTYobWVzc2FnZSwga2V5KTtcblx0ICAgICAqL1xuXHQgICAgQy5IbWFjU0hBMjU2ID0gSGFzaGVyLl9jcmVhdGVIbWFjSGVscGVyKFNIQTI1Nik7XG5cdH0oTWF0aCkpO1xuXG5cblx0cmV0dXJuIENyeXB0b0pTLlNIQTI1NjtcblxufSkpOyIsICJpbXBvcnQgeyBQbHVnaW4sIFdvcmtzcGFjZUxlYWYgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IEFwcFZpZXcsIEFQUF9WSUVXX05BTUUgfSBmcm9tIFwiLi91aS9lbnRyeVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNlIGV4dGVuZHMgUGx1Z2luIHtcblx0YXN5bmMgb25sb2FkKCkge1xuXHRcdHRoaXMucmVnaXN0ZXJWaWV3KEFQUF9WSUVXX05BTUUsIChsZWFmKSA9PiBuZXcgQXBwVmlldyhsZWFmKSk7XG5cdFx0dGhpcy5hZGRSaWJib25JY29uKFwia2FuYmFuLXNxdWFyZVwiLCBcIk9wZW4gS2FuYmFuXCIsICgpID0+XG5cdFx0XHR0aGlzLmFjdGl2YXRlVmlldygpXG5cdFx0KTtcblx0fVxuXG5cdG9udW5sb2FkKCkge31cblxuXHRhc3luYyBhY3RpdmF0ZVZpZXcoKSB7XG5cdFx0Y29uc3QgeyB3b3Jrc3BhY2UgfSA9IHRoaXMuYXBwO1xuXG5cdFx0bGV0IGxlYWY6IFdvcmtzcGFjZUxlYWYgfCB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgbGVhdmVzID0gd29ya3NwYWNlLmdldExlYXZlc09mVHlwZShBUFBfVklFV19OQU1FKTtcblxuXHRcdGlmIChsZWF2ZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0Ly8gQSBsZWFmIHdpdGggb3VyIHZpZXcgYWxyZWFkeSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0XHRsZWFmID0gbGVhdmVzWzBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBPdXIgdmlldyBjb3VsZCBub3QgYmUgZm91bmQgaW4gdGhlIHdvcmtzcGFjZSwgY3JlYXRlIGEgbmV3IGxlYWZcblx0XHRcdC8vIGluIHRoZSByaWdodCBzaWRlYmFyIGZvciBpdFxuXHRcdFx0bGVhZiA9IHdvcmtzcGFjZS5nZXRMZWFmKFwidGFiXCIpO1xuXHRcdFx0YXdhaXQgbGVhZi5zZXRWaWV3U3RhdGUoeyB0eXBlOiBBUFBfVklFV19OQU1FLCBhY3RpdmU6IHRydWUgfSk7XG5cdFx0fVxuXG5cdFx0Ly8gXCJSZXZlYWxcIiB0aGUgbGVhZiBpbiBjYXNlIGl0IGlzIGluIGEgY29sbGFwc2VkIHNpZGViYXJcblx0XHRsZWFmICYmIHdvcmtzcGFjZS5yZXZlYWxMZWFmKGxlYWYpO1xuXHR9XG59XG4iLCAiaW1wb3J0IHsgSXRlbVZpZXcgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuaW1wb3J0IE1haW4gZnJvbSBcIi4vbWFpbi5zdmVsdGVcIjtcblxuZXhwb3J0IGNvbnN0IEFQUF9WSUVXX05BTUUgPSBcInByb2plY3QtcGxhblwiO1xuXG5leHBvcnQgY2xhc3MgQXBwVmlldyBleHRlbmRzIEl0ZW1WaWV3IHtcblx0Y29tcG9uZW50OiBNYWluIHwgdW5kZWZpbmVkO1xuXHRpY29uID0gXCJrYW5iYW4tc3F1YXJlXCI7XG5cblx0Z2V0Vmlld1R5cGUoKSB7XG5cdFx0dGhpcy5sZWFmLm9wZW5GaWxlO1xuXHRcdHJldHVybiBBUFBfVklFV19OQU1FO1xuXHR9XG5cblx0Z2V0RGlzcGxheVRleHQoKSB7XG5cdFx0cmV0dXJuIFwiUHJvamVjdCBQbGFubmVyXCI7XG5cdH1cblxuXHRhc3luYyBvbk9wZW4oKSB7XG5cdFx0dGhpcy5jb21wb25lbnQgPSBuZXcgTWFpbih7XG5cdFx0XHR0YXJnZXQ6IHRoaXMuY29udGVudEVsLFxuXHRcdFx0cHJvcHM6IHtcblx0XHRcdFx0d29ya3NwYWNlOiB0aGlzLmFwcC53b3Jrc3BhY2UsXG5cdFx0XHRcdHZhdWx0OiB0aGlzLmFwcC52YXVsdCxcblx0XHRcdFx0cmVnaXN0ZXJFdmVudDogdGhpcy5yZWdpc3RlckV2ZW50LmJpbmQodGhpcyksXG5cdFx0XHR9LFxuXHRcdH0pO1xuXHR9XG5cblx0YXN5bmMgb25DbG9zZSgpIHtcblx0XHR0aGlzLmNvbXBvbmVudD8uJGRlc3Ryb3koKTtcblx0fVxufVxuIiwgIi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBub29wKCkge31cblxuZXhwb3J0IGNvbnN0IGlkZW50aXR5ID0gKHgpID0+IHg7XG5cbi8qKlxuICogQHRlbXBsYXRlIFRcbiAqIEB0ZW1wbGF0ZSBTXG4gKiBAcGFyYW0ge1R9IHRhclxuICogQHBhcmFtIHtTfSBzcmNcbiAqIEByZXR1cm5zIHtUICYgU31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2lnbih0YXIsIHNyYykge1xuXHQvLyBAdHMtaWdub3JlXG5cdGZvciAoY29uc3QgayBpbiBzcmMpIHRhcltrXSA9IHNyY1trXTtcblx0cmV0dXJuIC8qKiBAdHlwZSB7VCAmIFN9ICovICh0YXIpO1xufVxuXG4vLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL3RoZW4vaXMtcHJvbWlzZS9ibG9iL21hc3Rlci9pbmRleC5qc1xuLy8gRGlzdHJpYnV0ZWQgdW5kZXIgTUlUIExpY2Vuc2UgaHR0cHM6Ly9naXRodWIuY29tL3RoZW4vaXMtcHJvbWlzZS9ibG9iL21hc3Rlci9MSUNFTlNFXG4vKipcbiAqIEBwYXJhbSB7YW55fSB2YWx1ZVxuICogQHJldHVybnMge3ZhbHVlIGlzIFByb21pc2VMaWtlPGFueT59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc19wcm9taXNlKHZhbHVlKSB7XG5cdHJldHVybiAoXG5cdFx0ISF2YWx1ZSAmJlxuXHRcdCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykgJiZcblx0XHR0eXBlb2YgKC8qKiBAdHlwZSB7YW55fSAqLyAodmFsdWUpLnRoZW4pID09PSAnZnVuY3Rpb24nXG5cdCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfbG9jYXRpb24oZWxlbWVudCwgZmlsZSwgbGluZSwgY29sdW1uLCBjaGFyKSB7XG5cdGVsZW1lbnQuX19zdmVsdGVfbWV0YSA9IHtcblx0XHRsb2M6IHsgZmlsZSwgbGluZSwgY29sdW1uLCBjaGFyIH1cblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1bihmbikge1xuXHRyZXR1cm4gZm4oKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJsYW5rX29iamVjdCgpIHtcblx0cmV0dXJuIE9iamVjdC5jcmVhdGUobnVsbCk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtGdW5jdGlvbltdfSBmbnNcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuX2FsbChmbnMpIHtcblx0Zm5zLmZvckVhY2gocnVuKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge2FueX0gdGhpbmdcbiAqIEByZXR1cm5zIHt0aGluZyBpcyBGdW5jdGlvbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHRoaW5nKSB7XG5cdHJldHVybiB0eXBlb2YgdGhpbmcgPT09ICdmdW5jdGlvbic7XG59XG5cbi8qKiBAcmV0dXJucyB7Ym9vbGVhbn0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYWZlX25vdF9lcXVhbChhLCBiKSB7XG5cdHJldHVybiBhICE9IGEgPyBiID09IGIgOiBhICE9PSBiIHx8IChhICYmIHR5cGVvZiBhID09PSAnb2JqZWN0JykgfHwgdHlwZW9mIGEgPT09ICdmdW5jdGlvbic7XG59XG5cbmxldCBzcmNfdXJsX2VxdWFsX2FuY2hvcjtcblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gZWxlbWVudF9zcmNcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmxcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3JjX3VybF9lcXVhbChlbGVtZW50X3NyYywgdXJsKSB7XG5cdGlmIChlbGVtZW50X3NyYyA9PT0gdXJsKSByZXR1cm4gdHJ1ZTtcblx0aWYgKCFzcmNfdXJsX2VxdWFsX2FuY2hvcikge1xuXHRcdHNyY191cmxfZXF1YWxfYW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXHR9XG5cdC8vIFRoaXMgaXMgYWN0dWFsbHkgZmFzdGVyIHRoYW4gZG9pbmcgVVJMKC4uKS5ocmVmXG5cdHNyY191cmxfZXF1YWxfYW5jaG9yLmhyZWYgPSB1cmw7XG5cdHJldHVybiBlbGVtZW50X3NyYyA9PT0gc3JjX3VybF9lcXVhbF9hbmNob3IuaHJlZjtcbn1cblxuLyoqIEBwYXJhbSB7c3RyaW5nfSBzcmNzZXQgKi9cbmZ1bmN0aW9uIHNwbGl0X3NyY3NldChzcmNzZXQpIHtcblx0cmV0dXJuIHNyY3NldC5zcGxpdCgnLCcpLm1hcCgoc3JjKSA9PiBzcmMudHJpbSgpLnNwbGl0KCcgJykuZmlsdGVyKEJvb2xlYW4pKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxTb3VyY2VFbGVtZW50IHwgSFRNTEltYWdlRWxlbWVudH0gZWxlbWVudF9zcmNzZXRcbiAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbH0gc3Jjc2V0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNyY3NldF91cmxfZXF1YWwoZWxlbWVudF9zcmNzZXQsIHNyY3NldCkge1xuXHRjb25zdCBlbGVtZW50X3VybHMgPSBzcGxpdF9zcmNzZXQoZWxlbWVudF9zcmNzZXQuc3Jjc2V0KTtcblx0Y29uc3QgdXJscyA9IHNwbGl0X3NyY3NldChzcmNzZXQgfHwgJycpO1xuXG5cdHJldHVybiAoXG5cdFx0dXJscy5sZW5ndGggPT09IGVsZW1lbnRfdXJscy5sZW5ndGggJiZcblx0XHR1cmxzLmV2ZXJ5KFxuXHRcdFx0KFt1cmwsIHdpZHRoXSwgaSkgPT5cblx0XHRcdFx0d2lkdGggPT09IGVsZW1lbnRfdXJsc1tpXVsxXSAmJlxuXHRcdFx0XHQvLyBXZSBuZWVkIHRvIHRlc3QgYm90aCB3YXlzIGJlY2F1c2UgVml0ZSB3aWxsIGNyZWF0ZSBhbiBhIGZ1bGwgVVJMIHdpdGhcblx0XHRcdFx0Ly8gYG5ldyBVUkwoYXNzZXQsIGltcG9ydC5tZXRhLnVybCkuaHJlZmAgZm9yIHRoZSBjbGllbnQgd2hlbiBgYmFzZTogJy4vJ2AsIGFuZCB0aGVcblx0XHRcdFx0Ly8gcmVsYXRpdmUgVVJMcyBpbnNpZGUgc3Jjc2V0IGFyZSBub3QgYXV0b21hdGljYWxseSByZXNvbHZlZCB0byBhYnNvbHV0ZSBVUkxzIGJ5XG5cdFx0XHRcdC8vIGJyb3dzZXJzIChpbiBjb250cmFzdCB0byBpbWcuc3JjKS4gVGhpcyBtZWFucyBib3RoIFNTUiBhbmQgRE9NIGNvZGUgY291bGRcblx0XHRcdFx0Ly8gY29udGFpbiByZWxhdGl2ZSBvciBhYnNvbHV0ZSBVUkxzLlxuXHRcdFx0XHQoc3JjX3VybF9lcXVhbChlbGVtZW50X3VybHNbaV1bMF0sIHVybCkgfHwgc3JjX3VybF9lcXVhbCh1cmwsIGVsZW1lbnRfdXJsc1tpXVswXSkpXG5cdFx0KVxuXHQpO1xufVxuXG4vKiogQHJldHVybnMge2Jvb2xlYW59ICovXG5leHBvcnQgZnVuY3Rpb24gbm90X2VxdWFsKGEsIGIpIHtcblx0cmV0dXJuIGEgIT0gYSA/IGIgPT0gYiA6IGEgIT09IGI7XG59XG5cbi8qKiBAcmV0dXJucyB7Ym9vbGVhbn0gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc19lbXB0eShvYmopIHtcblx0cmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoID09PSAwO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVfc3RvcmUoc3RvcmUsIG5hbWUpIHtcblx0aWYgKHN0b3JlICE9IG51bGwgJiYgdHlwZW9mIHN0b3JlLnN1YnNjcmliZSAhPT0gJ2Z1bmN0aW9uJykge1xuXHRcdHRocm93IG5ldyBFcnJvcihgJyR7bmFtZX0nIGlzIG5vdCBhIHN0b3JlIHdpdGggYSAnc3Vic2NyaWJlJyBtZXRob2RgKTtcblx0fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3Vic2NyaWJlKHN0b3JlLCAuLi5jYWxsYmFja3MpIHtcblx0aWYgKHN0b3JlID09IG51bGwpIHtcblx0XHRmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIGNhbGxiYWNrcykge1xuXHRcdFx0Y2FsbGJhY2sodW5kZWZpbmVkKTtcblx0XHR9XG5cdFx0cmV0dXJuIG5vb3A7XG5cdH1cblx0Y29uc3QgdW5zdWIgPSBzdG9yZS5zdWJzY3JpYmUoLi4uY2FsbGJhY2tzKTtcblx0cmV0dXJuIHVuc3ViLnVuc3Vic2NyaWJlID8gKCkgPT4gdW5zdWIudW5zdWJzY3JpYmUoKSA6IHVuc3ViO1xufVxuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudCB2YWx1ZSBmcm9tIGEgc3RvcmUgYnkgc3Vic2NyaWJpbmcgYW5kIGltbWVkaWF0ZWx5IHVuc3Vic2NyaWJpbmcuXG4gKlxuICogaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3Mvc3ZlbHRlLXN0b3JlI2dldFxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuLi9zdG9yZS9wdWJsaWMuanMnKS5SZWFkYWJsZTxUPn0gc3RvcmVcbiAqIEByZXR1cm5zIHtUfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X3N0b3JlX3ZhbHVlKHN0b3JlKSB7XG5cdGxldCB2YWx1ZTtcblx0c3Vic2NyaWJlKHN0b3JlLCAoXykgPT4gKHZhbHVlID0gXykpKCk7XG5cdHJldHVybiB2YWx1ZTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvbmVudF9zdWJzY3JpYmUoY29tcG9uZW50LCBzdG9yZSwgY2FsbGJhY2spIHtcblx0Y29tcG9uZW50LiQkLm9uX2Rlc3Ryb3kucHVzaChzdWJzY3JpYmUoc3RvcmUsIGNhbGxiYWNrKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfc2xvdChkZWZpbml0aW9uLCBjdHgsICQkc2NvcGUsIGZuKSB7XG5cdGlmIChkZWZpbml0aW9uKSB7XG5cdFx0Y29uc3Qgc2xvdF9jdHggPSBnZXRfc2xvdF9jb250ZXh0KGRlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZm4pO1xuXHRcdHJldHVybiBkZWZpbml0aW9uWzBdKHNsb3RfY3R4KTtcblx0fVxufVxuXG5mdW5jdGlvbiBnZXRfc2xvdF9jb250ZXh0KGRlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZm4pIHtcblx0cmV0dXJuIGRlZmluaXRpb25bMV0gJiYgZm4gPyBhc3NpZ24oJCRzY29wZS5jdHguc2xpY2UoKSwgZGVmaW5pdGlvblsxXShmbihjdHgpKSkgOiAkJHNjb3BlLmN0eDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldF9zbG90X2NoYW5nZXMoZGVmaW5pdGlvbiwgJCRzY29wZSwgZGlydHksIGZuKSB7XG5cdGlmIChkZWZpbml0aW9uWzJdICYmIGZuKSB7XG5cdFx0Y29uc3QgbGV0cyA9IGRlZmluaXRpb25bMl0oZm4oZGlydHkpKTtcblx0XHRpZiAoJCRzY29wZS5kaXJ0eSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gbGV0cztcblx0XHR9XG5cdFx0aWYgKHR5cGVvZiBsZXRzID09PSAnb2JqZWN0Jykge1xuXHRcdFx0Y29uc3QgbWVyZ2VkID0gW107XG5cdFx0XHRjb25zdCBsZW4gPSBNYXRoLm1heCgkJHNjb3BlLmRpcnR5Lmxlbmd0aCwgbGV0cy5sZW5ndGgpO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gMSkge1xuXHRcdFx0XHRtZXJnZWRbaV0gPSAkJHNjb3BlLmRpcnR5W2ldIHwgbGV0c1tpXTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtZXJnZWQ7XG5cdFx0fVxuXHRcdHJldHVybiAkJHNjb3BlLmRpcnR5IHwgbGV0cztcblx0fVxuXHRyZXR1cm4gJCRzY29wZS5kaXJ0eTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZV9zbG90X2Jhc2UoXG5cdHNsb3QsXG5cdHNsb3RfZGVmaW5pdGlvbixcblx0Y3R4LFxuXHQkJHNjb3BlLFxuXHRzbG90X2NoYW5nZXMsXG5cdGdldF9zbG90X2NvbnRleHRfZm5cbikge1xuXHRpZiAoc2xvdF9jaGFuZ2VzKSB7XG5cdFx0Y29uc3Qgc2xvdF9jb250ZXh0ID0gZ2V0X3Nsb3RfY29udGV4dChzbG90X2RlZmluaXRpb24sIGN0eCwgJCRzY29wZSwgZ2V0X3Nsb3RfY29udGV4dF9mbik7XG5cdFx0c2xvdC5wKHNsb3RfY29udGV4dCwgc2xvdF9jaGFuZ2VzKTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlX3Nsb3QoXG5cdHNsb3QsXG5cdHNsb3RfZGVmaW5pdGlvbixcblx0Y3R4LFxuXHQkJHNjb3BlLFxuXHRkaXJ0eSxcblx0Z2V0X3Nsb3RfY2hhbmdlc19mbixcblx0Z2V0X3Nsb3RfY29udGV4dF9mblxuKSB7XG5cdGNvbnN0IHNsb3RfY2hhbmdlcyA9IGdldF9zbG90X2NoYW5nZXMoc2xvdF9kZWZpbml0aW9uLCAkJHNjb3BlLCBkaXJ0eSwgZ2V0X3Nsb3RfY2hhbmdlc19mbik7XG5cdHVwZGF0ZV9zbG90X2Jhc2Uoc2xvdCwgc2xvdF9kZWZpbml0aW9uLCBjdHgsICQkc2NvcGUsIHNsb3RfY2hhbmdlcywgZ2V0X3Nsb3RfY29udGV4dF9mbik7XG59XG5cbi8qKiBAcmV0dXJucyB7YW55W10gfCAtMX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRfYWxsX2RpcnR5X2Zyb21fc2NvcGUoJCRzY29wZSkge1xuXHRpZiAoJCRzY29wZS5jdHgubGVuZ3RoID4gMzIpIHtcblx0XHRjb25zdCBkaXJ0eSA9IFtdO1xuXHRcdGNvbnN0IGxlbmd0aCA9ICQkc2NvcGUuY3R4Lmxlbmd0aCAvIDMyO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcblx0XHRcdGRpcnR5W2ldID0gLTE7XG5cdFx0fVxuXHRcdHJldHVybiBkaXJ0eTtcblx0fVxuXHRyZXR1cm4gLTE7XG59XG5cbi8qKiBAcmV0dXJucyB7e319ICovXG5leHBvcnQgZnVuY3Rpb24gZXhjbHVkZV9pbnRlcm5hbF9wcm9wcyhwcm9wcykge1xuXHRjb25zdCByZXN1bHQgPSB7fTtcblx0Zm9yIChjb25zdCBrIGluIHByb3BzKSBpZiAoa1swXSAhPT0gJyQnKSByZXN1bHRba10gPSBwcm9wc1trXTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqIEByZXR1cm5zIHt7fX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlX3Jlc3RfcHJvcHMocHJvcHMsIGtleXMpIHtcblx0Y29uc3QgcmVzdCA9IHt9O1xuXHRrZXlzID0gbmV3IFNldChrZXlzKTtcblx0Zm9yIChjb25zdCBrIGluIHByb3BzKSBpZiAoIWtleXMuaGFzKGspICYmIGtbMF0gIT09ICckJykgcmVzdFtrXSA9IHByb3BzW2tdO1xuXHRyZXR1cm4gcmVzdDtcbn1cblxuLyoqIEByZXR1cm5zIHt7fX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlX3Nsb3RzKHNsb3RzKSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRmb3IgKGNvbnN0IGtleSBpbiBzbG90cykge1xuXHRcdHJlc3VsdFtrZXldID0gdHJ1ZTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogQHJldHVybnMgeyh0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uY2UoZm4pIHtcblx0bGV0IHJhbiA9IGZhbHNlO1xuXHRyZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0XHRpZiAocmFuKSByZXR1cm47XG5cdFx0cmFuID0gdHJ1ZTtcblx0XHRmbi5jYWxsKHRoaXMsIC4uLmFyZ3MpO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbnVsbF90b19lbXB0eSh2YWx1ZSkge1xuXHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/ICcnIDogdmFsdWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRfc3RvcmVfdmFsdWUoc3RvcmUsIHJldCwgdmFsdWUpIHtcblx0c3RvcmUuc2V0KHZhbHVlKTtcblx0cmV0dXJuIHJldDtcbn1cblxuZXhwb3J0IGNvbnN0IGhhc19wcm9wID0gKG9iaiwgcHJvcCkgPT4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBhY3Rpb25fZGVzdHJveWVyKGFjdGlvbl9yZXN1bHQpIHtcblx0cmV0dXJuIGFjdGlvbl9yZXN1bHQgJiYgaXNfZnVuY3Rpb24oYWN0aW9uX3Jlc3VsdC5kZXN0cm95KSA/IGFjdGlvbl9yZXN1bHQuZGVzdHJveSA6IG5vb3A7XG59XG5cbi8qKiBAcGFyYW0ge251bWJlciB8IHN0cmluZ30gdmFsdWVcbiAqIEByZXR1cm5zIHtbbnVtYmVyLCBzdHJpbmddfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRfY3NzX3VuaXQodmFsdWUpIHtcblx0Y29uc3Qgc3BsaXQgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLm1hdGNoKC9eXFxzKigtP1tcXGQuXSspKFteXFxzXSopXFxzKiQvKTtcblx0cmV0dXJuIHNwbGl0ID8gW3BhcnNlRmxvYXQoc3BsaXRbMV0pLCBzcGxpdFsyXSB8fCAncHgnXSA6IFsvKiogQHR5cGUge251bWJlcn0gKi8gKHZhbHVlKSwgJ3B4J107XG59XG5cbmV4cG9ydCBjb25zdCBjb250ZW50ZWRpdGFibGVfdHJ1dGh5X3ZhbHVlcyA9IFsnJywgdHJ1ZSwgMSwgJ3RydWUnLCAnY29udGVudGVkaXRhYmxlJ107XG4iLCAiLyoqIEB0eXBlIHt0eXBlb2YgZ2xvYmFsVGhpc30gKi9cbmV4cG9ydCBjb25zdCBnbG9iYWxzID1cblx0dHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcblx0XHQ/IHdpbmRvd1xuXHRcdDogdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnXG5cdFx0PyBnbG9iYWxUaGlzXG5cdFx0OiAvLyBAdHMtaWdub3JlIE5vZGUgdHlwaW5ncyBoYXZlIHRoaXNcblx0XHQgIGdsb2JhbDtcbiIsICJpbXBvcnQgeyBnbG9iYWxzIH0gZnJvbSAnLi9nbG9iYWxzLmpzJztcblxuLyoqXG4gKiBSZXNpemUgb2JzZXJ2ZXIgc2luZ2xldG9uLlxuICogT25lIGxpc3RlbmVyIHBlciBlbGVtZW50IG9ubHkhXG4gKiBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2EvY2hyb21pdW0ub3JnL2cvYmxpbmstZGV2L2MvejZpZW5PTlViNUEvbS9GNS1WY1VadEJBQUpcbiAqL1xuZXhwb3J0IGNsYXNzIFJlc2l6ZU9ic2VydmVyU2luZ2xldG9uIHtcblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEByZWFkb25seVxuXHQgKiBAdHlwZSB7V2Vha01hcDxFbGVtZW50LCBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkxpc3RlbmVyPn1cblx0ICovXG5cdF9saXN0ZW5lcnMgPSAnV2Vha01hcCcgaW4gZ2xvYmFscyA/IG5ldyBXZWFrTWFwKCkgOiB1bmRlZmluZWQ7XG5cblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEB0eXBlIHtSZXNpemVPYnNlcnZlcn1cblx0ICovXG5cdF9vYnNlcnZlciA9IHVuZGVmaW5lZDtcblxuXHQvKiogQHR5cGUge1Jlc2l6ZU9ic2VydmVyT3B0aW9uc30gKi9cblx0b3B0aW9ucztcblxuXHQvKiogQHBhcmFtIHtSZXNpemVPYnNlcnZlck9wdGlvbnN9IG9wdGlvbnMgKi9cblx0Y29uc3RydWN0b3Iob3B0aW9ucykge1xuXHRcdHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG5cdCAqIEBwYXJhbSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5MaXN0ZW5lcn0gbGlzdGVuZXJcblx0ICogQHJldHVybnMgeygpID0+IHZvaWR9XG5cdCAqL1xuXHRvYnNlcnZlKGVsZW1lbnQsIGxpc3RlbmVyKSB7XG5cdFx0dGhpcy5fbGlzdGVuZXJzLnNldChlbGVtZW50LCBsaXN0ZW5lcik7XG5cdFx0dGhpcy5fZ2V0T2JzZXJ2ZXIoKS5vYnNlcnZlKGVsZW1lbnQsIHRoaXMub3B0aW9ucyk7XG5cdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdHRoaXMuX2xpc3RlbmVycy5kZWxldGUoZWxlbWVudCk7XG5cdFx0XHR0aGlzLl9vYnNlcnZlci51bm9ic2VydmUoZWxlbWVudCk7IC8vIHRoaXMgbGluZSBjYW4gcHJvYmFibHkgYmUgcmVtb3ZlZFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogQHByaXZhdGVcblx0ICovXG5cdF9nZXRPYnNlcnZlcigpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0dGhpcy5fb2JzZXJ2ZXIgPz9cblx0XHRcdCh0aGlzLl9vYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoZW50cmllcykgPT4ge1xuXHRcdFx0XHRmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcblx0XHRcdFx0XHRSZXNpemVPYnNlcnZlclNpbmdsZXRvbi5lbnRyaWVzLnNldChlbnRyeS50YXJnZXQsIGVudHJ5KTtcblx0XHRcdFx0XHR0aGlzLl9saXN0ZW5lcnMuZ2V0KGVudHJ5LnRhcmdldCk/LihlbnRyeSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pKVxuXHRcdCk7XG5cdH1cbn1cblxuLy8gTmVlZHMgdG8gYmUgd3JpdHRlbiBsaWtlIHRoaXMgdG8gcGFzcyB0aGUgdHJlZS1zaGFrZS10ZXN0XG5SZXNpemVPYnNlcnZlclNpbmdsZXRvbi5lbnRyaWVzID0gJ1dlYWtNYXAnIGluIGdsb2JhbHMgPyBuZXcgV2Vha01hcCgpIDogdW5kZWZpbmVkO1xuIiwgImltcG9ydCB7IGNvbnRlbnRlZGl0YWJsZV90cnV0aHlfdmFsdWVzLCBoYXNfcHJvcCB9IGZyb20gJy4vdXRpbHMuanMnO1xuXG5pbXBvcnQgeyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbiB9IGZyb20gJy4vUmVzaXplT2JzZXJ2ZXJTaW5nbGV0b24uanMnO1xuXG4vLyBUcmFjayB3aGljaCBub2RlcyBhcmUgY2xhaW1lZCBkdXJpbmcgaHlkcmF0aW9uLiBVbmNsYWltZWQgbm9kZXMgY2FuIHRoZW4gYmUgcmVtb3ZlZCBmcm9tIHRoZSBET01cbi8vIGF0IHRoZSBlbmQgb2YgaHlkcmF0aW9uIHdpdGhvdXQgdG91Y2hpbmcgdGhlIHJlbWFpbmluZyBub2Rlcy5cbmxldCBpc19oeWRyYXRpbmcgPSBmYWxzZTtcblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0X2h5ZHJhdGluZygpIHtcblx0aXNfaHlkcmF0aW5nID0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuZF9oeWRyYXRpbmcoKSB7XG5cdGlzX2h5ZHJhdGluZyA9IGZhbHNlO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoXG4gKiBAcGFyYW0geyhpbmRleDogbnVtYmVyKSA9PiBudW1iZXJ9IGtleVxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiB1cHBlcl9ib3VuZChsb3csIGhpZ2gsIGtleSwgdmFsdWUpIHtcblx0Ly8gUmV0dXJuIGZpcnN0IGluZGV4IG9mIHZhbHVlIGxhcmdlciB0aGFuIGlucHV0IHZhbHVlIGluIHRoZSByYW5nZSBbbG93LCBoaWdoKVxuXHR3aGlsZSAobG93IDwgaGlnaCkge1xuXHRcdGNvbnN0IG1pZCA9IGxvdyArICgoaGlnaCAtIGxvdykgPj4gMSk7XG5cdFx0aWYgKGtleShtaWQpIDw9IHZhbHVlKSB7XG5cdFx0XHRsb3cgPSBtaWQgKyAxO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRoaWdoID0gbWlkO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbG93O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZUV4fSB0YXJnZXRcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBpbml0X2h5ZHJhdGUodGFyZ2V0KSB7XG5cdGlmICh0YXJnZXQuaHlkcmF0ZV9pbml0KSByZXR1cm47XG5cdHRhcmdldC5oeWRyYXRlX2luaXQgPSB0cnVlO1xuXHQvLyBXZSBrbm93IHRoYXQgYWxsIGNoaWxkcmVuIGhhdmUgY2xhaW1fb3JkZXIgdmFsdWVzIHNpbmNlIHRoZSB1bmNsYWltZWQgaGF2ZSBiZWVuIGRldGFjaGVkIGlmIHRhcmdldCBpcyBub3QgPGhlYWQ+XG5cblx0bGV0IGNoaWxkcmVuID0gLyoqIEB0eXBlIHtBcnJheUxpa2U8Tm9kZUV4Mj59ICovICh0YXJnZXQuY2hpbGROb2Rlcyk7XG5cdC8vIElmIHRhcmdldCBpcyA8aGVhZD4sIHRoZXJlIG1heSBiZSBjaGlsZHJlbiB3aXRob3V0IGNsYWltX29yZGVyXG5cdGlmICh0YXJnZXQubm9kZU5hbWUgPT09ICdIRUFEJykge1xuXHRcdGNvbnN0IG15X2NoaWxkcmVuID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3Qgbm9kZSA9IGNoaWxkcmVuW2ldO1xuXHRcdFx0aWYgKG5vZGUuY2xhaW1fb3JkZXIgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRteV9jaGlsZHJlbi5wdXNoKG5vZGUpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjaGlsZHJlbiA9IG15X2NoaWxkcmVuO1xuXHR9XG5cdC8qXG5cdCAqIFJlb3JkZXIgY2xhaW1lZCBjaGlsZHJlbiBvcHRpbWFsbHkuXG5cdCAqIFdlIGNhbiByZW9yZGVyIGNsYWltZWQgY2hpbGRyZW4gb3B0aW1hbGx5IGJ5IGZpbmRpbmcgdGhlIGxvbmdlc3Qgc3Vic2VxdWVuY2Ugb2Zcblx0ICogbm9kZXMgdGhhdCBhcmUgYWxyZWFkeSBjbGFpbWVkIGluIG9yZGVyIGFuZCBvbmx5IG1vdmluZyB0aGUgcmVzdC4gVGhlIGxvbmdlc3Rcblx0ICogc3Vic2VxdWVuY2Ugb2Ygbm9kZXMgdGhhdCBhcmUgY2xhaW1lZCBpbiBvcmRlciBjYW4gYmUgZm91bmQgYnlcblx0ICogY29tcHV0aW5nIHRoZSBsb25nZXN0IGluY3JlYXNpbmcgc3Vic2VxdWVuY2Ugb2YgLmNsYWltX29yZGVyIHZhbHVlcy5cblx0ICpcblx0ICogVGhpcyBhbGdvcml0aG0gaXMgb3B0aW1hbCBpbiBnZW5lcmF0aW5nIHRoZSBsZWFzdCBhbW91bnQgb2YgcmVvcmRlciBvcGVyYXRpb25zXG5cdCAqIHBvc3NpYmxlLlxuXHQgKlxuXHQgKiBQcm9vZjpcblx0ICogV2Uga25vdyB0aGF0LCBnaXZlbiBhIHNldCBvZiByZW9yZGVyaW5nIG9wZXJhdGlvbnMsIHRoZSBub2RlcyB0aGF0IGRvIG5vdCBtb3ZlXG5cdCAqIGFsd2F5cyBmb3JtIGFuIGluY3JlYXNpbmcgc3Vic2VxdWVuY2UsIHNpbmNlIHRoZXkgZG8gbm90IG1vdmUgYW1vbmcgZWFjaCBvdGhlclxuXHQgKiBtZWFuaW5nIHRoYXQgdGhleSBtdXN0IGJlIGFscmVhZHkgb3JkZXJlZCBhbW9uZyBlYWNoIG90aGVyLiBUaHVzLCB0aGUgbWF4aW1hbFxuXHQgKiBzZXQgb2Ygbm9kZXMgdGhhdCBkbyBub3QgbW92ZSBmb3JtIGEgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlLlxuXHQgKi9cblx0Ly8gQ29tcHV0ZSBsb25nZXN0IGluY3JlYXNpbmcgc3Vic2VxdWVuY2Vcblx0Ly8gbTogc3Vic2VxdWVuY2UgbGVuZ3RoIGogPT4gaW5kZXggayBvZiBzbWFsbGVzdCB2YWx1ZSB0aGF0IGVuZHMgYW4gaW5jcmVhc2luZyBzdWJzZXF1ZW5jZSBvZiBsZW5ndGggalxuXHRjb25zdCBtID0gbmV3IEludDMyQXJyYXkoY2hpbGRyZW4ubGVuZ3RoICsgMSk7XG5cdC8vIFByZWRlY2Vzc29yIGluZGljZXMgKyAxXG5cdGNvbnN0IHAgPSBuZXcgSW50MzJBcnJheShjaGlsZHJlbi5sZW5ndGgpO1xuXHRtWzBdID0gLTE7XG5cdGxldCBsb25nZXN0ID0gMDtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuXHRcdGNvbnN0IGN1cnJlbnQgPSBjaGlsZHJlbltpXS5jbGFpbV9vcmRlcjtcblx0XHQvLyBGaW5kIHRoZSBsYXJnZXN0IHN1YnNlcXVlbmNlIGxlbmd0aCBzdWNoIHRoYXQgaXQgZW5kcyBpbiBhIHZhbHVlIGxlc3MgdGhhbiBvdXIgY3VycmVudCB2YWx1ZVxuXHRcdC8vIHVwcGVyX2JvdW5kIHJldHVybnMgZmlyc3QgZ3JlYXRlciB2YWx1ZSwgc28gd2Ugc3VidHJhY3Qgb25lXG5cdFx0Ly8gd2l0aCBmYXN0IHBhdGggZm9yIHdoZW4gd2UgYXJlIG9uIHRoZSBjdXJyZW50IGxvbmdlc3Qgc3Vic2VxdWVuY2Vcblx0XHRjb25zdCBzZXFfbGVuID1cblx0XHRcdChsb25nZXN0ID4gMCAmJiBjaGlsZHJlblttW2xvbmdlc3RdXS5jbGFpbV9vcmRlciA8PSBjdXJyZW50XG5cdFx0XHRcdD8gbG9uZ2VzdCArIDFcblx0XHRcdFx0OiB1cHBlcl9ib3VuZCgxLCBsb25nZXN0LCAoaWR4KSA9PiBjaGlsZHJlblttW2lkeF1dLmNsYWltX29yZGVyLCBjdXJyZW50KSkgLSAxO1xuXHRcdHBbaV0gPSBtW3NlcV9sZW5dICsgMTtcblx0XHRjb25zdCBuZXdfbGVuID0gc2VxX2xlbiArIDE7XG5cdFx0Ly8gV2UgY2FuIGd1YXJhbnRlZSB0aGF0IGN1cnJlbnQgaXMgdGhlIHNtYWxsZXN0IHZhbHVlLiBPdGhlcndpc2UsIHdlIHdvdWxkIGhhdmUgZ2VuZXJhdGVkIGEgbG9uZ2VyIHNlcXVlbmNlLlxuXHRcdG1bbmV3X2xlbl0gPSBpO1xuXHRcdGxvbmdlc3QgPSBNYXRoLm1heChuZXdfbGVuLCBsb25nZXN0KTtcblx0fVxuXHQvLyBUaGUgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlIG9mIG5vZGVzIChpbml0aWFsbHkgcmV2ZXJzZWQpXG5cblx0LyoqXG5cdCAqIEB0eXBlIHtOb2RlRXgyW119XG5cdCAqL1xuXHRjb25zdCBsaXMgPSBbXTtcblx0Ly8gVGhlIHJlc3Qgb2YgdGhlIG5vZGVzLCBub2RlcyB0aGF0IHdpbGwgYmUgbW92ZWRcblxuXHQvKipcblx0ICogQHR5cGUge05vZGVFeDJbXX1cblx0ICovXG5cdGNvbnN0IHRvX21vdmUgPSBbXTtcblx0bGV0IGxhc3QgPSBjaGlsZHJlbi5sZW5ndGggLSAxO1xuXHRmb3IgKGxldCBjdXIgPSBtW2xvbmdlc3RdICsgMTsgY3VyICE9IDA7IGN1ciA9IHBbY3VyIC0gMV0pIHtcblx0XHRsaXMucHVzaChjaGlsZHJlbltjdXIgLSAxXSk7XG5cdFx0Zm9yICg7IGxhc3QgPj0gY3VyOyBsYXN0LS0pIHtcblx0XHRcdHRvX21vdmUucHVzaChjaGlsZHJlbltsYXN0XSk7XG5cdFx0fVxuXHRcdGxhc3QtLTtcblx0fVxuXHRmb3IgKDsgbGFzdCA+PSAwOyBsYXN0LS0pIHtcblx0XHR0b19tb3ZlLnB1c2goY2hpbGRyZW5bbGFzdF0pO1xuXHR9XG5cdGxpcy5yZXZlcnNlKCk7XG5cdC8vIFdlIHNvcnQgdGhlIG5vZGVzIGJlaW5nIG1vdmVkIHRvIGd1YXJhbnRlZSB0aGF0IHRoZWlyIGluc2VydGlvbiBvcmRlciBtYXRjaGVzIHRoZSBjbGFpbSBvcmRlclxuXHR0b19tb3ZlLnNvcnQoKGEsIGIpID0+IGEuY2xhaW1fb3JkZXIgLSBiLmNsYWltX29yZGVyKTtcblx0Ly8gRmluYWxseSwgd2UgbW92ZSB0aGUgbm9kZXNcblx0Zm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgdG9fbW92ZS5sZW5ndGg7IGkrKykge1xuXHRcdHdoaWxlIChqIDwgbGlzLmxlbmd0aCAmJiB0b19tb3ZlW2ldLmNsYWltX29yZGVyID49IGxpc1tqXS5jbGFpbV9vcmRlcikge1xuXHRcdFx0aisrO1xuXHRcdH1cblx0XHRjb25zdCBhbmNob3IgPSBqIDwgbGlzLmxlbmd0aCA/IGxpc1tqXSA6IG51bGw7XG5cdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSh0b19tb3ZlW2ldLCBhbmNob3IpO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlfSB0YXJnZXRcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmQodGFyZ2V0LCBub2RlKSB7XG5cdHRhcmdldC5hcHBlbmRDaGlsZChub2RlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IHRhcmdldFxuICogQHBhcmFtIHtzdHJpbmd9IHN0eWxlX3NoZWV0X2lkXG4gKiBAcGFyYW0ge3N0cmluZ30gc3R5bGVzXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGVuZF9zdHlsZXModGFyZ2V0LCBzdHlsZV9zaGVldF9pZCwgc3R5bGVzKSB7XG5cdGNvbnN0IGFwcGVuZF9zdHlsZXNfdG8gPSBnZXRfcm9vdF9mb3Jfc3R5bGUodGFyZ2V0KTtcblx0aWYgKCFhcHBlbmRfc3R5bGVzX3RvLmdldEVsZW1lbnRCeUlkKHN0eWxlX3NoZWV0X2lkKSkge1xuXHRcdGNvbnN0IHN0eWxlID0gZWxlbWVudCgnc3R5bGUnKTtcblx0XHRzdHlsZS5pZCA9IHN0eWxlX3NoZWV0X2lkO1xuXHRcdHN0eWxlLnRleHRDb250ZW50ID0gc3R5bGVzO1xuXHRcdGFwcGVuZF9zdHlsZXNoZWV0KGFwcGVuZF9zdHlsZXNfdG8sIHN0eWxlKTtcblx0fVxufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge1NoYWRvd1Jvb3QgfCBEb2N1bWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldF9yb290X2Zvcl9zdHlsZShub2RlKSB7XG5cdGlmICghbm9kZSkgcmV0dXJuIGRvY3VtZW50O1xuXHRjb25zdCByb290ID0gbm9kZS5nZXRSb290Tm9kZSA/IG5vZGUuZ2V0Um9vdE5vZGUoKSA6IG5vZGUub3duZXJEb2N1bWVudDtcblx0aWYgKHJvb3QgJiYgLyoqIEB0eXBlIHtTaGFkb3dSb290fSAqLyAocm9vdCkuaG9zdCkge1xuXHRcdHJldHVybiAvKiogQHR5cGUge1NoYWRvd1Jvb3R9ICovIChyb290KTtcblx0fVxuXHRyZXR1cm4gbm9kZS5vd25lckRvY3VtZW50O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZVxuICogQHJldHVybnMge0NTU1N0eWxlU2hlZXR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRfZW1wdHlfc3R5bGVzaGVldChub2RlKSB7XG5cdGNvbnN0IHN0eWxlX2VsZW1lbnQgPSBlbGVtZW50KCdzdHlsZScpO1xuXHQvLyBGb3IgdHJhbnNpdGlvbnMgdG8gd29yayB3aXRob3V0ICdzdHlsZS1zcmM6IHVuc2FmZS1pbmxpbmUnIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5LFxuXHQvLyB0aGVzZSBlbXB0eSB0YWdzIG5lZWQgdG8gYmUgYWxsb3dlZCB3aXRoIGEgaGFzaCBhcyBhIHdvcmthcm91bmQgdW50aWwgd2UgbW92ZSB0byB0aGUgV2ViIEFuaW1hdGlvbnMgQVBJLlxuXHQvLyBVc2luZyB0aGUgaGFzaCBmb3IgdGhlIGVtcHR5IHN0cmluZyAoZm9yIGFuIGVtcHR5IHRhZykgd29ya3MgaW4gYWxsIGJyb3dzZXJzIGV4Y2VwdCBTYWZhcmkuXG5cdC8vIFNvIGFzIGEgd29ya2Fyb3VuZCBmb3IgdGhlIHdvcmthcm91bmQsIHdoZW4gd2UgYXBwZW5kIGVtcHR5IHN0eWxlIHRhZ3Mgd2Ugc2V0IHRoZWlyIGNvbnRlbnQgdG8gLyogZW1wdHkgKi8uXG5cdC8vIFRoZSBoYXNoICdzaGEyNTYtOU9sTk8wRE5FZWFWekhMNFJad0NMc0JIQThXQlE4dG9CcC80RjVYVjJuYz0nIHdpbGwgdGhlbiB3b3JrIGV2ZW4gaW4gU2FmYXJpLlxuXHRzdHlsZV9lbGVtZW50LnRleHRDb250ZW50ID0gJy8qIGVtcHR5ICovJztcblx0YXBwZW5kX3N0eWxlc2hlZXQoZ2V0X3Jvb3RfZm9yX3N0eWxlKG5vZGUpLCBzdHlsZV9lbGVtZW50KTtcblx0cmV0dXJuIHN0eWxlX2VsZW1lbnQuc2hlZXQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtTaGFkb3dSb290IHwgRG9jdW1lbnR9IG5vZGVcbiAqIEBwYXJhbSB7SFRNTFN0eWxlRWxlbWVudH0gc3R5bGVcbiAqIEByZXR1cm5zIHtDU1NTdHlsZVNoZWV0fVxuICovXG5mdW5jdGlvbiBhcHBlbmRfc3R5bGVzaGVldChub2RlLCBzdHlsZSkge1xuXHRhcHBlbmQoLyoqIEB0eXBlIHtEb2N1bWVudH0gKi8gKG5vZGUpLmhlYWQgfHwgbm9kZSwgc3R5bGUpO1xuXHRyZXR1cm4gc3R5bGUuc2hlZXQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlRXh9IHRhcmdldFxuICogQHBhcmFtIHtOb2RlRXh9IG5vZGVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kX2h5ZHJhdGlvbih0YXJnZXQsIG5vZGUpIHtcblx0aWYgKGlzX2h5ZHJhdGluZykge1xuXHRcdGluaXRfaHlkcmF0ZSh0YXJnZXQpO1xuXHRcdGlmIChcblx0XHRcdHRhcmdldC5hY3R1YWxfZW5kX2NoaWxkID09PSB1bmRlZmluZWQgfHxcblx0XHRcdCh0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCAhPT0gbnVsbCAmJiB0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZC5wYXJlbnROb2RlICE9PSB0YXJnZXQpXG5cdFx0KSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IHRhcmdldC5maXJzdENoaWxkO1xuXHRcdH1cblx0XHQvLyBTa2lwIG5vZGVzIG9mIHVuZGVmaW5lZCBvcmRlcmluZ1xuXHRcdHdoaWxlICh0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCAhPT0gbnVsbCAmJiB0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZC5jbGFpbV9vcmRlciA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IHRhcmdldC5hY3R1YWxfZW5kX2NoaWxkLm5leHRTaWJsaW5nO1xuXHRcdH1cblx0XHRpZiAobm9kZSAhPT0gdGFyZ2V0LmFjdHVhbF9lbmRfY2hpbGQpIHtcblx0XHRcdC8vIFdlIG9ubHkgaW5zZXJ0IGlmIHRoZSBvcmRlcmluZyBvZiB0aGlzIG5vZGUgc2hvdWxkIGJlIG1vZGlmaWVkIG9yIHRoZSBwYXJlbnQgbm9kZSBpcyBub3QgdGFyZ2V0XG5cdFx0XHRpZiAobm9kZS5jbGFpbV9vcmRlciAhPT0gdW5kZWZpbmVkIHx8IG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0KSB7XG5cdFx0XHRcdHRhcmdldC5pbnNlcnRCZWZvcmUobm9kZSwgdGFyZ2V0LmFjdHVhbF9lbmRfY2hpbGQpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0YXJnZXQuYWN0dWFsX2VuZF9jaGlsZCA9IG5vZGUubmV4dFNpYmxpbmc7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0IHx8IG5vZGUubmV4dFNpYmxpbmcgIT09IG51bGwpIHtcblx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQobm9kZSk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IHRhcmdldFxuICogQHBhcmFtIHtOb2RlfSBub2RlXG4gKiBAcGFyYW0ge05vZGV9IFthbmNob3JdXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydCh0YXJnZXQsIG5vZGUsIGFuY2hvcikge1xuXHR0YXJnZXQuaW5zZXJ0QmVmb3JlKG5vZGUsIGFuY2hvciB8fCBudWxsKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGVFeH0gdGFyZ2V0XG4gKiBAcGFyYW0ge05vZGVFeH0gbm9kZVxuICogQHBhcmFtIHtOb2RlRXh9IFthbmNob3JdXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydF9oeWRyYXRpb24odGFyZ2V0LCBub2RlLCBhbmNob3IpIHtcblx0aWYgKGlzX2h5ZHJhdGluZyAmJiAhYW5jaG9yKSB7XG5cdFx0YXBwZW5kX2h5ZHJhdGlvbih0YXJnZXQsIG5vZGUpO1xuXHR9IGVsc2UgaWYgKG5vZGUucGFyZW50Tm9kZSAhPT0gdGFyZ2V0IHx8IG5vZGUubmV4dFNpYmxpbmcgIT0gYW5jaG9yKSB7XG5cdFx0dGFyZ2V0Lmluc2VydEJlZm9yZShub2RlLCBhbmNob3IgfHwgbnVsbCk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGV0YWNoKG5vZGUpIHtcblx0aWYgKG5vZGUucGFyZW50Tm9kZSkge1xuXHRcdG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblx0fVxufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlc3Ryb3lfZWFjaChpdGVyYXRpb25zLCBkZXRhY2hpbmcpIHtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBpdGVyYXRpb25zLmxlbmd0aDsgaSArPSAxKSB7XG5cdFx0aWYgKGl0ZXJhdGlvbnNbaV0pIGl0ZXJhdGlvbnNbaV0uZChkZXRhY2hpbmcpO1xuXHR9XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIHtrZXlvZiBIVE1MRWxlbWVudFRhZ05hbWVNYXB9IEtcbiAqIEBwYXJhbSB7S30gbmFtZVxuICogQHJldHVybnMge0hUTUxFbGVtZW50VGFnTmFtZU1hcFtLXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVsZW1lbnQobmFtZSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChuYW1lKTtcbn1cblxuLyoqXG4gKiBAdGVtcGxhdGUge2tleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcH0gS1xuICogQHBhcmFtIHtLfSBuYW1lXG4gKiBAcGFyYW0ge3N0cmluZ30gaXNcbiAqIEByZXR1cm5zIHtIVE1MRWxlbWVudFRhZ05hbWVNYXBbS119XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbGVtZW50X2lzKG5hbWUsIGlzKSB7XG5cdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KG5hbWUsIHsgaXMgfSk7XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIFRcbiAqIEB0ZW1wbGF0ZSB7a2V5b2YgVH0gS1xuICogQHBhcmFtIHtUfSBvYmpcbiAqIEBwYXJhbSB7S1tdfSBleGNsdWRlXG4gKiBAcmV0dXJucyB7UGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+Pn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdF93aXRob3V0X3Byb3BlcnRpZXMob2JqLCBleGNsdWRlKSB7XG5cdGNvbnN0IHRhcmdldCA9IC8qKiBAdHlwZSB7UGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+Pn0gKi8gKHt9KTtcblx0Zm9yIChjb25zdCBrIGluIG9iaikge1xuXHRcdGlmIChcblx0XHRcdGhhc19wcm9wKG9iaiwgaykgJiZcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdGV4Y2x1ZGUuaW5kZXhPZihrKSA9PT0gLTFcblx0XHQpIHtcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdHRhcmdldFtrXSA9IG9ialtrXTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHRhcmdldDtcbn1cblxuLyoqXG4gKiBAdGVtcGxhdGUge2tleW9mIFNWR0VsZW1lbnRUYWdOYW1lTWFwfSBLXG4gKiBAcGFyYW0ge0t9IG5hbWVcbiAqIEByZXR1cm5zIHtTVkdFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3ZnX2VsZW1lbnQobmFtZSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsIG5hbWUpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhXG4gKiBAcmV0dXJucyB7VGV4dH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRleHQoZGF0YSkge1xuXHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoZGF0YSk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gc3BhY2UoKSB7XG5cdHJldHVybiB0ZXh0KCcgJyk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gZW1wdHkoKSB7XG5cdHJldHVybiB0ZXh0KCcnKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudFxuICogQHJldHVybnMge0NvbW1lbnR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21tZW50KGNvbnRlbnQpIHtcblx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoY29udGVudCk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtFdmVudFRhcmdldH0gbm9kZVxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50XG4gKiBAcGFyYW0ge0V2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3R9IGhhbmRsZXJcbiAqIEBwYXJhbSB7Ym9vbGVhbiB8IEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zIHwgRXZlbnRMaXN0ZW5lck9wdGlvbnN9IFtvcHRpb25zXVxuICogQHJldHVybnMgeygpID0+IHZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0ZW4obm9kZSwgZXZlbnQsIGhhbmRsZXIsIG9wdGlvbnMpIHtcblx0bm9kZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLCBvcHRpb25zKTtcblx0cmV0dXJuICgpID0+IG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlciwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogQHJldHVybnMgeyhldmVudDogYW55KSA9PiBhbnl9ICovXG5leHBvcnQgZnVuY3Rpb24gcHJldmVudF9kZWZhdWx0KGZuKSB7XG5cdHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdC8vIEB0cy1pZ25vcmVcblx0XHRyZXR1cm4gZm4uY2FsbCh0aGlzLCBldmVudCk7XG5cdH07XG59XG5cbi8qKlxuICogQHJldHVybnMgeyhldmVudDogYW55KSA9PiBhbnl9ICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcF9wcm9wYWdhdGlvbihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdHJldHVybiBmbi5jYWxsKHRoaXMsIGV2ZW50KTtcblx0fTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7KGV2ZW50OiBhbnkpID0+IGFueX0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9wX2ltbWVkaWF0ZV9wcm9wYWdhdGlvbihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdHJldHVybiBmbi5jYWxsKHRoaXMsIGV2ZW50KTtcblx0fTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7KGV2ZW50OiBhbnkpID0+IHZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2VsZihmbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0Ly8gQHRzLWlnbm9yZVxuXHRcdGlmIChldmVudC50YXJnZXQgPT09IHRoaXMpIGZuLmNhbGwodGhpcywgZXZlbnQpO1xuXHR9O1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHsoZXZlbnQ6IGFueSkgPT4gdm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cnVzdGVkKGZuKSB7XG5cdHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0aWYgKGV2ZW50LmlzVHJ1c3RlZCkgZm4uY2FsbCh0aGlzLCBldmVudCk7XG5cdH07XG59XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBub2RlXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0cmlidXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gW3ZhbHVlXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRyKG5vZGUsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcblx0aWYgKHZhbHVlID09IG51bGwpIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJpYnV0ZSk7XG5cdGVsc2UgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZSkgIT09IHZhbHVlKSBub2RlLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUsIHZhbHVlKTtcbn1cbi8qKlxuICogTGlzdCBvZiBhdHRyaWJ1dGVzIHRoYXQgc2hvdWxkIGFsd2F5cyBiZSBzZXQgdGhyb3VnaCB0aGUgYXR0ciBtZXRob2QsXG4gKiBiZWNhdXNlIHVwZGF0aW5nIHRoZW0gdGhyb3VnaCB0aGUgcHJvcGVydHkgc2V0dGVyIGRvZXNuJ3Qgd29yayByZWxpYWJseS5cbiAqIEluIHRoZSBleGFtcGxlIG9mIGB3aWR0aGAvYGhlaWdodGAsIHRoZSBwcm9ibGVtIGlzIHRoYXQgdGhlIHNldHRlciBvbmx5XG4gKiBhY2NlcHRzIG51bWVyaWMgdmFsdWVzLCBidXQgdGhlIGF0dHJpYnV0ZSBjYW4gYWxzbyBiZSBzZXQgdG8gYSBzdHJpbmcgbGlrZSBgNTAlYC5cbiAqIElmIHRoaXMgbGlzdCBiZWNvbWVzIHRvbyBiaWcsIHJldGhpbmsgdGhpcyBhcHByb2FjaC5cbiAqL1xuY29uc3QgYWx3YXlzX3NldF90aHJvdWdoX3NldF9hdHRyaWJ1dGUgPSBbJ3dpZHRoJywgJ2hlaWdodCddO1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHt7IFt4OiBzdHJpbmddOiBzdHJpbmcgfX0gYXR0cmlidXRlc1xuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfYXR0cmlidXRlcyhub2RlLCBhdHRyaWJ1dGVzKSB7XG5cdC8vIEB0cy1pZ25vcmVcblx0Y29uc3QgZGVzY3JpcHRvcnMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhub2RlLl9fcHJvdG9fXyk7XG5cdGZvciAoY29uc3Qga2V5IGluIGF0dHJpYnV0ZXMpIHtcblx0XHRpZiAoYXR0cmlidXRlc1trZXldID09IG51bGwpIHtcblx0XHRcdG5vZGUucmVtb3ZlQXR0cmlidXRlKGtleSk7XG5cdFx0fSBlbHNlIGlmIChrZXkgPT09ICdzdHlsZScpIHtcblx0XHRcdG5vZGUuc3R5bGUuY3NzVGV4dCA9IGF0dHJpYnV0ZXNba2V5XTtcblx0XHR9IGVsc2UgaWYgKGtleSA9PT0gJ19fdmFsdWUnKSB7XG5cdFx0XHQvKiogQHR5cGUge2FueX0gKi8gKG5vZGUpLnZhbHVlID0gbm9kZVtrZXldID0gYXR0cmlidXRlc1trZXldO1xuXHRcdH0gZWxzZSBpZiAoXG5cdFx0XHRkZXNjcmlwdG9yc1trZXldICYmXG5cdFx0XHRkZXNjcmlwdG9yc1trZXldLnNldCAmJlxuXHRcdFx0YWx3YXlzX3NldF90aHJvdWdoX3NldF9hdHRyaWJ1dGUuaW5kZXhPZihrZXkpID09PSAtMVxuXHRcdCkge1xuXHRcdFx0bm9kZVtrZXldID0gYXR0cmlidXRlc1trZXldO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhdHRyKG5vZGUsIGtleSwgYXR0cmlidXRlc1trZXldKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnQgJiBFbGVtZW50Q1NTSW5saW5lU3R5bGV9IG5vZGVcbiAqIEBwYXJhbSB7eyBbeDogc3RyaW5nXTogc3RyaW5nIH19IGF0dHJpYnV0ZXNcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X3N2Z19hdHRyaWJ1dGVzKG5vZGUsIGF0dHJpYnV0ZXMpIHtcblx0Zm9yIChjb25zdCBrZXkgaW4gYXR0cmlidXRlcykge1xuXHRcdGF0dHIobm9kZSwga2V5LCBhdHRyaWJ1dGVzW2tleV0pO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gZGF0YV9tYXBcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2N1c3RvbV9lbGVtZW50X2RhdGFfbWFwKG5vZGUsIGRhdGFfbWFwKSB7XG5cdE9iamVjdC5rZXlzKGRhdGFfbWFwKS5mb3JFYWNoKChrZXkpID0+IHtcblx0XHRzZXRfY3VzdG9tX2VsZW1lbnRfZGF0YShub2RlLCBrZXksIGRhdGFfbWFwW2tleV0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfY3VzdG9tX2VsZW1lbnRfZGF0YShub2RlLCBwcm9wLCB2YWx1ZSkge1xuXHRjb25zdCBsb3dlciA9IHByb3AudG9Mb3dlckNhc2UoKTsgLy8gZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggZXhpc3RpbmcgYmVoYXZpb3Igd2UgZG8gbG93ZXJjYXNlIGZpcnN0XG5cdGlmIChsb3dlciBpbiBub2RlKSB7XG5cdFx0bm9kZVtsb3dlcl0gPSB0eXBlb2Ygbm9kZVtsb3dlcl0gPT09ICdib29sZWFuJyAmJiB2YWx1ZSA9PT0gJycgPyB0cnVlIDogdmFsdWU7XG5cdH0gZWxzZSBpZiAocHJvcCBpbiBub2RlKSB7XG5cdFx0bm9kZVtwcm9wXSA9IHR5cGVvZiBub2RlW3Byb3BdID09PSAnYm9vbGVhbicgJiYgdmFsdWUgPT09ICcnID8gdHJ1ZSA6IHZhbHVlO1xuXHR9IGVsc2Uge1xuXHRcdGF0dHIobm9kZSwgcHJvcCwgdmFsdWUpO1xuXHR9XG59XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHRhZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2R5bmFtaWNfZWxlbWVudF9kYXRhKHRhZykge1xuXHRyZXR1cm4gLy0vLnRlc3QodGFnKSA/IHNldF9jdXN0b21fZWxlbWVudF9kYXRhX21hcCA6IHNldF9hdHRyaWJ1dGVzO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24geGxpbmtfYXR0cihub2RlLCBhdHRyaWJ1dGUsIHZhbHVlKSB7XG5cdG5vZGUuc2V0QXR0cmlidXRlTlMoJ2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnLCBhdHRyaWJ1dGUsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBub2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X3N2ZWx0ZV9kYXRhc2V0KG5vZGUpIHtcblx0cmV0dXJuIG5vZGUuZGF0YXNldC5zdmVsdGVIO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt1bmtub3duW119ICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X2JpbmRpbmdfZ3JvdXBfdmFsdWUoZ3JvdXAsIF9fdmFsdWUsIGNoZWNrZWQpIHtcblx0Y29uc3QgdmFsdWUgPSBuZXcgU2V0KCk7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgZ3JvdXAubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRpZiAoZ3JvdXBbaV0uY2hlY2tlZCkgdmFsdWUuYWRkKGdyb3VwW2ldLl9fdmFsdWUpO1xuXHR9XG5cdGlmICghY2hlY2tlZCkge1xuXHRcdHZhbHVlLmRlbGV0ZShfX3ZhbHVlKTtcblx0fVxuXHRyZXR1cm4gQXJyYXkuZnJvbSh2YWx1ZSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MSW5wdXRFbGVtZW50W119IGdyb3VwXG4gKiBAcmV0dXJucyB7eyBwKC4uLmlucHV0czogSFRNTElucHV0RWxlbWVudFtdKTogdm9pZDsgcigpOiB2b2lkOyB9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdF9iaW5kaW5nX2dyb3VwKGdyb3VwKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2lucHV0cztcblx0cmV0dXJuIHtcblx0XHQvKiBwdXNoICovIHAoLi4uaW5wdXRzKSB7XG5cdFx0XHRfaW5wdXRzID0gaW5wdXRzO1xuXHRcdFx0X2lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gZ3JvdXAucHVzaChpbnB1dCkpO1xuXHRcdH0sXG5cdFx0LyogcmVtb3ZlICovIHIoKSB7XG5cdFx0XHRfaW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiBncm91cC5zcGxpY2UoZ3JvdXAuaW5kZXhPZihpbnB1dCksIDEpKTtcblx0XHR9XG5cdH07XG59XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJbXX0gaW5kZXhlc1xuICogQHJldHVybnMge3sgdShuZXdfaW5kZXhlczogbnVtYmVyW10pOiB2b2lkOyBwKC4uLmlucHV0czogSFRNTElucHV0RWxlbWVudFtdKTogdm9pZDsgcjogKCkgPT4gdm9pZDsgfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRfYmluZGluZ19ncm91cF9keW5hbWljKGdyb3VwLCBpbmRleGVzKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2dyb3VwID0gZ2V0X2JpbmRpbmdfZ3JvdXAoZ3JvdXApO1xuXG5cdC8qKlxuXHQgKiBAdHlwZSB7SFRNTElucHV0RWxlbWVudFtdfSAqL1xuXHRsZXQgX2lucHV0cztcblxuXHRmdW5jdGlvbiBnZXRfYmluZGluZ19ncm91cChncm91cCkge1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaW5kZXhlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Z3JvdXAgPSBncm91cFtpbmRleGVzW2ldXSA9IGdyb3VwW2luZGV4ZXNbaV1dIHx8IFtdO1xuXHRcdH1cblx0XHRyZXR1cm4gZ3JvdXA7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGZ1bmN0aW9uIHB1c2goKSB7XG5cdFx0X2lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT4gX2dyb3VwLnB1c2goaW5wdXQpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJucyB7dm9pZH0gKi9cblx0ZnVuY3Rpb24gcmVtb3ZlKCkge1xuXHRcdF9pbnB1dHMuZm9yRWFjaCgoaW5wdXQpID0+IF9ncm91cC5zcGxpY2UoX2dyb3VwLmluZGV4T2YoaW5wdXQpLCAxKSk7XG5cdH1cblx0cmV0dXJuIHtcblx0XHQvKiB1cGRhdGUgKi8gdShuZXdfaW5kZXhlcykge1xuXHRcdFx0aW5kZXhlcyA9IG5ld19pbmRleGVzO1xuXHRcdFx0Y29uc3QgbmV3X2dyb3VwID0gZ2V0X2JpbmRpbmdfZ3JvdXAoZ3JvdXApO1xuXHRcdFx0aWYgKG5ld19ncm91cCAhPT0gX2dyb3VwKSB7XG5cdFx0XHRcdHJlbW92ZSgpO1xuXHRcdFx0XHRfZ3JvdXAgPSBuZXdfZ3JvdXA7XG5cdFx0XHRcdHB1c2goKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdC8qIHB1c2ggKi8gcCguLi5pbnB1dHMpIHtcblx0XHRcdF9pbnB1dHMgPSBpbnB1dHM7XG5cdFx0XHRwdXNoKCk7XG5cdFx0fSxcblx0XHQvKiByZW1vdmUgKi8gcjogcmVtb3ZlXG5cdH07XG59XG5cbi8qKiBAcmV0dXJucyB7bnVtYmVyfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvX251bWJlcih2YWx1ZSkge1xuXHRyZXR1cm4gdmFsdWUgPT09ICcnID8gbnVsbCA6ICt2YWx1ZTtcbn1cblxuLyoqIEByZXR1cm5zIHthbnlbXX0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aW1lX3Jhbmdlc190b19hcnJheShyYW5nZXMpIHtcblx0Y29uc3QgYXJyYXkgPSBbXTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRhcnJheS5wdXNoKHsgc3RhcnQ6IHJhbmdlcy5zdGFydChpKSwgZW5kOiByYW5nZXMuZW5kKGkpIH0pO1xuXHR9XG5cdHJldHVybiBhcnJheTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtDaGlsZE5vZGVbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoaWxkcmVuKGVsZW1lbnQpIHtcblx0cmV0dXJuIEFycmF5LmZyb20oZWxlbWVudC5jaGlsZE5vZGVzKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGluaXRfY2xhaW1faW5mbyhub2Rlcykge1xuXHRpZiAobm9kZXMuY2xhaW1faW5mbyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0bm9kZXMuY2xhaW1faW5mbyA9IHsgbGFzdF9pbmRleDogMCwgdG90YWxfY2xhaW1lZDogMCB9O1xuXHR9XG59XG5cbi8qKlxuICogQHRlbXBsYXRlIHtDaGlsZE5vZGVFeH0gUlxuICogQHBhcmFtIHtDaGlsZE5vZGVBcnJheX0gbm9kZXNcbiAqIEBwYXJhbSB7KG5vZGU6IENoaWxkTm9kZUV4KSA9PiBub2RlIGlzIFJ9IHByZWRpY2F0ZVxuICogQHBhcmFtIHsobm9kZTogQ2hpbGROb2RlRXgpID0+IENoaWxkTm9kZUV4IHwgdW5kZWZpbmVkfSBwcm9jZXNzX25vZGVcbiAqIEBwYXJhbSB7KCkgPT4gUn0gY3JlYXRlX25vZGVcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9udF91cGRhdGVfbGFzdF9pbmRleFxuICogQHJldHVybnMge1J9XG4gKi9cbmZ1bmN0aW9uIGNsYWltX25vZGUobm9kZXMsIHByZWRpY2F0ZSwgcHJvY2Vzc19ub2RlLCBjcmVhdGVfbm9kZSwgZG9udF91cGRhdGVfbGFzdF9pbmRleCA9IGZhbHNlKSB7XG5cdC8vIFRyeSB0byBmaW5kIG5vZGVzIGluIGFuIG9yZGVyIHN1Y2ggdGhhdCB3ZSBsZW5ndGhlbiB0aGUgbG9uZ2VzdCBpbmNyZWFzaW5nIHN1YnNlcXVlbmNlXG5cdGluaXRfY2xhaW1faW5mbyhub2Rlcyk7XG5cdGNvbnN0IHJlc3VsdF9ub2RlID0gKCgpID0+IHtcblx0XHQvLyBXZSBmaXJzdCB0cnkgdG8gZmluZCBhbiBlbGVtZW50IGFmdGVyIHRoZSBwcmV2aW91cyBvbmVcblx0XHRmb3IgKGxldCBpID0gbm9kZXMuY2xhaW1faW5mby5sYXN0X2luZGV4OyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcblx0XHRcdGlmIChwcmVkaWNhdGUobm9kZSkpIHtcblx0XHRcdFx0Y29uc3QgcmVwbGFjZW1lbnQgPSBwcm9jZXNzX25vZGUobm9kZSk7XG5cdFx0XHRcdGlmIChyZXBsYWNlbWVudCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0bm9kZXMuc3BsaWNlKGksIDEpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdG5vZGVzW2ldID0gcmVwbGFjZW1lbnQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCFkb250X3VwZGF0ZV9sYXN0X2luZGV4KSB7XG5cdFx0XHRcdFx0bm9kZXMuY2xhaW1faW5mby5sYXN0X2luZGV4ID0gaTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gbm9kZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gT3RoZXJ3aXNlLCB3ZSB0cnkgdG8gZmluZCBvbmUgYmVmb3JlXG5cdFx0Ly8gV2UgaXRlcmF0ZSBpbiByZXZlcnNlIHNvIHRoYXQgd2UgZG9uJ3QgZ28gdG9vIGZhciBiYWNrXG5cdFx0Zm9yIChsZXQgaSA9IG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleCAtIDE7IGkgPj0gMDsgaS0tKSB7XG5cdFx0XHRjb25zdCBub2RlID0gbm9kZXNbaV07XG5cdFx0XHRpZiAocHJlZGljYXRlKG5vZGUpKSB7XG5cdFx0XHRcdGNvbnN0IHJlcGxhY2VtZW50ID0gcHJvY2Vzc19ub2RlKG5vZGUpO1xuXHRcdFx0XHRpZiAocmVwbGFjZW1lbnQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdG5vZGVzLnNwbGljZShpLCAxKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRub2Rlc1tpXSA9IHJlcGxhY2VtZW50O1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICghZG9udF91cGRhdGVfbGFzdF9pbmRleCkge1xuXHRcdFx0XHRcdG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleCA9IGk7XG5cdFx0XHRcdH0gZWxzZSBpZiAocmVwbGFjZW1lbnQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdC8vIFNpbmNlIHdlIHNwbGljZWQgYmVmb3JlIHRoZSBsYXN0X2luZGV4LCB3ZSBkZWNyZWFzZSBpdFxuXHRcdFx0XHRcdG5vZGVzLmNsYWltX2luZm8ubGFzdF9pbmRleC0tO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBub2RlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBJZiB3ZSBjYW4ndCBmaW5kIGFueSBtYXRjaGluZyBub2RlLCB3ZSBjcmVhdGUgYSBuZXcgb25lXG5cdFx0cmV0dXJuIGNyZWF0ZV9ub2RlKCk7XG5cdH0pKCk7XG5cdHJlc3VsdF9ub2RlLmNsYWltX29yZGVyID0gbm9kZXMuY2xhaW1faW5mby50b3RhbF9jbGFpbWVkO1xuXHRub2Rlcy5jbGFpbV9pbmZvLnRvdGFsX2NsYWltZWQgKz0gMTtcblx0cmV0dXJuIHJlc3VsdF9ub2RlO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Q2hpbGROb2RlQXJyYXl9IG5vZGVzXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHt7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfX0gYXR0cmlidXRlc1xuICogQHBhcmFtIHsobmFtZTogc3RyaW5nKSA9PiBFbGVtZW50IHwgU1ZHRWxlbWVudH0gY3JlYXRlX2VsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50IHwgU1ZHRWxlbWVudH1cbiAqL1xuZnVuY3Rpb24gY2xhaW1fZWxlbWVudF9iYXNlKG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzLCBjcmVhdGVfZWxlbWVudCkge1xuXHRyZXR1cm4gY2xhaW1fbm9kZShcblx0XHRub2Rlcyxcblx0XHQvKiogQHJldHVybnMge25vZGUgaXMgRWxlbWVudCB8IFNWR0VsZW1lbnR9ICovXG5cdFx0KG5vZGUpID0+IG5vZGUubm9kZU5hbWUgPT09IG5hbWUsXG5cdFx0LyoqIEBwYXJhbSB7RWxlbWVudH0gbm9kZSAqL1xuXHRcdChub2RlKSA9PiB7XG5cdFx0XHRjb25zdCByZW1vdmUgPSBbXTtcblx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgbm9kZS5hdHRyaWJ1dGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGNvbnN0IGF0dHJpYnV0ZSA9IG5vZGUuYXR0cmlidXRlc1tqXTtcblx0XHRcdFx0aWYgKCFhdHRyaWJ1dGVzW2F0dHJpYnV0ZS5uYW1lXSkge1xuXHRcdFx0XHRcdHJlbW92ZS5wdXNoKGF0dHJpYnV0ZS5uYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmVtb3ZlLmZvckVhY2goKHYpID0+IG5vZGUucmVtb3ZlQXR0cmlidXRlKHYpKTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0XHQoKSA9PiBjcmVhdGVfZWxlbWVudChuYW1lKVxuXHQpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Q2hpbGROb2RlQXJyYXl9IG5vZGVzXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHt7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfX0gYXR0cmlidXRlc1xuICogQHJldHVybnMge0VsZW1lbnQgfCBTVkdFbGVtZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fZWxlbWVudChub2RlcywgbmFtZSwgYXR0cmlidXRlcykge1xuXHRyZXR1cm4gY2xhaW1fZWxlbWVudF9iYXNlKG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzLCBlbGVtZW50KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7eyBba2V5OiBzdHJpbmddOiBib29sZWFuIH19IGF0dHJpYnV0ZXNcbiAqIEByZXR1cm5zIHtFbGVtZW50IHwgU1ZHRWxlbWVudH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYWltX3N2Z19lbGVtZW50KG5vZGVzLCBuYW1lLCBhdHRyaWJ1dGVzKSB7XG5cdHJldHVybiBjbGFpbV9lbGVtZW50X2Jhc2Uobm9kZXMsIG5hbWUsIGF0dHJpYnV0ZXMsIHN2Z19lbGVtZW50KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0NoaWxkTm9kZUFycmF5fSBub2Rlc1xuICogQHJldHVybnMge1RleHR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFpbV90ZXh0KG5vZGVzLCBkYXRhKSB7XG5cdHJldHVybiBjbGFpbV9ub2RlKFxuXHRcdG5vZGVzLFxuXHRcdC8qKiBAcmV0dXJucyB7bm9kZSBpcyBUZXh0fSAqL1xuXHRcdChub2RlKSA9PiBub2RlLm5vZGVUeXBlID09PSAzLFxuXHRcdC8qKiBAcGFyYW0ge1RleHR9IG5vZGUgKi9cblx0XHQobm9kZSkgPT4ge1xuXHRcdFx0Y29uc3QgZGF0YV9zdHIgPSAnJyArIGRhdGE7XG5cdFx0XHRpZiAobm9kZS5kYXRhLnN0YXJ0c1dpdGgoZGF0YV9zdHIpKSB7XG5cdFx0XHRcdGlmIChub2RlLmRhdGEubGVuZ3RoICE9PSBkYXRhX3N0ci5sZW5ndGgpIHtcblx0XHRcdFx0XHRyZXR1cm4gbm9kZS5zcGxpdFRleHQoZGF0YV9zdHIubGVuZ3RoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bm9kZS5kYXRhID0gZGF0YV9zdHI7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHQoKSA9PiB0ZXh0KGRhdGEpLFxuXHRcdHRydWUgLy8gVGV4dCBub2RlcyBzaG91bGQgbm90IHVwZGF0ZSBsYXN0IGluZGV4IHNpbmNlIGl0IGlzIGxpa2VseSBub3Qgd29ydGggaXQgdG8gZWxpbWluYXRlIGFuIGluY3JlYXNpbmcgc3Vic2VxdWVuY2Ugb2YgYWN0dWFsIGVsZW1lbnRzXG5cdCk7XG59XG5cbi8qKlxuICogQHJldHVybnMge1RleHR9ICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fc3BhY2Uobm9kZXMpIHtcblx0cmV0dXJuIGNsYWltX3RleHQobm9kZXMsICcgJyk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtDaGlsZE5vZGVBcnJheX0gbm9kZXNcbiAqIEByZXR1cm5zIHtDb21tZW50fVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1fY29tbWVudChub2RlcywgZGF0YSkge1xuXHRyZXR1cm4gY2xhaW1fbm9kZShcblx0XHRub2Rlcyxcblx0XHQvKiogQHJldHVybnMge25vZGUgaXMgQ29tbWVudH0gKi9cblx0XHQobm9kZSkgPT4gbm9kZS5ub2RlVHlwZSA9PT0gOCxcblx0XHQvKiogQHBhcmFtIHtDb21tZW50fSBub2RlICovXG5cdFx0KG5vZGUpID0+IHtcblx0XHRcdG5vZGUuZGF0YSA9ICcnICsgZGF0YTtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fSxcblx0XHQoKSA9PiBjb21tZW50KGRhdGEpLFxuXHRcdHRydWVcblx0KTtcbn1cblxuZnVuY3Rpb24gZ2V0X2NvbW1lbnRfaWR4KG5vZGVzLCB0ZXh0LCBzdGFydCkge1xuXHRmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBub2Rlcy5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcblx0XHRpZiAobm9kZS5ub2RlVHlwZSA9PT0gOCAvKiBjb21tZW50IG5vZGUgKi8gJiYgbm9kZS50ZXh0Q29udGVudC50cmltKCkgPT09IHRleHQpIHtcblx0XHRcdHJldHVybiBpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gLTE7XG59XG5cbi8qKlxuICogQHBhcmFtIHtib29sZWFufSBpc19zdmdcbiAqIEByZXR1cm5zIHtIdG1sVGFnSHlkcmF0aW9ufVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhaW1faHRtbF90YWcobm9kZXMsIGlzX3N2Zykge1xuXHQvLyBmaW5kIGh0bWwgb3BlbmluZyB0YWdcblx0Y29uc3Qgc3RhcnRfaW5kZXggPSBnZXRfY29tbWVudF9pZHgobm9kZXMsICdIVE1MX1RBR19TVEFSVCcsIDApO1xuXHRjb25zdCBlbmRfaW5kZXggPSBnZXRfY29tbWVudF9pZHgobm9kZXMsICdIVE1MX1RBR19FTkQnLCBzdGFydF9pbmRleCArIDEpO1xuXHRpZiAoc3RhcnRfaW5kZXggPT09IC0xIHx8IGVuZF9pbmRleCA9PT0gLTEpIHtcblx0XHRyZXR1cm4gbmV3IEh0bWxUYWdIeWRyYXRpb24oaXNfc3ZnKTtcblx0fVxuXG5cdGluaXRfY2xhaW1faW5mbyhub2Rlcyk7XG5cdGNvbnN0IGh0bWxfdGFnX25vZGVzID0gbm9kZXMuc3BsaWNlKHN0YXJ0X2luZGV4LCBlbmRfaW5kZXggLSBzdGFydF9pbmRleCArIDEpO1xuXHRkZXRhY2goaHRtbF90YWdfbm9kZXNbMF0pO1xuXHRkZXRhY2goaHRtbF90YWdfbm9kZXNbaHRtbF90YWdfbm9kZXMubGVuZ3RoIC0gMV0pO1xuXHRjb25zdCBjbGFpbWVkX25vZGVzID0gaHRtbF90YWdfbm9kZXMuc2xpY2UoMSwgaHRtbF90YWdfbm9kZXMubGVuZ3RoIC0gMSk7XG5cdGlmIChjbGFpbWVkX25vZGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBuZXcgSHRtbFRhZ0h5ZHJhdGlvbihpc19zdmcpO1xuXHR9XG5cdGZvciAoY29uc3QgbiBvZiBjbGFpbWVkX25vZGVzKSB7XG5cdFx0bi5jbGFpbV9vcmRlciA9IG5vZGVzLmNsYWltX2luZm8udG90YWxfY2xhaW1lZDtcblx0XHRub2Rlcy5jbGFpbV9pbmZvLnRvdGFsX2NsYWltZWQgKz0gMTtcblx0fVxuXHRyZXR1cm4gbmV3IEh0bWxUYWdIeWRyYXRpb24oaXNfc3ZnLCBjbGFpbWVkX25vZGVzKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfZGF0YSh0ZXh0LCBkYXRhKSB7XG5cdGRhdGEgPSAnJyArIGRhdGE7XG5cdGlmICh0ZXh0LmRhdGEgPT09IGRhdGEpIHJldHVybjtcblx0dGV4dC5kYXRhID0gLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkYXRhKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfZGF0YV9jb250ZW50ZWRpdGFibGUodGV4dCwgZGF0YSkge1xuXHRkYXRhID0gJycgKyBkYXRhO1xuXHRpZiAodGV4dC53aG9sZVRleHQgPT09IGRhdGEpIHJldHVybjtcblx0dGV4dC5kYXRhID0gLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkYXRhKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge1RleHR9IHRleHRcbiAqIEBwYXJhbSB7dW5rbm93bn0gZGF0YVxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHJfdmFsdWVcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2RhdGFfbWF5YmVfY29udGVudGVkaXRhYmxlKHRleHQsIGRhdGEsIGF0dHJfdmFsdWUpIHtcblx0aWYgKH5jb250ZW50ZWRpdGFibGVfdHJ1dGh5X3ZhbHVlcy5pbmRleE9mKGF0dHJfdmFsdWUpKSB7XG5cdFx0c2V0X2RhdGFfY29udGVudGVkaXRhYmxlKHRleHQsIGRhdGEpO1xuXHR9IGVsc2Uge1xuXHRcdHNldF9kYXRhKHRleHQsIGRhdGEpO1xuXHR9XG59XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2V0X2lucHV0X3ZhbHVlKGlucHV0LCB2YWx1ZSkge1xuXHRpbnB1dC52YWx1ZSA9IHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldF9pbnB1dF90eXBlKGlucHV0LCB0eXBlKSB7XG5cdHRyeSB7XG5cdFx0aW5wdXQudHlwZSA9IHR5cGU7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHQvLyBkbyBub3RoaW5nXG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRfc3R5bGUobm9kZSwga2V5LCB2YWx1ZSwgaW1wb3J0YW50KSB7XG5cdGlmICh2YWx1ZSA9PSBudWxsKSB7XG5cdFx0bm9kZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpO1xuXHR9IGVsc2Uge1xuXHRcdG5vZGUuc3R5bGUuc2V0UHJvcGVydHkoa2V5LCB2YWx1ZSwgaW1wb3J0YW50ID8gJ2ltcG9ydGFudCcgOiAnJyk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3Rfb3B0aW9uKHNlbGVjdCwgdmFsdWUsIG1vdW50aW5nKSB7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0Lm9wdGlvbnMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRjb25zdCBvcHRpb24gPSBzZWxlY3Qub3B0aW9uc1tpXTtcblx0XHRpZiAob3B0aW9uLl9fdmFsdWUgPT09IHZhbHVlKSB7XG5cdFx0XHRvcHRpb24uc2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0fVxuXHRpZiAoIW1vdW50aW5nIHx8IHZhbHVlICE9PSB1bmRlZmluZWQpIHtcblx0XHRzZWxlY3Quc2VsZWN0ZWRJbmRleCA9IC0xOyAvLyBubyBvcHRpb24gc2hvdWxkIGJlIHNlbGVjdGVkXG5cdH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3Rfb3B0aW9ucyhzZWxlY3QsIHZhbHVlKSB7XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0Lm9wdGlvbnMubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRjb25zdCBvcHRpb24gPSBzZWxlY3Qub3B0aW9uc1tpXTtcblx0XHRvcHRpb24uc2VsZWN0ZWQgPSB+dmFsdWUuaW5kZXhPZihvcHRpb24uX192YWx1ZSk7XG5cdH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNlbGVjdF92YWx1ZShzZWxlY3QpIHtcblx0Y29uc3Qgc2VsZWN0ZWRfb3B0aW9uID0gc2VsZWN0LnF1ZXJ5U2VsZWN0b3IoJzpjaGVja2VkJyk7XG5cdHJldHVybiBzZWxlY3RlZF9vcHRpb24gJiYgc2VsZWN0ZWRfb3B0aW9uLl9fdmFsdWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3RfbXVsdGlwbGVfdmFsdWUoc2VsZWN0KSB7XG5cdHJldHVybiBbXS5tYXAuY2FsbChzZWxlY3QucXVlcnlTZWxlY3RvckFsbCgnOmNoZWNrZWQnKSwgKG9wdGlvbikgPT4gb3B0aW9uLl9fdmFsdWUpO1xufVxuLy8gdW5mb3J0dW5hdGVseSB0aGlzIGNhbid0IGJlIGEgY29uc3RhbnQgYXMgdGhhdCB3b3VsZG4ndCBiZSB0cmVlLXNoYWtlYWJsZVxuLy8gc28gd2UgY2FjaGUgdGhlIHJlc3VsdCBpbnN0ZWFkXG5cbi8qKlxuICogQHR5cGUge2Jvb2xlYW59ICovXG5sZXQgY3Jvc3NvcmlnaW47XG5cbi8qKlxuICogQHJldHVybnMge2Jvb2xlYW59ICovXG5leHBvcnQgZnVuY3Rpb24gaXNfY3Jvc3NvcmlnaW4oKSB7XG5cdGlmIChjcm9zc29yaWdpbiA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0Y3Jvc3NvcmlnaW4gPSBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0aWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5wYXJlbnQpIHtcblx0XHRcdFx0dm9pZCB3aW5kb3cucGFyZW50LmRvY3VtZW50O1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRjcm9zc29yaWdpbiA9IHRydWU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBjcm9zc29yaWdpbjtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBub2RlXG4gKiBAcGFyYW0geygpID0+IHZvaWR9IGZuXG4gKiBAcmV0dXJucyB7KCkgPT4gdm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZF9pZnJhbWVfcmVzaXplX2xpc3RlbmVyKG5vZGUsIGZuKSB7XG5cdGNvbnN0IGNvbXB1dGVkX3N0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShub2RlKTtcblx0aWYgKGNvbXB1dGVkX3N0eWxlLnBvc2l0aW9uID09PSAnc3RhdGljJykge1xuXHRcdG5vZGUuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuXHR9XG5cdGNvbnN0IGlmcmFtZSA9IGVsZW1lbnQoJ2lmcmFtZScpO1xuXHRpZnJhbWUuc2V0QXR0cmlidXRlKFxuXHRcdCdzdHlsZScsXG5cdFx0J2Rpc3BsYXk6IGJsb2NrOyBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogMDsgbGVmdDogMDsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsgJyArXG5cdFx0XHQnb3ZlcmZsb3c6IGhpZGRlbjsgYm9yZGVyOiAwOyBvcGFjaXR5OiAwOyBwb2ludGVyLWV2ZW50czogbm9uZTsgei1pbmRleDogLTE7J1xuXHQpO1xuXHRpZnJhbWUuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG5cdGlmcmFtZS50YWJJbmRleCA9IC0xO1xuXHRjb25zdCBjcm9zc29yaWdpbiA9IGlzX2Nyb3Nzb3JpZ2luKCk7XG5cblx0LyoqXG5cdCAqIEB0eXBlIHsoKSA9PiB2b2lkfVxuXHQgKi9cblx0bGV0IHVuc3Vic2NyaWJlO1xuXHRpZiAoY3Jvc3NvcmlnaW4pIHtcblx0XHRpZnJhbWUuc3JjID0gXCJkYXRhOnRleHQvaHRtbCw8c2NyaXB0Pm9ucmVzaXplPWZ1bmN0aW9uKCl7cGFyZW50LnBvc3RNZXNzYWdlKDAsJyonKX08L3NjcmlwdD5cIjtcblx0XHR1bnN1YnNjcmliZSA9IGxpc3Rlbihcblx0XHRcdHdpbmRvdyxcblx0XHRcdCdtZXNzYWdlJyxcblx0XHRcdC8qKiBAcGFyYW0ge01lc3NhZ2VFdmVudH0gZXZlbnQgKi8gKGV2ZW50KSA9PiB7XG5cdFx0XHRcdGlmIChldmVudC5zb3VyY2UgPT09IGlmcmFtZS5jb250ZW50V2luZG93KSBmbigpO1xuXHRcdFx0fVxuXHRcdCk7XG5cdH0gZWxzZSB7XG5cdFx0aWZyYW1lLnNyYyA9ICdhYm91dDpibGFuayc7XG5cdFx0aWZyYW1lLm9ubG9hZCA9ICgpID0+IHtcblx0XHRcdHVuc3Vic2NyaWJlID0gbGlzdGVuKGlmcmFtZS5jb250ZW50V2luZG93LCAncmVzaXplJywgZm4pO1xuXHRcdFx0Ly8gbWFrZSBzdXJlIGFuIGluaXRpYWwgcmVzaXplIGV2ZW50IGlzIGZpcmVkIF9hZnRlcl8gdGhlIGlmcmFtZSBpcyBsb2FkZWQgKHdoaWNoIGlzIGFzeW5jaHJvbm91cylcblx0XHRcdC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vc3ZlbHRlanMvc3ZlbHRlL2lzc3Vlcy80MjMzXG5cdFx0XHRmbigpO1xuXHRcdH07XG5cdH1cblx0YXBwZW5kKG5vZGUsIGlmcmFtZSk7XG5cdHJldHVybiAoKSA9PiB7XG5cdFx0aWYgKGNyb3Nzb3JpZ2luKSB7XG5cdFx0XHR1bnN1YnNjcmliZSgpO1xuXHRcdH0gZWxzZSBpZiAodW5zdWJzY3JpYmUgJiYgaWZyYW1lLmNvbnRlbnRXaW5kb3cpIHtcblx0XHRcdHVuc3Vic2NyaWJlKCk7XG5cdFx0fVxuXHRcdGRldGFjaChpZnJhbWUpO1xuXHR9O1xufVxuZXhwb3J0IGNvbnN0IHJlc2l6ZV9vYnNlcnZlcl9jb250ZW50X2JveCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgUmVzaXplT2JzZXJ2ZXJTaW5nbGV0b24oe1xuXHRib3g6ICdjb250ZW50LWJveCdcbn0pO1xuZXhwb3J0IGNvbnN0IHJlc2l6ZV9vYnNlcnZlcl9ib3JkZXJfYm94ID0gLyogQF9fUFVSRV9fICovIG5ldyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbih7XG5cdGJveDogJ2JvcmRlci1ib3gnXG59KTtcbmV4cG9ydCBjb25zdCByZXNpemVfb2JzZXJ2ZXJfZGV2aWNlX3BpeGVsX2NvbnRlbnRfYm94ID0gLyogQF9fUFVSRV9fICovIG5ldyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbihcblx0eyBib3g6ICdkZXZpY2UtcGl4ZWwtY29udGVudC1ib3gnIH1cbik7XG5leHBvcnQgeyBSZXNpemVPYnNlcnZlclNpbmdsZXRvbiB9O1xuXG4vKipcbiAqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvZ2dsZV9jbGFzcyhlbGVtZW50LCBuYW1lLCB0b2dnbGUpIHtcblx0Ly8gVGhlIGAhIWAgaXMgcmVxdWlyZWQgYmVjYXVzZSBhbiBgdW5kZWZpbmVkYCBmbGFnIG1lYW5zIGZsaXBwaW5nIHRoZSBjdXJyZW50IHN0YXRlLlxuXHRlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUobmFtZSwgISF0b2dnbGUpO1xufVxuXG4vKipcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogQHBhcmFtIHtUfSBbZGV0YWlsXVxuICogQHBhcmFtIHt7IGJ1YmJsZXM/OiBib29sZWFuLCBjYW5jZWxhYmxlPzogYm9vbGVhbiB9fSBbb3B0aW9uc11cbiAqIEByZXR1cm5zIHtDdXN0b21FdmVudDxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1c3RvbV9ldmVudCh0eXBlLCBkZXRhaWwsIHsgYnViYmxlcyA9IGZhbHNlLCBjYW5jZWxhYmxlID0gZmFsc2UgfSA9IHt9KSB7XG5cdHJldHVybiBuZXcgQ3VzdG9tRXZlbnQodHlwZSwgeyBkZXRhaWwsIGJ1YmJsZXMsIGNhbmNlbGFibGUgfSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwYXJlbnRcbiAqIEByZXR1cm5zIHtDaGlsZE5vZGVBcnJheX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1ZXJ5X3NlbGVjdG9yX2FsbChzZWxlY3RvciwgcGFyZW50ID0gZG9jdW1lbnQuYm9keSkge1xuXHRyZXR1cm4gQXJyYXkuZnJvbShwYXJlbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBub2RlSWRcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGhlYWRcbiAqIEByZXR1cm5zIHthbnlbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhlYWRfc2VsZWN0b3Iobm9kZUlkLCBoZWFkKSB7XG5cdGNvbnN0IHJlc3VsdCA9IFtdO1xuXHRsZXQgc3RhcnRlZCA9IDA7XG5cdGZvciAoY29uc3Qgbm9kZSBvZiBoZWFkLmNoaWxkTm9kZXMpIHtcblx0XHRpZiAobm9kZS5ub2RlVHlwZSA9PT0gOCAvKiBjb21tZW50IG5vZGUgKi8pIHtcblx0XHRcdGNvbnN0IGNvbW1lbnQgPSBub2RlLnRleHRDb250ZW50LnRyaW0oKTtcblx0XHRcdGlmIChjb21tZW50ID09PSBgSEVBRF8ke25vZGVJZH1fRU5EYCkge1xuXHRcdFx0XHRzdGFydGVkIC09IDE7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKG5vZGUpO1xuXHRcdFx0fSBlbHNlIGlmIChjb21tZW50ID09PSBgSEVBRF8ke25vZGVJZH1fU1RBUlRgKSB7XG5cdFx0XHRcdHN0YXJ0ZWQgKz0gMTtcblx0XHRcdFx0cmVzdWx0LnB1c2gobm9kZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChzdGFydGVkID4gMCkge1xuXHRcdFx0cmVzdWx0LnB1c2gobm9kZSk7XG5cdFx0fVxuXHR9XG5cdHJldHVybiByZXN1bHQ7XG59XG4vKiogKi9cbmV4cG9ydCBjbGFzcyBIdG1sVGFnIHtcblx0LyoqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBkZWZhdWx0IGZhbHNlXG5cdCAqL1xuXHRpc19zdmcgPSBmYWxzZTtcblx0LyoqIHBhcmVudCBmb3IgY3JlYXRpbmcgbm9kZSAqL1xuXHRlID0gdW5kZWZpbmVkO1xuXHQvKiogaHRtbCB0YWcgbm9kZXMgKi9cblx0biA9IHVuZGVmaW5lZDtcblx0LyoqIHRhcmdldCAqL1xuXHR0ID0gdW5kZWZpbmVkO1xuXHQvKiogYW5jaG9yICovXG5cdGEgPSB1bmRlZmluZWQ7XG5cdGNvbnN0cnVjdG9yKGlzX3N2ZyA9IGZhbHNlKSB7XG5cdFx0dGhpcy5pc19zdmcgPSBpc19zdmc7XG5cdFx0dGhpcy5lID0gdGhpcy5uID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaHRtbFxuXHQgKiBAcmV0dXJucyB7dm9pZH1cblx0ICovXG5cdGMoaHRtbCkge1xuXHRcdHRoaXMuaChodG1sKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaHRtbFxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50IHwgU1ZHRWxlbWVudH0gdGFyZ2V0XG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnQgfCBTVkdFbGVtZW50fSBhbmNob3Jcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRtKGh0bWwsIHRhcmdldCwgYW5jaG9yID0gbnVsbCkge1xuXHRcdGlmICghdGhpcy5lKSB7XG5cdFx0XHRpZiAodGhpcy5pc19zdmcpXG5cdFx0XHRcdHRoaXMuZSA9IHN2Z19lbGVtZW50KC8qKiBAdHlwZSB7a2V5b2YgU1ZHRWxlbWVudFRhZ05hbWVNYXB9ICovICh0YXJnZXQubm9kZU5hbWUpKTtcblx0XHRcdC8qKiAjNzM2NCAgdGFyZ2V0IGZvciA8dGVtcGxhdGU+IG1heSBiZSBwcm92aWRlZCBhcyAjZG9jdW1lbnQtZnJhZ21lbnQoMTEpICovIGVsc2Vcblx0XHRcdFx0dGhpcy5lID0gZWxlbWVudChcblx0XHRcdFx0XHQvKiogQHR5cGUge2tleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcH0gKi8gKFxuXHRcdFx0XHRcdFx0dGFyZ2V0Lm5vZGVUeXBlID09PSAxMSA/ICdURU1QTEFURScgOiB0YXJnZXQubm9kZU5hbWVcblx0XHRcdFx0XHQpXG5cdFx0XHRcdCk7XG5cdFx0XHR0aGlzLnQgPVxuXHRcdFx0XHR0YXJnZXQudGFnTmFtZSAhPT0gJ1RFTVBMQVRFJ1xuXHRcdFx0XHRcdD8gdGFyZ2V0XG5cdFx0XHRcdFx0OiAvKiogQHR5cGUge0hUTUxUZW1wbGF0ZUVsZW1lbnR9ICovICh0YXJnZXQpLmNvbnRlbnQ7XG5cdFx0XHR0aGlzLmMoaHRtbCk7XG5cdFx0fVxuXHRcdHRoaXMuaShhbmNob3IpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0aChodG1sKSB7XG5cdFx0dGhpcy5lLmlubmVySFRNTCA9IGh0bWw7XG5cdFx0dGhpcy5uID0gQXJyYXkuZnJvbShcblx0XHRcdHRoaXMuZS5ub2RlTmFtZSA9PT0gJ1RFTVBMQVRFJyA/IHRoaXMuZS5jb250ZW50LmNoaWxkTm9kZXMgOiB0aGlzLmUuY2hpbGROb2Rlc1xuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGkoYW5jaG9yKSB7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm4ubGVuZ3RoOyBpICs9IDEpIHtcblx0XHRcdGluc2VydCh0aGlzLnQsIHRoaXMubltpXSwgYW5jaG9yKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtzdHJpbmd9IGh0bWxcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRwKGh0bWwpIHtcblx0XHR0aGlzLmQoKTtcblx0XHR0aGlzLmgoaHRtbCk7XG5cdFx0dGhpcy5pKHRoaXMuYSk7XG5cdH1cblxuXHQvKipcblx0ICogQHJldHVybnMge3ZvaWR9ICovXG5cdGQoKSB7XG5cdFx0dGhpcy5uLmZvckVhY2goZGV0YWNoKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgSHRtbFRhZ0h5ZHJhdGlvbiBleHRlbmRzIEh0bWxUYWcge1xuXHQvKiogQHR5cGUge0VsZW1lbnRbXX0gaHlkcmF0aW9uIGNsYWltZWQgbm9kZXMgKi9cblx0bCA9IHVuZGVmaW5lZDtcblxuXHRjb25zdHJ1Y3Rvcihpc19zdmcgPSBmYWxzZSwgY2xhaW1lZF9ub2Rlcykge1xuXHRcdHN1cGVyKGlzX3N2Zyk7XG5cdFx0dGhpcy5lID0gdGhpcy5uID0gbnVsbDtcblx0XHR0aGlzLmwgPSBjbGFpbWVkX25vZGVzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBodG1sXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0YyhodG1sKSB7XG5cdFx0aWYgKHRoaXMubCkge1xuXHRcdFx0dGhpcy5uID0gdGhpcy5sO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzdXBlci5jKGh0bWwpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAcmV0dXJucyB7dm9pZH0gKi9cblx0aShhbmNob3IpIHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubi5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdFx0aW5zZXJ0X2h5ZHJhdGlvbih0aGlzLnQsIHRoaXMubltpXSwgYW5jaG9yKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05hbWVkTm9kZU1hcH0gYXR0cmlidXRlc1xuICogQHJldHVybnMge3t9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXR0cmlidXRlX3RvX29iamVjdChhdHRyaWJ1dGVzKSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiBhdHRyaWJ1dGVzKSB7XG5cdFx0cmVzdWx0W2F0dHJpYnV0ZS5uYW1lXSA9IGF0dHJpYnV0ZS52YWx1ZTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG5jb25zdCBlc2NhcGVkID0ge1xuXHQnXCInOiAnJnF1b3Q7Jyxcblx0JyYnOiAnJmFtcDsnLFxuXHQnPCc6ICcmbHQ7J1xufTtcblxuY29uc3QgcmVnZXhfYXR0cmlidXRlX2NoYXJhY3RlcnNfdG9fZXNjYXBlID0gL1tcIiY8XS9nO1xuXG4vKipcbiAqIE5vdGUgdGhhdCB0aGUgYXR0cmlidXRlIGl0c2VsZiBzaG91bGQgYmUgc3Vycm91bmRlZCBpbiBkb3VibGUgcXVvdGVzXG4gKiBAcGFyYW0ge2FueX0gYXR0cmlidXRlXG4gKi9cbmZ1bmN0aW9uIGVzY2FwZV9hdHRyaWJ1dGUoYXR0cmlidXRlKSB7XG5cdHJldHVybiBTdHJpbmcoYXR0cmlidXRlKS5yZXBsYWNlKHJlZ2V4X2F0dHJpYnV0ZV9jaGFyYWN0ZXJzX3RvX2VzY2FwZSwgKG1hdGNoKSA9PiBlc2NhcGVkW21hdGNoXSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+fSBhdHRyaWJ1dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpbmdpZnlfc3ByZWFkKGF0dHJpYnV0ZXMpIHtcblx0bGV0IHN0ciA9ICcgJztcblx0Zm9yIChjb25zdCBrZXkgaW4gYXR0cmlidXRlcykge1xuXHRcdGlmIChhdHRyaWJ1dGVzW2tleV0gIT0gbnVsbCkge1xuXHRcdFx0c3RyICs9IGAke2tleX09XCIke2VzY2FwZV9hdHRyaWJ1dGUoYXR0cmlidXRlc1trZXldKX1cIiBgO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBzdHI7XG59XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge3t9fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0X2N1c3RvbV9lbGVtZW50c19zbG90cyhlbGVtZW50KSB7XG5cdGNvbnN0IHJlc3VsdCA9IHt9O1xuXHRlbGVtZW50LmNoaWxkTm9kZXMuZm9yRWFjaChcblx0XHQvKiogQHBhcmFtIHtFbGVtZW50fSBub2RlICovIChub2RlKSA9PiB7XG5cdFx0XHRyZXN1bHRbbm9kZS5zbG90IHx8ICdkZWZhdWx0J10gPSB0cnVlO1xuXHRcdH1cblx0KTtcblx0cmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN0cnVjdF9zdmVsdGVfY29tcG9uZW50KGNvbXBvbmVudCwgcHJvcHMpIHtcblx0cmV0dXJuIG5ldyBjb21wb25lbnQocHJvcHMpO1xufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtOb2RlICYge1xuICogXHRjbGFpbV9vcmRlcj86IG51bWJlcjtcbiAqIFx0aHlkcmF0ZV9pbml0PzogdHJ1ZTtcbiAqIFx0YWN0dWFsX2VuZF9jaGlsZD86IE5vZGVFeDtcbiAqIFx0Y2hpbGROb2RlczogTm9kZUxpc3RPZjxOb2RlRXg+O1xuICogfX0gTm9kZUV4XG4gKi9cblxuLyoqIEB0eXBlZGVmIHtDaGlsZE5vZGUgJiBOb2RlRXh9IENoaWxkTm9kZUV4ICovXG5cbi8qKiBAdHlwZWRlZiB7Tm9kZUV4ICYgeyBjbGFpbV9vcmRlcjogbnVtYmVyIH19IE5vZGVFeDIgKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7Q2hpbGROb2RlRXhbXSAmIHtcbiAqIFx0Y2xhaW1faW5mbz86IHtcbiAqIFx0XHRsYXN0X2luZGV4OiBudW1iZXI7XG4gKiBcdFx0dG90YWxfY2xhaW1lZDogbnVtYmVyO1xuICogXHR9O1xuICogfX0gQ2hpbGROb2RlQXJyYXlcbiAqL1xuIiwgImltcG9ydCB7IGN1c3RvbV9ldmVudCB9IGZyb20gJy4vZG9tLmpzJztcblxuZXhwb3J0IGxldCBjdXJyZW50X2NvbXBvbmVudDtcblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldF9jdXJyZW50X2NvbXBvbmVudChjb21wb25lbnQpIHtcblx0Y3VycmVudF9jb21wb25lbnQgPSBjb21wb25lbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRfY3VycmVudF9jb21wb25lbnQoKSB7XG5cdGlmICghY3VycmVudF9jb21wb25lbnQpIHRocm93IG5ldyBFcnJvcignRnVuY3Rpb24gY2FsbGVkIG91dHNpZGUgY29tcG9uZW50IGluaXRpYWxpemF0aW9uJyk7XG5cdHJldHVybiBjdXJyZW50X2NvbXBvbmVudDtcbn1cblxuLyoqXG4gKiBTY2hlZHVsZXMgYSBjYWxsYmFjayB0byBydW4gaW1tZWRpYXRlbHkgYmVmb3JlIHRoZSBjb21wb25lbnQgaXMgdXBkYXRlZCBhZnRlciBhbnkgc3RhdGUgY2hhbmdlLlxuICpcbiAqIFRoZSBmaXJzdCB0aW1lIHRoZSBjYWxsYmFjayBydW5zIHdpbGwgYmUgYmVmb3JlIHRoZSBpbml0aWFsIGBvbk1vdW50YFxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNiZWZvcmV1cGRhdGVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiZWZvcmVVcGRhdGUoZm4pIHtcblx0Z2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuYmVmb3JlX3VwZGF0ZS5wdXNoKGZuKTtcbn1cblxuLyoqXG4gKiBUaGUgYG9uTW91bnRgIGZ1bmN0aW9uIHNjaGVkdWxlcyBhIGNhbGxiYWNrIHRvIHJ1biBhcyBzb29uIGFzIHRoZSBjb21wb25lbnQgaGFzIGJlZW4gbW91bnRlZCB0byB0aGUgRE9NLlxuICogSXQgbXVzdCBiZSBjYWxsZWQgZHVyaW5nIHRoZSBjb21wb25lbnQncyBpbml0aWFsaXNhdGlvbiAoYnV0IGRvZXNuJ3QgbmVlZCB0byBsaXZlICppbnNpZGUqIHRoZSBjb21wb25lbnQ7XG4gKiBpdCBjYW4gYmUgY2FsbGVkIGZyb20gYW4gZXh0ZXJuYWwgbW9kdWxlKS5cbiAqXG4gKiBJZiBhIGZ1bmN0aW9uIGlzIHJldHVybmVkIF9zeW5jaHJvbm91c2x5XyBmcm9tIGBvbk1vdW50YCwgaXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgY29tcG9uZW50IGlzIHVubW91bnRlZC5cbiAqXG4gKiBgb25Nb3VudGAgZG9lcyBub3QgcnVuIGluc2lkZSBhIFtzZXJ2ZXItc2lkZSBjb21wb25lbnRdKGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzI3J1bi10aW1lLXNlcnZlci1zaWRlLWNvbXBvbmVudC1hcGkpLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNvbm1vdW50XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHsoKSA9PiBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLk5vdEZ1bmN0aW9uPFQ+IHwgUHJvbWlzZTxpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLk5vdEZ1bmN0aW9uPFQ+PiB8ICgoKSA9PiBhbnkpfSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbk1vdW50KGZuKSB7XG5cdGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLm9uX21vdW50LnB1c2goZm4pO1xufVxuXG4vKipcbiAqIFNjaGVkdWxlcyBhIGNhbGxiYWNrIHRvIHJ1biBpbW1lZGlhdGVseSBhZnRlciB0aGUgY29tcG9uZW50IGhhcyBiZWVuIHVwZGF0ZWQuXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIHJ1bnMgd2lsbCBiZSBhZnRlciB0aGUgaW5pdGlhbCBgb25Nb3VudGBcbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUjYWZ0ZXJ1cGRhdGVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlclVwZGF0ZShmbikge1xuXHRnZXRfY3VycmVudF9jb21wb25lbnQoKS4kJC5hZnRlcl91cGRhdGUucHVzaChmbik7XG59XG5cbi8qKlxuICogU2NoZWR1bGVzIGEgY2FsbGJhY2sgdG8gcnVuIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgY29tcG9uZW50IGlzIHVubW91bnRlZC5cbiAqXG4gKiBPdXQgb2YgYG9uTW91bnRgLCBgYmVmb3JlVXBkYXRlYCwgYGFmdGVyVXBkYXRlYCBhbmQgYG9uRGVzdHJveWAsIHRoaXMgaXMgdGhlXG4gKiBvbmx5IG9uZSB0aGF0IHJ1bnMgaW5zaWRlIGEgc2VydmVyLXNpZGUgY29tcG9uZW50LlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNvbmRlc3Ryb3lcbiAqIEBwYXJhbSB7KCkgPT4gYW55fSBmblxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkRlc3Ryb3koZm4pIHtcblx0Z2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQub25fZGVzdHJveS5wdXNoKGZuKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGV2ZW50IGRpc3BhdGNoZXIgdGhhdCBjYW4gYmUgdXNlZCB0byBkaXNwYXRjaCBbY29tcG9uZW50IGV2ZW50c10oaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3MjdGVtcGxhdGUtc3ludGF4LWNvbXBvbmVudC1kaXJlY3RpdmVzLW9uLWV2ZW50bmFtZSkuXG4gKiBFdmVudCBkaXNwYXRjaGVycyBhcmUgZnVuY3Rpb25zIHRoYXQgY2FuIHRha2UgdHdvIGFyZ3VtZW50czogYG5hbWVgIGFuZCBgZGV0YWlsYC5cbiAqXG4gKiBDb21wb25lbnQgZXZlbnRzIGNyZWF0ZWQgd2l0aCBgY3JlYXRlRXZlbnREaXNwYXRjaGVyYCBjcmVhdGUgYVxuICogW0N1c3RvbUV2ZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ3VzdG9tRXZlbnQpLlxuICogVGhlc2UgZXZlbnRzIGRvIG5vdCBbYnViYmxlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL0xlYXJuL0phdmFTY3JpcHQvQnVpbGRpbmdfYmxvY2tzL0V2ZW50cyNFdmVudF9idWJibGluZ19hbmRfY2FwdHVyZSkuXG4gKiBUaGUgYGRldGFpbGAgYXJndW1lbnQgY29ycmVzcG9uZHMgdG8gdGhlIFtDdXN0b21FdmVudC5kZXRhaWxdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9DdXN0b21FdmVudC9kZXRhaWwpXG4gKiBwcm9wZXJ0eSBhbmQgY2FuIGNvbnRhaW4gYW55IHR5cGUgb2YgZGF0YS5cbiAqXG4gKiBUaGUgZXZlbnQgZGlzcGF0Y2hlciBjYW4gYmUgdHlwZWQgdG8gbmFycm93IHRoZSBhbGxvd2VkIGV2ZW50IG5hbWVzIGFuZCB0aGUgdHlwZSBvZiB0aGUgYGRldGFpbGAgYXJndW1lbnQ6XG4gKiBgYGB0c1xuICogY29uc3QgZGlzcGF0Y2ggPSBjcmVhdGVFdmVudERpc3BhdGNoZXI8e1xuICogIGxvYWRlZDogbmV2ZXI7IC8vIGRvZXMgbm90IHRha2UgYSBkZXRhaWwgYXJndW1lbnRcbiAqICBjaGFuZ2U6IHN0cmluZzsgLy8gdGFrZXMgYSBkZXRhaWwgYXJndW1lbnQgb2YgdHlwZSBzdHJpbmcsIHdoaWNoIGlzIHJlcXVpcmVkXG4gKiAgb3B0aW9uYWw6IG51bWJlciB8IG51bGw7IC8vIHRha2VzIGFuIG9wdGlvbmFsIGRldGFpbCBhcmd1bWVudCBvZiB0eXBlIG51bWJlclxuICogfT4oKTtcbiAqIGBgYFxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNjcmVhdGVldmVudGRpc3BhdGNoZXJcbiAqIEB0ZW1wbGF0ZSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW0V2ZW50TWFwPWFueV1cbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuRXZlbnREaXNwYXRjaGVyPEV2ZW50TWFwPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUV2ZW50RGlzcGF0Y2hlcigpIHtcblx0Y29uc3QgY29tcG9uZW50ID0gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCk7XG5cdHJldHVybiAodHlwZSwgZGV0YWlsLCB7IGNhbmNlbGFibGUgPSBmYWxzZSB9ID0ge30pID0+IHtcblx0XHRjb25zdCBjYWxsYmFja3MgPSBjb21wb25lbnQuJCQuY2FsbGJhY2tzW3R5cGVdO1xuXHRcdGlmIChjYWxsYmFja3MpIHtcblx0XHRcdC8vIFRPRE8gYXJlIHRoZXJlIHNpdHVhdGlvbnMgd2hlcmUgZXZlbnRzIGNvdWxkIGJlIGRpc3BhdGNoZWRcblx0XHRcdC8vIGluIGEgc2VydmVyIChub24tRE9NKSBlbnZpcm9ubWVudD9cblx0XHRcdGNvbnN0IGV2ZW50ID0gY3VzdG9tX2V2ZW50KC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodHlwZSksIGRldGFpbCwgeyBjYW5jZWxhYmxlIH0pO1xuXHRcdFx0Y2FsbGJhY2tzLnNsaWNlKCkuZm9yRWFjaCgoZm4pID0+IHtcblx0XHRcdFx0Zm4uY2FsbChjb21wb25lbnQsIGV2ZW50KTtcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuICFldmVudC5kZWZhdWx0UHJldmVudGVkO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcbn1cblxuLyoqXG4gKiBBc3NvY2lhdGVzIGFuIGFyYml0cmFyeSBgY29udGV4dGAgb2JqZWN0IHdpdGggdGhlIGN1cnJlbnQgY29tcG9uZW50IGFuZCB0aGUgc3BlY2lmaWVkIGBrZXlgXG4gKiBhbmQgcmV0dXJucyB0aGF0IG9iamVjdC4gVGhlIGNvbnRleHQgaXMgdGhlbiBhdmFpbGFibGUgdG8gY2hpbGRyZW4gb2YgdGhlIGNvbXBvbmVudFxuICogKGluY2x1ZGluZyBzbG90dGVkIGNvbnRlbnQpIHdpdGggYGdldENvbnRleHRgLlxuICpcbiAqIExpa2UgbGlmZWN5Y2xlIGZ1bmN0aW9ucywgdGhpcyBtdXN0IGJlIGNhbGxlZCBkdXJpbmcgY29tcG9uZW50IGluaXRpYWxpc2F0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNzZXRjb250ZXh0XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHBhcmFtIHtUfSBjb250ZXh0XG4gKiBAcmV0dXJucyB7VH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldENvbnRleHQoa2V5LCBjb250ZXh0KSB7XG5cdGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLmNvbnRleHQuc2V0KGtleSwgY29udGV4dCk7XG5cdHJldHVybiBjb250ZXh0O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgY29udGV4dCB0aGF0IGJlbG9uZ3MgdG8gdGhlIGNsb3Nlc3QgcGFyZW50IGNvbXBvbmVudCB3aXRoIHRoZSBzcGVjaWZpZWQgYGtleWAuXG4gKiBNdXN0IGJlIGNhbGxlZCBkdXJpbmcgY29tcG9uZW50IGluaXRpYWxpc2F0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNnZXRjb250ZXh0XG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHJldHVybnMge1R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250ZXh0KGtleSkge1xuXHRyZXR1cm4gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuY29udGV4dC5nZXQoa2V5KTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIHdob2xlIGNvbnRleHQgbWFwIHRoYXQgYmVsb25ncyB0byB0aGUgY2xvc2VzdCBwYXJlbnQgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgZHVyaW5nIGNvbXBvbmVudCBpbml0aWFsaXNhdGlvbi4gVXNlZnVsLCBmb3IgZXhhbXBsZSwgaWYgeW91XG4gKiBwcm9ncmFtbWF0aWNhbGx5IGNyZWF0ZSBhIGNvbXBvbmVudCBhbmQgd2FudCB0byBwYXNzIHRoZSBleGlzdGluZyBjb250ZXh0IHRvIGl0LlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZSNnZXRhbGxjb250ZXh0c1xuICogQHRlbXBsYXRlIHtNYXA8YW55LCBhbnk+fSBbVD1NYXA8YW55LCBhbnk+XVxuICogQHJldHVybnMge1R9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbGxDb250ZXh0cygpIHtcblx0cmV0dXJuIGdldF9jdXJyZW50X2NvbXBvbmVudCgpLiQkLmNvbnRleHQ7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBnaXZlbiBga2V5YCBoYXMgYmVlbiBzZXQgaW4gdGhlIGNvbnRleHQgb2YgYSBwYXJlbnQgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgZHVyaW5nIGNvbXBvbmVudCBpbml0aWFsaXNhdGlvbi5cbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUjaGFzY29udGV4dFxuICogQHBhcmFtIHthbnl9IGtleVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNDb250ZXh0KGtleSkge1xuXHRyZXR1cm4gZ2V0X2N1cnJlbnRfY29tcG9uZW50KCkuJCQuY29udGV4dC5oYXMoa2V5KTtcbn1cblxuLy8gVE9ETyBmaWd1cmUgb3V0IGlmIHdlIHN0aWxsIHdhbnQgdG8gc3VwcG9ydFxuLy8gc2hvcnRoYW5kIGV2ZW50cywgb3IgaWYgd2Ugd2FudCB0byBpbXBsZW1lbnRcbi8vIGEgcmVhbCBidWJibGluZyBtZWNoYW5pc21cbi8qKlxuICogQHBhcmFtIGNvbXBvbmVudFxuICogQHBhcmFtIGV2ZW50XG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1YmJsZShjb21wb25lbnQsIGV2ZW50KSB7XG5cdGNvbnN0IGNhbGxiYWNrcyA9IGNvbXBvbmVudC4kJC5jYWxsYmFja3NbZXZlbnQudHlwZV07XG5cdGlmIChjYWxsYmFja3MpIHtcblx0XHQvLyBAdHMtaWdub3JlXG5cdFx0Y2FsbGJhY2tzLnNsaWNlKCkuZm9yRWFjaCgoZm4pID0+IGZuLmNhbGwodGhpcywgZXZlbnQpKTtcblx0fVxufVxuIiwgImltcG9ydCB7IHJ1bl9hbGwgfSBmcm9tICcuL3V0aWxzLmpzJztcbmltcG9ydCB7IGN1cnJlbnRfY29tcG9uZW50LCBzZXRfY3VycmVudF9jb21wb25lbnQgfSBmcm9tICcuL2xpZmVjeWNsZS5qcyc7XG5cbmV4cG9ydCBjb25zdCBkaXJ0eV9jb21wb25lbnRzID0gW107XG5leHBvcnQgY29uc3QgaW50cm9zID0geyBlbmFibGVkOiBmYWxzZSB9O1xuZXhwb3J0IGNvbnN0IGJpbmRpbmdfY2FsbGJhY2tzID0gW107XG5cbmxldCByZW5kZXJfY2FsbGJhY2tzID0gW107XG5cbmNvbnN0IGZsdXNoX2NhbGxiYWNrcyA9IFtdO1xuXG5jb25zdCByZXNvbHZlZF9wcm9taXNlID0gLyogQF9fUFVSRV9fICovIFByb21pc2UucmVzb2x2ZSgpO1xuXG5sZXQgdXBkYXRlX3NjaGVkdWxlZCA9IGZhbHNlO1xuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gc2NoZWR1bGVfdXBkYXRlKCkge1xuXHRpZiAoIXVwZGF0ZV9zY2hlZHVsZWQpIHtcblx0XHR1cGRhdGVfc2NoZWR1bGVkID0gdHJ1ZTtcblx0XHRyZXNvbHZlZF9wcm9taXNlLnRoZW4oZmx1c2gpO1xuXHR9XG59XG5cbi8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWNrKCkge1xuXHRzY2hlZHVsZV91cGRhdGUoKTtcblx0cmV0dXJuIHJlc29sdmVkX3Byb21pc2U7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfcmVuZGVyX2NhbGxiYWNrKGZuKSB7XG5cdHJlbmRlcl9jYWxsYmFja3MucHVzaChmbik7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRfZmx1c2hfY2FsbGJhY2soZm4pIHtcblx0Zmx1c2hfY2FsbGJhY2tzLnB1c2goZm4pO1xufVxuXG4vLyBmbHVzaCgpIGNhbGxzIGNhbGxiYWNrcyBpbiB0aGlzIG9yZGVyOlxuLy8gMS4gQWxsIGJlZm9yZVVwZGF0ZSBjYWxsYmFja3MsIGluIG9yZGVyOiBwYXJlbnRzIGJlZm9yZSBjaGlsZHJlblxuLy8gMi4gQWxsIGJpbmQ6dGhpcyBjYWxsYmFja3MsIGluIHJldmVyc2Ugb3JkZXI6IGNoaWxkcmVuIGJlZm9yZSBwYXJlbnRzLlxuLy8gMy4gQWxsIGFmdGVyVXBkYXRlIGNhbGxiYWNrcywgaW4gb3JkZXI6IHBhcmVudHMgYmVmb3JlIGNoaWxkcmVuLiBFWENFUFRcbi8vICAgIGZvciBhZnRlclVwZGF0ZXMgY2FsbGVkIGR1cmluZyB0aGUgaW5pdGlhbCBvbk1vdW50LCB3aGljaCBhcmUgY2FsbGVkIGluXG4vLyAgICByZXZlcnNlIG9yZGVyOiBjaGlsZHJlbiBiZWZvcmUgcGFyZW50cy5cbi8vIFNpbmNlIGNhbGxiYWNrcyBtaWdodCB1cGRhdGUgY29tcG9uZW50IHZhbHVlcywgd2hpY2ggY291bGQgdHJpZ2dlciBhbm90aGVyXG4vLyBjYWxsIHRvIGZsdXNoKCksIHRoZSBmb2xsb3dpbmcgc3RlcHMgZ3VhcmQgYWdhaW5zdCB0aGlzOlxuLy8gMS4gRHVyaW5nIGJlZm9yZVVwZGF0ZSwgYW55IHVwZGF0ZWQgY29tcG9uZW50cyB3aWxsIGJlIGFkZGVkIHRvIHRoZVxuLy8gICAgZGlydHlfY29tcG9uZW50cyBhcnJheSBhbmQgd2lsbCBjYXVzZSBhIHJlZW50cmFudCBjYWxsIHRvIGZsdXNoKCkuIEJlY2F1c2Vcbi8vICAgIHRoZSBmbHVzaCBpbmRleCBpcyBrZXB0IG91dHNpZGUgdGhlIGZ1bmN0aW9uLCB0aGUgcmVlbnRyYW50IGNhbGwgd2lsbCBwaWNrXG4vLyAgICB1cCB3aGVyZSB0aGUgZWFybGllciBjYWxsIGxlZnQgb2ZmIGFuZCBnbyB0aHJvdWdoIGFsbCBkaXJ0eSBjb21wb25lbnRzLiBUaGVcbi8vICAgIGN1cnJlbnRfY29tcG9uZW50IHZhbHVlIGlzIHNhdmVkIGFuZCByZXN0b3JlZCBzbyB0aGF0IHRoZSByZWVudHJhbnQgY2FsbCB3aWxsXG4vLyAgICBub3QgaW50ZXJmZXJlIHdpdGggdGhlIFwicGFyZW50XCIgZmx1c2goKSBjYWxsLlxuLy8gMi4gYmluZDp0aGlzIGNhbGxiYWNrcyBjYW5ub3QgdHJpZ2dlciBuZXcgZmx1c2goKSBjYWxscy5cbi8vIDMuIER1cmluZyBhZnRlclVwZGF0ZSwgYW55IHVwZGF0ZWQgY29tcG9uZW50cyB3aWxsIE5PVCBoYXZlIHRoZWlyIGFmdGVyVXBkYXRlXG4vLyAgICBjYWxsYmFjayBjYWxsZWQgYSBzZWNvbmQgdGltZTsgdGhlIHNlZW5fY2FsbGJhY2tzIHNldCwgb3V0c2lkZSB0aGUgZmx1c2goKVxuLy8gICAgZnVuY3Rpb24sIGd1YXJhbnRlZXMgdGhpcyBiZWhhdmlvci5cbmNvbnN0IHNlZW5fY2FsbGJhY2tzID0gbmV3IFNldCgpO1xuXG5sZXQgZmx1c2hpZHggPSAwOyAvLyBEbyAqbm90KiBtb3ZlIHRoaXMgaW5zaWRlIHRoZSBmbHVzaCgpIGZ1bmN0aW9uXG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaCgpIHtcblx0Ly8gRG8gbm90IHJlZW50ZXIgZmx1c2ggd2hpbGUgZGlydHkgY29tcG9uZW50cyBhcmUgdXBkYXRlZCwgYXMgdGhpcyBjYW5cblx0Ly8gcmVzdWx0IGluIGFuIGluZmluaXRlIGxvb3AuIEluc3RlYWQsIGxldCB0aGUgaW5uZXIgZmx1c2ggaGFuZGxlIGl0LlxuXHQvLyBSZWVudHJhbmN5IGlzIG9rIGFmdGVyd2FyZHMgZm9yIGJpbmRpbmdzIGV0Yy5cblx0aWYgKGZsdXNoaWR4ICE9PSAwKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHNhdmVkX2NvbXBvbmVudCA9IGN1cnJlbnRfY29tcG9uZW50O1xuXHRkbyB7XG5cdFx0Ly8gZmlyc3QsIGNhbGwgYmVmb3JlVXBkYXRlIGZ1bmN0aW9uc1xuXHRcdC8vIGFuZCB1cGRhdGUgY29tcG9uZW50c1xuXHRcdHRyeSB7XG5cdFx0XHR3aGlsZSAoZmx1c2hpZHggPCBkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCkge1xuXHRcdFx0XHRjb25zdCBjb21wb25lbnQgPSBkaXJ0eV9jb21wb25lbnRzW2ZsdXNoaWR4XTtcblx0XHRcdFx0Zmx1c2hpZHgrKztcblx0XHRcdFx0c2V0X2N1cnJlbnRfY29tcG9uZW50KGNvbXBvbmVudCk7XG5cdFx0XHRcdHVwZGF0ZShjb21wb25lbnQuJCQpO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdC8vIHJlc2V0IGRpcnR5IHN0YXRlIHRvIG5vdCBlbmQgdXAgaW4gYSBkZWFkbG9ja2VkIHN0YXRlIGFuZCB0aGVuIHJldGhyb3dcblx0XHRcdGRpcnR5X2NvbXBvbmVudHMubGVuZ3RoID0gMDtcblx0XHRcdGZsdXNoaWR4ID0gMDtcblx0XHRcdHRocm93IGU7XG5cdFx0fVxuXHRcdHNldF9jdXJyZW50X2NvbXBvbmVudChudWxsKTtcblx0XHRkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCA9IDA7XG5cdFx0Zmx1c2hpZHggPSAwO1xuXHRcdHdoaWxlIChiaW5kaW5nX2NhbGxiYWNrcy5sZW5ndGgpIGJpbmRpbmdfY2FsbGJhY2tzLnBvcCgpKCk7XG5cdFx0Ly8gdGhlbiwgb25jZSBjb21wb25lbnRzIGFyZSB1cGRhdGVkLCBjYWxsXG5cdFx0Ly8gYWZ0ZXJVcGRhdGUgZnVuY3Rpb25zLiBUaGlzIG1heSBjYXVzZVxuXHRcdC8vIHN1YnNlcXVlbnQgdXBkYXRlcy4uLlxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcmVuZGVyX2NhbGxiYWNrcy5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdFx0Y29uc3QgY2FsbGJhY2sgPSByZW5kZXJfY2FsbGJhY2tzW2ldO1xuXHRcdFx0aWYgKCFzZWVuX2NhbGxiYWNrcy5oYXMoY2FsbGJhY2spKSB7XG5cdFx0XHRcdC8vIC4uLnNvIGd1YXJkIGFnYWluc3QgaW5maW5pdGUgbG9vcHNcblx0XHRcdFx0c2Vlbl9jYWxsYmFja3MuYWRkKGNhbGxiYWNrKTtcblx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVuZGVyX2NhbGxiYWNrcy5sZW5ndGggPSAwO1xuXHR9IHdoaWxlIChkaXJ0eV9jb21wb25lbnRzLmxlbmd0aCk7XG5cdHdoaWxlIChmbHVzaF9jYWxsYmFja3MubGVuZ3RoKSB7XG5cdFx0Zmx1c2hfY2FsbGJhY2tzLnBvcCgpKCk7XG5cdH1cblx0dXBkYXRlX3NjaGVkdWxlZCA9IGZhbHNlO1xuXHRzZWVuX2NhbGxiYWNrcy5jbGVhcigpO1xuXHRzZXRfY3VycmVudF9jb21wb25lbnQoc2F2ZWRfY29tcG9uZW50KTtcbn1cblxuLyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuZnVuY3Rpb24gdXBkYXRlKCQkKSB7XG5cdGlmICgkJC5mcmFnbWVudCAhPT0gbnVsbCkge1xuXHRcdCQkLnVwZGF0ZSgpO1xuXHRcdHJ1bl9hbGwoJCQuYmVmb3JlX3VwZGF0ZSk7XG5cdFx0Y29uc3QgZGlydHkgPSAkJC5kaXJ0eTtcblx0XHQkJC5kaXJ0eSA9IFstMV07XG5cdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQucCgkJC5jdHgsIGRpcnR5KTtcblx0XHQkJC5hZnRlcl91cGRhdGUuZm9yRWFjaChhZGRfcmVuZGVyX2NhbGxiYWNrKTtcblx0fVxufVxuXG4vKipcbiAqIFVzZWZ1bCBmb3IgZXhhbXBsZSB0byBleGVjdXRlIHJlbWFpbmluZyBgYWZ0ZXJVcGRhdGVgIGNhbGxiYWNrcyBiZWZvcmUgZXhlY3V0aW5nIGBkZXN0cm95YC5cbiAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gZm5zXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsdXNoX3JlbmRlcl9jYWxsYmFja3MoZm5zKSB7XG5cdGNvbnN0IGZpbHRlcmVkID0gW107XG5cdGNvbnN0IHRhcmdldHMgPSBbXTtcblx0cmVuZGVyX2NhbGxiYWNrcy5mb3JFYWNoKChjKSA9PiAoZm5zLmluZGV4T2YoYykgPT09IC0xID8gZmlsdGVyZWQucHVzaChjKSA6IHRhcmdldHMucHVzaChjKSkpO1xuXHR0YXJnZXRzLmZvckVhY2goKGMpID0+IGMoKSk7XG5cdHJlbmRlcl9jYWxsYmFja3MgPSBmaWx0ZXJlZDtcbn1cbiIsICJpbXBvcnQgeyBpZGVudGl0eSBhcyBsaW5lYXIsIGlzX2Z1bmN0aW9uLCBub29wLCBydW5fYWxsIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyBub3cgfSBmcm9tICcuL2Vudmlyb25tZW50LmpzJztcbmltcG9ydCB7IGxvb3AgfSBmcm9tICcuL2xvb3AuanMnO1xuaW1wb3J0IHsgY3JlYXRlX3J1bGUsIGRlbGV0ZV9ydWxlIH0gZnJvbSAnLi9zdHlsZV9tYW5hZ2VyLmpzJztcbmltcG9ydCB7IGN1c3RvbV9ldmVudCB9IGZyb20gJy4vZG9tLmpzJztcbmltcG9ydCB7IGFkZF9yZW5kZXJfY2FsbGJhY2sgfSBmcm9tICcuL3NjaGVkdWxlci5qcyc7XG5cbi8qKlxuICogQHR5cGUge1Byb21pc2U8dm9pZD4gfCBudWxsfVxuICovXG5sZXQgcHJvbWlzZTtcblxuLyoqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZnVuY3Rpb24gd2FpdCgpIHtcblx0aWYgKCFwcm9taXNlKSB7XG5cdFx0cHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdHByb21pc2UudGhlbigoKSA9PiB7XG5cdFx0XHRwcm9taXNlID0gbnVsbDtcblx0XHR9KTtcblx0fVxuXHRyZXR1cm4gcHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IG5vZGVcbiAqIEBwYXJhbSB7SU5UUk8gfCBPVVRSTyB8IGJvb2xlYW59IGRpcmVjdGlvblxuICogQHBhcmFtIHsnc3RhcnQnIHwgJ2VuZCd9IGtpbmRcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBkaXNwYXRjaChub2RlLCBkaXJlY3Rpb24sIGtpbmQpIHtcblx0bm9kZS5kaXNwYXRjaEV2ZW50KGN1c3RvbV9ldmVudChgJHtkaXJlY3Rpb24gPyAnaW50cm8nIDogJ291dHJvJ30ke2tpbmR9YCkpO1xufVxuXG5jb25zdCBvdXRyb2luZyA9IG5ldyBTZXQoKTtcblxuLyoqXG4gKiBAdHlwZSB7T3V0cm99XG4gKi9cbmxldCBvdXRyb3M7XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBfb3V0cm9zKCkge1xuXHRvdXRyb3MgPSB7XG5cdFx0cjogMCxcblx0XHRjOiBbXSxcblx0XHRwOiBvdXRyb3MgLy8gcGFyZW50IGdyb3VwXG5cdH07XG59XG5cbi8qKlxuICogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tfb3V0cm9zKCkge1xuXHRpZiAoIW91dHJvcy5yKSB7XG5cdFx0cnVuX2FsbChvdXRyb3MuYyk7XG5cdH1cblx0b3V0cm9zID0gb3V0cm9zLnA7XG59XG5cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkZyYWdtZW50fSBibG9ja1xuICogQHBhcmFtIHswIHwgMX0gW2xvY2FsXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2l0aW9uX2luKGJsb2NrLCBsb2NhbCkge1xuXHRpZiAoYmxvY2sgJiYgYmxvY2suaSkge1xuXHRcdG91dHJvaW5nLmRlbGV0ZShibG9jayk7XG5cdFx0YmxvY2suaShsb2NhbCk7XG5cdH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wcml2YXRlLmpzJykuRnJhZ21lbnR9IGJsb2NrXG4gKiBAcGFyYW0gezAgfCAxfSBsb2NhbFxuICogQHBhcmFtIHswIHwgMX0gW2RldGFjaF1cbiAqIEBwYXJhbSB7KCkgPT4gdm9pZH0gW2NhbGxiYWNrXVxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2l0aW9uX291dChibG9jaywgbG9jYWwsIGRldGFjaCwgY2FsbGJhY2spIHtcblx0aWYgKGJsb2NrICYmIGJsb2NrLm8pIHtcblx0XHRpZiAob3V0cm9pbmcuaGFzKGJsb2NrKSkgcmV0dXJuO1xuXHRcdG91dHJvaW5nLmFkZChibG9jayk7XG5cdFx0b3V0cm9zLmMucHVzaCgoKSA9PiB7XG5cdFx0XHRvdXRyb2luZy5kZWxldGUoYmxvY2spO1xuXHRcdFx0aWYgKGNhbGxiYWNrKSB7XG5cdFx0XHRcdGlmIChkZXRhY2gpIGJsb2NrLmQoMSk7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0YmxvY2subyhsb2NhbCk7XG5cdH0gZWxzZSBpZiAoY2FsbGJhY2spIHtcblx0XHRjYWxsYmFjaygpO1xuXHR9XG59XG5cbi8qKlxuICogQHR5cGUge2ltcG9ydCgnLi4vdHJhbnNpdGlvbi9wdWJsaWMuanMnKS5UcmFuc2l0aW9uQ29uZmlnfVxuICovXG5jb25zdCBudWxsX3RyYW5zaXRpb24gPSB7IGR1cmF0aW9uOiAwIH07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50ICYgRWxlbWVudENTU0lubGluZVN0eWxlfSBub2RlXG4gKiBAcGFyYW0ge1RyYW5zaXRpb25Gbn0gZm5cbiAqIEBwYXJhbSB7YW55fSBwYXJhbXNcbiAqIEByZXR1cm5zIHt7IHN0YXJ0KCk6IHZvaWQ7IGludmFsaWRhdGUoKTogdm9pZDsgZW5kKCk6IHZvaWQ7IH19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfaW5fdHJhbnNpdGlvbihub2RlLCBmbiwgcGFyYW1zKSB7XG5cdC8qKlxuXHQgKiBAdHlwZSB7VHJhbnNpdGlvbk9wdGlvbnN9ICovXG5cdGNvbnN0IG9wdGlvbnMgPSB7IGRpcmVjdGlvbjogJ2luJyB9O1xuXHRsZXQgY29uZmlnID0gZm4obm9kZSwgcGFyYW1zLCBvcHRpb25zKTtcblx0bGV0IHJ1bm5pbmcgPSBmYWxzZTtcblx0bGV0IGFuaW1hdGlvbl9uYW1lO1xuXHRsZXQgdGFzaztcblx0bGV0IHVpZCA9IDA7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBjbGVhbnVwKCkge1xuXHRcdGlmIChhbmltYXRpb25fbmFtZSkgZGVsZXRlX3J1bGUobm9kZSwgYW5pbWF0aW9uX25hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBnbygpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cdFx0aWYgKGNzcykgYW5pbWF0aW9uX25hbWUgPSBjcmVhdGVfcnVsZShub2RlLCAwLCAxLCBkdXJhdGlvbiwgZGVsYXksIGVhc2luZywgY3NzLCB1aWQrKyk7XG5cdFx0dGljaygwLCAxKTtcblx0XHRjb25zdCBzdGFydF90aW1lID0gbm93KCkgKyBkZWxheTtcblx0XHRjb25zdCBlbmRfdGltZSA9IHN0YXJ0X3RpbWUgKyBkdXJhdGlvbjtcblx0XHRpZiAodGFzaykgdGFzay5hYm9ydCgpO1xuXHRcdHJ1bm5pbmcgPSB0cnVlO1xuXHRcdGFkZF9yZW5kZXJfY2FsbGJhY2soKCkgPT4gZGlzcGF0Y2gobm9kZSwgdHJ1ZSwgJ3N0YXJ0JykpO1xuXHRcdHRhc2sgPSBsb29wKChub3cpID0+IHtcblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChub3cgPj0gZW5kX3RpbWUpIHtcblx0XHRcdFx0XHR0aWNrKDEsIDApO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIHRydWUsICdlbmQnKTtcblx0XHRcdFx0XHRjbGVhbnVwKCk7XG5cdFx0XHRcdFx0cmV0dXJuIChydW5uaW5nID0gZmFsc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChub3cgPj0gc3RhcnRfdGltZSkge1xuXHRcdFx0XHRcdGNvbnN0IHQgPSBlYXNpbmcoKG5vdyAtIHN0YXJ0X3RpbWUpIC8gZHVyYXRpb24pO1xuXHRcdFx0XHRcdHRpY2sodCwgMSAtIHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcnVubmluZztcblx0XHR9KTtcblx0fVxuXHRsZXQgc3RhcnRlZCA9IGZhbHNlO1xuXHRyZXR1cm4ge1xuXHRcdHN0YXJ0KCkge1xuXHRcdFx0aWYgKHN0YXJ0ZWQpIHJldHVybjtcblx0XHRcdHN0YXJ0ZWQgPSB0cnVlO1xuXHRcdFx0ZGVsZXRlX3J1bGUobm9kZSk7XG5cdFx0XHRpZiAoaXNfZnVuY3Rpb24oY29uZmlnKSkge1xuXHRcdFx0XHRjb25maWcgPSBjb25maWcob3B0aW9ucyk7XG5cdFx0XHRcdHdhaXQoKS50aGVuKGdvKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGdvKCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRpbnZhbGlkYXRlKCkge1xuXHRcdFx0c3RhcnRlZCA9IGZhbHNlO1xuXHRcdH0sXG5cdFx0ZW5kKCkge1xuXHRcdFx0aWYgKHJ1bm5pbmcpIHtcblx0XHRcdFx0Y2xlYW51cCgpO1xuXHRcdFx0XHRydW5uaW5nID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHtUcmFuc2l0aW9uRm59IGZuXG4gKiBAcGFyYW0ge2FueX0gcGFyYW1zXG4gKiBAcmV0dXJucyB7eyBlbmQocmVzZXQ6IGFueSk6IHZvaWQ7IH19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVfb3V0X3RyYW5zaXRpb24obm9kZSwgZm4sIHBhcmFtcykge1xuXHQvKiogQHR5cGUge1RyYW5zaXRpb25PcHRpb25zfSAqL1xuXHRjb25zdCBvcHRpb25zID0geyBkaXJlY3Rpb246ICdvdXQnIH07XG5cdGxldCBjb25maWcgPSBmbihub2RlLCBwYXJhbXMsIG9wdGlvbnMpO1xuXHRsZXQgcnVubmluZyA9IHRydWU7XG5cdGxldCBhbmltYXRpb25fbmFtZTtcblx0Y29uc3QgZ3JvdXAgPSBvdXRyb3M7XG5cdGdyb3VwLnIgKz0gMTtcblx0LyoqIEB0eXBlIHtib29sZWFufSAqL1xuXHRsZXQgb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBnbygpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cblx0XHRpZiAoY3NzKSBhbmltYXRpb25fbmFtZSA9IGNyZWF0ZV9ydWxlKG5vZGUsIDEsIDAsIGR1cmF0aW9uLCBkZWxheSwgZWFzaW5nLCBjc3MpO1xuXG5cdFx0Y29uc3Qgc3RhcnRfdGltZSA9IG5vdygpICsgZGVsYXk7XG5cdFx0Y29uc3QgZW5kX3RpbWUgPSBzdGFydF90aW1lICsgZHVyYXRpb247XG5cdFx0YWRkX3JlbmRlcl9jYWxsYmFjaygoKSA9PiBkaXNwYXRjaChub2RlLCBmYWxzZSwgJ3N0YXJ0JykpO1xuXG5cdFx0aWYgKCdpbmVydCcgaW4gbm9kZSkge1xuXHRcdFx0b3JpZ2luYWxfaW5lcnRfdmFsdWUgPSAvKiogQHR5cGUge0hUTUxFbGVtZW50fSAqLyAobm9kZSkuaW5lcnQ7XG5cdFx0XHRub2RlLmluZXJ0ID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRsb29wKChub3cpID0+IHtcblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChub3cgPj0gZW5kX3RpbWUpIHtcblx0XHRcdFx0XHR0aWNrKDAsIDEpO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIGZhbHNlLCAnZW5kJyk7XG5cdFx0XHRcdFx0aWYgKCEtLWdyb3VwLnIpIHtcblx0XHRcdFx0XHRcdC8vIHRoaXMgd2lsbCByZXN1bHQgaW4gYGVuZCgpYCBiZWluZyBjYWxsZWQsXG5cdFx0XHRcdFx0XHQvLyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNsZWFuIHVwIGhlcmVcblx0XHRcdFx0XHRcdHJ1bl9hbGwoZ3JvdXAuYyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm93ID49IHN0YXJ0X3RpbWUpIHtcblx0XHRcdFx0XHRjb25zdCB0ID0gZWFzaW5nKChub3cgLSBzdGFydF90aW1lKSAvIGR1cmF0aW9uKTtcblx0XHRcdFx0XHR0aWNrKDEgLSB0LCB0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJ1bm5pbmc7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoaXNfZnVuY3Rpb24oY29uZmlnKSkge1xuXHRcdHdhaXQoKS50aGVuKCgpID0+IHtcblx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdGNvbmZpZyA9IGNvbmZpZyhvcHRpb25zKTtcblx0XHRcdGdvKCk7XG5cdFx0fSk7XG5cdH0gZWxzZSB7XG5cdFx0Z28oKTtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0ZW5kKHJlc2V0KSB7XG5cdFx0XHRpZiAocmVzZXQgJiYgJ2luZXJ0JyBpbiBub2RlKSB7XG5cdFx0XHRcdG5vZGUuaW5lcnQgPSBvcmlnaW5hbF9pbmVydF92YWx1ZTtcblx0XHRcdH1cblx0XHRcdGlmIChyZXNldCAmJiBjb25maWcudGljaykge1xuXHRcdFx0XHRjb25maWcudGljaygxLCAwKTtcblx0XHRcdH1cblx0XHRcdGlmIChydW5uaW5nKSB7XG5cdFx0XHRcdGlmIChhbmltYXRpb25fbmFtZSkgZGVsZXRlX3J1bGUobm9kZSwgYW5pbWF0aW9uX25hbWUpO1xuXHRcdFx0XHRydW5uaW5nID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCAmIEVsZW1lbnRDU1NJbmxpbmVTdHlsZX0gbm9kZVxuICogQHBhcmFtIHtUcmFuc2l0aW9uRm59IGZuXG4gKiBAcGFyYW0ge2FueX0gcGFyYW1zXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGludHJvXG4gKiBAcmV0dXJucyB7eyBydW4oYjogMCB8IDEpOiB2b2lkOyBlbmQoKTogdm9pZDsgfX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZV9iaWRpcmVjdGlvbmFsX3RyYW5zaXRpb24obm9kZSwgZm4sIHBhcmFtcywgaW50cm8pIHtcblx0LyoqXG5cdCAqIEB0eXBlIHtUcmFuc2l0aW9uT3B0aW9uc30gKi9cblx0Y29uc3Qgb3B0aW9ucyA9IHsgZGlyZWN0aW9uOiAnYm90aCcgfTtcblx0bGV0IGNvbmZpZyA9IGZuKG5vZGUsIHBhcmFtcywgb3B0aW9ucyk7XG5cdGxldCB0ID0gaW50cm8gPyAwIDogMTtcblxuXHQvKipcblx0ICogQHR5cGUge1Byb2dyYW0gfCBudWxsfSAqL1xuXHRsZXQgcnVubmluZ19wcm9ncmFtID0gbnVsbDtcblxuXHQvKipcblx0ICogQHR5cGUge1BlbmRpbmdQcm9ncmFtIHwgbnVsbH0gKi9cblx0bGV0IHBlbmRpbmdfcHJvZ3JhbSA9IG51bGw7XG5cdGxldCBhbmltYXRpb25fbmFtZSA9IG51bGw7XG5cblx0LyoqIEB0eXBlIHtib29sZWFufSAqL1xuXHRsZXQgb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cblx0LyoqXG5cdCAqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHRmdW5jdGlvbiBjbGVhcl9hbmltYXRpb24oKSB7XG5cdFx0aWYgKGFuaW1hdGlvbl9uYW1lKSBkZWxldGVfcnVsZShub2RlLCBhbmltYXRpb25fbmFtZSk7XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtQZW5kaW5nUHJvZ3JhbX0gcHJvZ3JhbVxuXHQgKiBAcGFyYW0ge251bWJlcn0gZHVyYXRpb25cblx0ICogQHJldHVybnMge1Byb2dyYW19XG5cdCAqL1xuXHRmdW5jdGlvbiBpbml0KHByb2dyYW0sIGR1cmF0aW9uKSB7XG5cdFx0Y29uc3QgZCA9IC8qKiBAdHlwZSB7UHJvZ3JhbVsnZCddfSAqLyAocHJvZ3JhbS5iIC0gdCk7XG5cdFx0ZHVyYXRpb24gKj0gTWF0aC5hYnMoZCk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGE6IHQsXG5cdFx0XHRiOiBwcm9ncmFtLmIsXG5cdFx0XHRkLFxuXHRcdFx0ZHVyYXRpb24sXG5cdFx0XHRzdGFydDogcHJvZ3JhbS5zdGFydCxcblx0XHRcdGVuZDogcHJvZ3JhbS5zdGFydCArIGR1cmF0aW9uLFxuXHRcdFx0Z3JvdXA6IHByb2dyYW0uZ3JvdXBcblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7SU5UUk8gfCBPVVRST30gYlxuXHQgKiBAcmV0dXJucyB7dm9pZH1cblx0ICovXG5cdGZ1bmN0aW9uIGdvKGIpIHtcblx0XHRjb25zdCB7XG5cdFx0XHRkZWxheSA9IDAsXG5cdFx0XHRkdXJhdGlvbiA9IDMwMCxcblx0XHRcdGVhc2luZyA9IGxpbmVhcixcblx0XHRcdHRpY2sgPSBub29wLFxuXHRcdFx0Y3NzXG5cdFx0fSA9IGNvbmZpZyB8fCBudWxsX3RyYW5zaXRpb247XG5cblx0XHQvKipcblx0XHQgKiBAdHlwZSB7UGVuZGluZ1Byb2dyYW19ICovXG5cdFx0Y29uc3QgcHJvZ3JhbSA9IHtcblx0XHRcdHN0YXJ0OiBub3coKSArIGRlbGF5LFxuXHRcdFx0YlxuXHRcdH07XG5cblx0XHRpZiAoIWIpIHtcblx0XHRcdC8vIEB0cy1pZ25vcmUgdG9kbzogaW1wcm92ZSB0eXBpbmdzXG5cdFx0XHRwcm9ncmFtLmdyb3VwID0gb3V0cm9zO1xuXHRcdFx0b3V0cm9zLnIgKz0gMTtcblx0XHR9XG5cblx0XHRpZiAoJ2luZXJ0JyBpbiBub2RlKSB7XG5cdFx0XHRpZiAoYikge1xuXHRcdFx0XHRpZiAob3JpZ2luYWxfaW5lcnRfdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdC8vIGFib3J0ZWQvcmV2ZXJzZWQgb3V0cm8gXHUyMDE0IHJlc3RvcmUgcHJldmlvdXMgaW5lcnQgdmFsdWVcblx0XHRcdFx0XHRub2RlLmluZXJ0ID0gb3JpZ2luYWxfaW5lcnRfdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG9yaWdpbmFsX2luZXJ0X3ZhbHVlID0gLyoqIEB0eXBlIHtIVE1MRWxlbWVudH0gKi8gKG5vZGUpLmluZXJ0O1xuXHRcdFx0XHRub2RlLmluZXJ0ID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAocnVubmluZ19wcm9ncmFtIHx8IHBlbmRpbmdfcHJvZ3JhbSkge1xuXHRcdFx0cGVuZGluZ19wcm9ncmFtID0gcHJvZ3JhbTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gaWYgdGhpcyBpcyBhbiBpbnRybywgYW5kIHRoZXJlJ3MgYSBkZWxheSwgd2UgbmVlZCB0byBkb1xuXHRcdFx0Ly8gYW4gaW5pdGlhbCB0aWNrIGFuZC9vciBhcHBseSBDU1MgYW5pbWF0aW9uIGltbWVkaWF0ZWx5XG5cdFx0XHRpZiAoY3NzKSB7XG5cdFx0XHRcdGNsZWFyX2FuaW1hdGlvbigpO1xuXHRcdFx0XHRhbmltYXRpb25fbmFtZSA9IGNyZWF0ZV9ydWxlKG5vZGUsIHQsIGIsIGR1cmF0aW9uLCBkZWxheSwgZWFzaW5nLCBjc3MpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGIpIHRpY2soMCwgMSk7XG5cdFx0XHRydW5uaW5nX3Byb2dyYW0gPSBpbml0KHByb2dyYW0sIGR1cmF0aW9uKTtcblx0XHRcdGFkZF9yZW5kZXJfY2FsbGJhY2soKCkgPT4gZGlzcGF0Y2gobm9kZSwgYiwgJ3N0YXJ0JykpO1xuXHRcdFx0bG9vcCgobm93KSA9PiB7XG5cdFx0XHRcdGlmIChwZW5kaW5nX3Byb2dyYW0gJiYgbm93ID4gcGVuZGluZ19wcm9ncmFtLnN0YXJ0KSB7XG5cdFx0XHRcdFx0cnVubmluZ19wcm9ncmFtID0gaW5pdChwZW5kaW5nX3Byb2dyYW0sIGR1cmF0aW9uKTtcblx0XHRcdFx0XHRwZW5kaW5nX3Byb2dyYW0gPSBudWxsO1xuXHRcdFx0XHRcdGRpc3BhdGNoKG5vZGUsIHJ1bm5pbmdfcHJvZ3JhbS5iLCAnc3RhcnQnKTtcblx0XHRcdFx0XHRpZiAoY3NzKSB7XG5cdFx0XHRcdFx0XHRjbGVhcl9hbmltYXRpb24oKTtcblx0XHRcdFx0XHRcdGFuaW1hdGlvbl9uYW1lID0gY3JlYXRlX3J1bGUoXG5cdFx0XHRcdFx0XHRcdG5vZGUsXG5cdFx0XHRcdFx0XHRcdHQsXG5cdFx0XHRcdFx0XHRcdHJ1bm5pbmdfcHJvZ3JhbS5iLFxuXHRcdFx0XHRcdFx0XHRydW5uaW5nX3Byb2dyYW0uZHVyYXRpb24sXG5cdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdGVhc2luZyxcblx0XHRcdFx0XHRcdFx0Y29uZmlnLmNzc1xuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHJ1bm5pbmdfcHJvZ3JhbSkge1xuXHRcdFx0XHRcdGlmIChub3cgPj0gcnVubmluZ19wcm9ncmFtLmVuZCkge1xuXHRcdFx0XHRcdFx0dGljaygodCA9IHJ1bm5pbmdfcHJvZ3JhbS5iKSwgMSAtIHQpO1xuXHRcdFx0XHRcdFx0ZGlzcGF0Y2gobm9kZSwgcnVubmluZ19wcm9ncmFtLmIsICdlbmQnKTtcblx0XHRcdFx0XHRcdGlmICghcGVuZGluZ19wcm9ncmFtKSB7XG5cdFx0XHRcdFx0XHRcdC8vIHdlJ3JlIGRvbmVcblx0XHRcdFx0XHRcdFx0aWYgKHJ1bm5pbmdfcHJvZ3JhbS5iKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gaW50cm8gXHUyMDE0IHdlIGNhbiB0aWR5IHVwIGltbWVkaWF0ZWx5XG5cdFx0XHRcdFx0XHRcdFx0Y2xlYXJfYW5pbWF0aW9uKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gb3V0cm8gXHUyMDE0IG5lZWRzIHRvIGJlIGNvb3JkaW5hdGVkXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCEtLXJ1bm5pbmdfcHJvZ3JhbS5ncm91cC5yKSBydW5fYWxsKHJ1bm5pbmdfcHJvZ3JhbS5ncm91cC5jKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0cnVubmluZ19wcm9ncmFtID0gbnVsbDtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKG5vdyA+PSBydW5uaW5nX3Byb2dyYW0uc3RhcnQpIHtcblx0XHRcdFx0XHRcdGNvbnN0IHAgPSBub3cgLSBydW5uaW5nX3Byb2dyYW0uc3RhcnQ7XG5cdFx0XHRcdFx0XHR0ID0gcnVubmluZ19wcm9ncmFtLmEgKyBydW5uaW5nX3Byb2dyYW0uZCAqIGVhc2luZyhwIC8gcnVubmluZ19wcm9ncmFtLmR1cmF0aW9uKTtcblx0XHRcdFx0XHRcdHRpY2sodCwgMSAtIHQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gISEocnVubmluZ19wcm9ncmFtIHx8IHBlbmRpbmdfcHJvZ3JhbSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHtcblx0XHRydW4oYikge1xuXHRcdFx0aWYgKGlzX2Z1bmN0aW9uKGNvbmZpZykpIHtcblx0XHRcdFx0d2FpdCgpLnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IG9wdHMgPSB7IGRpcmVjdGlvbjogYiA/ICdpbicgOiAnb3V0JyB9O1xuXHRcdFx0XHRcdC8vIEB0cy1pZ25vcmVcblx0XHRcdFx0XHRjb25maWcgPSBjb25maWcob3B0cyk7XG5cdFx0XHRcdFx0Z28oYik7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Z28oYik7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRlbmQoKSB7XG5cdFx0XHRjbGVhcl9hbmltYXRpb24oKTtcblx0XHRcdHJ1bm5pbmdfcHJvZ3JhbSA9IHBlbmRpbmdfcHJvZ3JhbSA9IG51bGw7XG5cdFx0fVxuXHR9O1xufVxuXG4vKiogQHR5cGVkZWYgezF9IElOVFJPICovXG4vKiogQHR5cGVkZWYgezB9IE9VVFJPICovXG4vKiogQHR5cGVkZWYge3sgZGlyZWN0aW9uOiAnaW4nIHwgJ291dCcgfCAnYm90aCcgfX0gVHJhbnNpdGlvbk9wdGlvbnMgKi9cbi8qKiBAdHlwZWRlZiB7KG5vZGU6IEVsZW1lbnQsIHBhcmFtczogYW55LCBvcHRpb25zOiBUcmFuc2l0aW9uT3B0aW9ucykgPT4gaW1wb3J0KCcuLi90cmFuc2l0aW9uL3B1YmxpYy5qcycpLlRyYW5zaXRpb25Db25maWd9IFRyYW5zaXRpb25GbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE91dHJvXG4gKiBAcHJvcGVydHkge251bWJlcn0gclxuICogQHByb3BlcnR5IHtGdW5jdGlvbltdfSBjXG4gKiBAcHJvcGVydHkge09iamVjdH0gcFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGVuZGluZ1Byb2dyYW1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzdGFydFxuICogQHByb3BlcnR5IHtJTlRST3xPVVRST30gYlxuICogQHByb3BlcnR5IHtPdXRyb30gW2dyb3VwXVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUHJvZ3JhbVxuICogQHByb3BlcnR5IHtudW1iZXJ9IGFcbiAqIEBwcm9wZXJ0eSB7SU5UUk98T1VUUk99IGJcbiAqIEBwcm9wZXJ0eSB7MXwtMX0gZFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGR1cmF0aW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gc3RhcnRcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBlbmRcbiAqIEBwcm9wZXJ0eSB7T3V0cm99IFtncm91cF1cbiAqL1xuIiwgImltcG9ydCB7IHRyYW5zaXRpb25faW4sIHRyYW5zaXRpb25fb3V0IH0gZnJvbSAnLi90cmFuc2l0aW9ucy5qcyc7XG5pbXBvcnQgeyBydW5fYWxsIH0gZnJvbSAnLi91dGlscy5qcyc7XG5cbi8vIGdlbmVyYWwgZWFjaCBmdW5jdGlvbnM6XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVfYXJyYXlfbGlrZShhcnJheV9saWtlX29yX2l0ZXJhdG9yKSB7XG5cdHJldHVybiBhcnJheV9saWtlX29yX2l0ZXJhdG9yPy5sZW5ndGggIT09IHVuZGVmaW5lZFxuXHRcdD8gYXJyYXlfbGlrZV9vcl9pdGVyYXRvclxuXHRcdDogQXJyYXkuZnJvbShhcnJheV9saWtlX29yX2l0ZXJhdG9yKTtcbn1cblxuLy8ga2V5ZWQgZWFjaCBmdW5jdGlvbnM6XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXN0cm95X2Jsb2NrKGJsb2NrLCBsb29rdXApIHtcblx0YmxvY2suZCgxKTtcblx0bG9va3VwLmRlbGV0ZShibG9jay5rZXkpO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gb3V0cm9fYW5kX2Rlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCkge1xuXHR0cmFuc2l0aW9uX291dChibG9jaywgMSwgMSwgKCkgPT4ge1xuXHRcdGxvb2t1cC5kZWxldGUoYmxvY2sua2V5KTtcblx0fSk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaXhfYW5kX2Rlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCkge1xuXHRibG9jay5mKCk7XG5cdGRlc3Ryb3lfYmxvY2soYmxvY2ssIGxvb2t1cCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaXhfYW5kX291dHJvX2FuZF9kZXN0cm95X2Jsb2NrKGJsb2NrLCBsb29rdXApIHtcblx0YmxvY2suZigpO1xuXHRvdXRyb19hbmRfZGVzdHJveV9ibG9jayhibG9jaywgbG9va3VwKTtcbn1cblxuLyoqIEByZXR1cm5zIHthbnlbXX0gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVfa2V5ZWRfZWFjaChcblx0b2xkX2Jsb2Nrcyxcblx0ZGlydHksXG5cdGdldF9rZXksXG5cdGR5bmFtaWMsXG5cdGN0eCxcblx0bGlzdCxcblx0bG9va3VwLFxuXHRub2RlLFxuXHRkZXN0cm95LFxuXHRjcmVhdGVfZWFjaF9ibG9jayxcblx0bmV4dCxcblx0Z2V0X2NvbnRleHRcbikge1xuXHRsZXQgbyA9IG9sZF9ibG9ja3MubGVuZ3RoO1xuXHRsZXQgbiA9IGxpc3QubGVuZ3RoO1xuXHRsZXQgaSA9IG87XG5cdGNvbnN0IG9sZF9pbmRleGVzID0ge307XG5cdHdoaWxlIChpLS0pIG9sZF9pbmRleGVzW29sZF9ibG9ja3NbaV0ua2V5XSA9IGk7XG5cdGNvbnN0IG5ld19ibG9ja3MgPSBbXTtcblx0Y29uc3QgbmV3X2xvb2t1cCA9IG5ldyBNYXAoKTtcblx0Y29uc3QgZGVsdGFzID0gbmV3IE1hcCgpO1xuXHRjb25zdCB1cGRhdGVzID0gW107XG5cdGkgPSBuO1xuXHR3aGlsZSAoaS0tKSB7XG5cdFx0Y29uc3QgY2hpbGRfY3R4ID0gZ2V0X2NvbnRleHQoY3R4LCBsaXN0LCBpKTtcblx0XHRjb25zdCBrZXkgPSBnZXRfa2V5KGNoaWxkX2N0eCk7XG5cdFx0bGV0IGJsb2NrID0gbG9va3VwLmdldChrZXkpO1xuXHRcdGlmICghYmxvY2spIHtcblx0XHRcdGJsb2NrID0gY3JlYXRlX2VhY2hfYmxvY2soa2V5LCBjaGlsZF9jdHgpO1xuXHRcdFx0YmxvY2suYygpO1xuXHRcdH0gZWxzZSBpZiAoZHluYW1pYykge1xuXHRcdFx0Ly8gZGVmZXIgdXBkYXRlcyB1bnRpbCBhbGwgdGhlIERPTSBzaHVmZmxpbmcgaXMgZG9uZVxuXHRcdFx0dXBkYXRlcy5wdXNoKCgpID0+IGJsb2NrLnAoY2hpbGRfY3R4LCBkaXJ0eSkpO1xuXHRcdH1cblx0XHRuZXdfbG9va3VwLnNldChrZXksIChuZXdfYmxvY2tzW2ldID0gYmxvY2spKTtcblx0XHRpZiAoa2V5IGluIG9sZF9pbmRleGVzKSBkZWx0YXMuc2V0KGtleSwgTWF0aC5hYnMoaSAtIG9sZF9pbmRleGVzW2tleV0pKTtcblx0fVxuXHRjb25zdCB3aWxsX21vdmUgPSBuZXcgU2V0KCk7XG5cdGNvbnN0IGRpZF9tb3ZlID0gbmV3IFNldCgpO1xuXHQvKiogQHJldHVybnMge3ZvaWR9ICovXG5cdGZ1bmN0aW9uIGluc2VydChibG9jaykge1xuXHRcdHRyYW5zaXRpb25faW4oYmxvY2ssIDEpO1xuXHRcdGJsb2NrLm0obm9kZSwgbmV4dCk7XG5cdFx0bG9va3VwLnNldChibG9jay5rZXksIGJsb2NrKTtcblx0XHRuZXh0ID0gYmxvY2suZmlyc3Q7XG5cdFx0bi0tO1xuXHR9XG5cdHdoaWxlIChvICYmIG4pIHtcblx0XHRjb25zdCBuZXdfYmxvY2sgPSBuZXdfYmxvY2tzW24gLSAxXTtcblx0XHRjb25zdCBvbGRfYmxvY2sgPSBvbGRfYmxvY2tzW28gLSAxXTtcblx0XHRjb25zdCBuZXdfa2V5ID0gbmV3X2Jsb2NrLmtleTtcblx0XHRjb25zdCBvbGRfa2V5ID0gb2xkX2Jsb2NrLmtleTtcblx0XHRpZiAobmV3X2Jsb2NrID09PSBvbGRfYmxvY2spIHtcblx0XHRcdC8vIGRvIG5vdGhpbmdcblx0XHRcdG5leHQgPSBuZXdfYmxvY2suZmlyc3Q7XG5cdFx0XHRvLS07XG5cdFx0XHRuLS07XG5cdFx0fSBlbHNlIGlmICghbmV3X2xvb2t1cC5oYXMob2xkX2tleSkpIHtcblx0XHRcdC8vIHJlbW92ZSBvbGQgYmxvY2tcblx0XHRcdGRlc3Ryb3kob2xkX2Jsb2NrLCBsb29rdXApO1xuXHRcdFx0by0tO1xuXHRcdH0gZWxzZSBpZiAoIWxvb2t1cC5oYXMobmV3X2tleSkgfHwgd2lsbF9tb3ZlLmhhcyhuZXdfa2V5KSkge1xuXHRcdFx0aW5zZXJ0KG5ld19ibG9jayk7XG5cdFx0fSBlbHNlIGlmIChkaWRfbW92ZS5oYXMob2xkX2tleSkpIHtcblx0XHRcdG8tLTtcblx0XHR9IGVsc2UgaWYgKGRlbHRhcy5nZXQobmV3X2tleSkgPiBkZWx0YXMuZ2V0KG9sZF9rZXkpKSB7XG5cdFx0XHRkaWRfbW92ZS5hZGQobmV3X2tleSk7XG5cdFx0XHRpbnNlcnQobmV3X2Jsb2NrKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0d2lsbF9tb3ZlLmFkZChvbGRfa2V5KTtcblx0XHRcdG8tLTtcblx0XHR9XG5cdH1cblx0d2hpbGUgKG8tLSkge1xuXHRcdGNvbnN0IG9sZF9ibG9jayA9IG9sZF9ibG9ja3Nbb107XG5cdFx0aWYgKCFuZXdfbG9va3VwLmhhcyhvbGRfYmxvY2sua2V5KSkgZGVzdHJveShvbGRfYmxvY2ssIGxvb2t1cCk7XG5cdH1cblx0d2hpbGUgKG4pIGluc2VydChuZXdfYmxvY2tzW24gLSAxXSk7XG5cdHJ1bl9hbGwodXBkYXRlcyk7XG5cdHJldHVybiBuZXdfYmxvY2tzO1xufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVfZWFjaF9rZXlzKGN0eCwgbGlzdCwgZ2V0X2NvbnRleHQsIGdldF9rZXkpIHtcblx0Y29uc3Qga2V5cyA9IG5ldyBNYXAoKTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3Qga2V5ID0gZ2V0X2tleShnZXRfY29udGV4dChjdHgsIGxpc3QsIGkpKTtcblx0XHRpZiAoa2V5cy5oYXMoa2V5KSkge1xuXHRcdFx0bGV0IHZhbHVlID0gJyc7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR2YWx1ZSA9IGB3aXRoIHZhbHVlICcke1N0cmluZyhrZXkpfScgYDtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0Ly8gY2FuJ3Qgc3RyaW5naWZ5XG5cdFx0XHR9XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBDYW5ub3QgaGF2ZSBkdXBsaWNhdGUga2V5cyBpbiBhIGtleWVkIGVhY2g6IEtleXMgYXQgaW5kZXggJHtrZXlzLmdldChcblx0XHRcdFx0XHRrZXlcblx0XHRcdFx0KX0gYW5kICR7aX0gJHt2YWx1ZX1hcmUgZHVwbGljYXRlc2Bcblx0XHRcdCk7XG5cdFx0fVxuXHRcdGtleXMuc2V0KGtleSwgaSk7XG5cdH1cbn1cbiIsICJjb25zdCBfYm9vbGVhbl9hdHRyaWJ1dGVzID0gLyoqIEB0eXBlIHtjb25zdH0gKi8gKFtcblx0J2FsbG93ZnVsbHNjcmVlbicsXG5cdCdhbGxvd3BheW1lbnRyZXF1ZXN0Jyxcblx0J2FzeW5jJyxcblx0J2F1dG9mb2N1cycsXG5cdCdhdXRvcGxheScsXG5cdCdjaGVja2VkJyxcblx0J2NvbnRyb2xzJyxcblx0J2RlZmF1bHQnLFxuXHQnZGVmZXInLFxuXHQnZGlzYWJsZWQnLFxuXHQnZm9ybW5vdmFsaWRhdGUnLFxuXHQnaGlkZGVuJyxcblx0J2luZXJ0Jyxcblx0J2lzbWFwJyxcblx0J2xvb3AnLFxuXHQnbXVsdGlwbGUnLFxuXHQnbXV0ZWQnLFxuXHQnbm9tb2R1bGUnLFxuXHQnbm92YWxpZGF0ZScsXG5cdCdvcGVuJyxcblx0J3BsYXlzaW5saW5lJyxcblx0J3JlYWRvbmx5Jyxcblx0J3JlcXVpcmVkJyxcblx0J3JldmVyc2VkJyxcblx0J3NlbGVjdGVkJ1xuXSk7XG5cbi8qKlxuICogTGlzdCBvZiBIVE1MIGJvb2xlYW4gYXR0cmlidXRlcyAoZS5nLiBgPGlucHV0IGRpc2FibGVkPmApLlxuICogU291cmNlOiBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9pbmRpY2VzLmh0bWxcbiAqXG4gKiBAdHlwZSB7U2V0PHN0cmluZz59XG4gKi9cbmV4cG9ydCBjb25zdCBib29sZWFuX2F0dHJpYnV0ZXMgPSBuZXcgU2V0KFsuLi5fYm9vbGVhbl9hdHRyaWJ1dGVzXSk7XG5cbi8qKiBAdHlwZWRlZiB7dHlwZW9mIF9ib29sZWFuX2F0dHJpYnV0ZXNbbnVtYmVyXX0gQm9vbGVhbkF0dHJpYnV0ZXMgKi9cbiIsICJpbXBvcnQge1xuXHRhZGRfcmVuZGVyX2NhbGxiYWNrLFxuXHRmbHVzaCxcblx0Zmx1c2hfcmVuZGVyX2NhbGxiYWNrcyxcblx0c2NoZWR1bGVfdXBkYXRlLFxuXHRkaXJ0eV9jb21wb25lbnRzXG59IGZyb20gJy4vc2NoZWR1bGVyLmpzJztcbmltcG9ydCB7IGN1cnJlbnRfY29tcG9uZW50LCBzZXRfY3VycmVudF9jb21wb25lbnQgfSBmcm9tICcuL2xpZmVjeWNsZS5qcyc7XG5pbXBvcnQgeyBibGFua19vYmplY3QsIGlzX2VtcHR5LCBpc19mdW5jdGlvbiwgcnVuLCBydW5fYWxsLCBub29wIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQge1xuXHRjaGlsZHJlbixcblx0ZGV0YWNoLFxuXHRzdGFydF9oeWRyYXRpbmcsXG5cdGVuZF9oeWRyYXRpbmcsXG5cdGdldF9jdXN0b21fZWxlbWVudHNfc2xvdHMsXG5cdGluc2VydCxcblx0ZWxlbWVudCxcblx0YXR0clxufSBmcm9tICcuL2RvbS5qcyc7XG5pbXBvcnQgeyB0cmFuc2l0aW9uX2luIH0gZnJvbSAnLi90cmFuc2l0aW9ucy5qcyc7XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaW5kKGNvbXBvbmVudCwgbmFtZSwgY2FsbGJhY2spIHtcblx0Y29uc3QgaW5kZXggPSBjb21wb25lbnQuJCQucHJvcHNbbmFtZV07XG5cdGlmIChpbmRleCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0Y29tcG9uZW50LiQkLmJvdW5kW2luZGV4XSA9IGNhbGxiYWNrO1xuXHRcdGNhbGxiYWNrKGNvbXBvbmVudC4kJC5jdHhbaW5kZXhdKTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlX2NvbXBvbmVudChibG9jaykge1xuXHRibG9jayAmJiBibG9jay5jKCk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFpbV9jb21wb25lbnQoYmxvY2ssIHBhcmVudF9ub2Rlcykge1xuXHRibG9jayAmJiBibG9jay5sKHBhcmVudF9ub2Rlcyk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3VudF9jb21wb25lbnQoY29tcG9uZW50LCB0YXJnZXQsIGFuY2hvcikge1xuXHRjb25zdCB7IGZyYWdtZW50LCBhZnRlcl91cGRhdGUgfSA9IGNvbXBvbmVudC4kJDtcblx0ZnJhZ21lbnQgJiYgZnJhZ21lbnQubSh0YXJnZXQsIGFuY2hvcik7XG5cdC8vIG9uTW91bnQgaGFwcGVucyBiZWZvcmUgdGhlIGluaXRpYWwgYWZ0ZXJVcGRhdGVcblx0YWRkX3JlbmRlcl9jYWxsYmFjaygoKSA9PiB7XG5cdFx0Y29uc3QgbmV3X29uX2Rlc3Ryb3kgPSBjb21wb25lbnQuJCQub25fbW91bnQubWFwKHJ1bikuZmlsdGVyKGlzX2Z1bmN0aW9uKTtcblx0XHQvLyBpZiB0aGUgY29tcG9uZW50IHdhcyBkZXN0cm95ZWQgaW1tZWRpYXRlbHlcblx0XHQvLyBpdCB3aWxsIHVwZGF0ZSB0aGUgYCQkLm9uX2Rlc3Ryb3lgIHJlZmVyZW5jZSB0byBgbnVsbGAuXG5cdFx0Ly8gdGhlIGRlc3RydWN0dXJlZCBvbl9kZXN0cm95IG1heSBzdGlsbCByZWZlcmVuY2UgdG8gdGhlIG9sZCBhcnJheVxuXHRcdGlmIChjb21wb25lbnQuJCQub25fZGVzdHJveSkge1xuXHRcdFx0Y29tcG9uZW50LiQkLm9uX2Rlc3Ryb3kucHVzaCguLi5uZXdfb25fZGVzdHJveSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIEVkZ2UgY2FzZSAtIGNvbXBvbmVudCB3YXMgZGVzdHJveWVkIGltbWVkaWF0ZWx5LFxuXHRcdFx0Ly8gbW9zdCBsaWtlbHkgYXMgYSByZXN1bHQgb2YgYSBiaW5kaW5nIGluaXRpYWxpc2luZ1xuXHRcdFx0cnVuX2FsbChuZXdfb25fZGVzdHJveSk7XG5cdFx0fVxuXHRcdGNvbXBvbmVudC4kJC5vbl9tb3VudCA9IFtdO1xuXHR9KTtcblx0YWZ0ZXJfdXBkYXRlLmZvckVhY2goYWRkX3JlbmRlcl9jYWxsYmFjayk7XG59XG5cbi8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXN0cm95X2NvbXBvbmVudChjb21wb25lbnQsIGRldGFjaGluZykge1xuXHRjb25zdCAkJCA9IGNvbXBvbmVudC4kJDtcblx0aWYgKCQkLmZyYWdtZW50ICE9PSBudWxsKSB7XG5cdFx0Zmx1c2hfcmVuZGVyX2NhbGxiYWNrcygkJC5hZnRlcl91cGRhdGUpO1xuXHRcdHJ1bl9hbGwoJCQub25fZGVzdHJveSk7XG5cdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQuZChkZXRhY2hpbmcpO1xuXHRcdC8vIFRPRE8gbnVsbCBvdXQgb3RoZXIgcmVmcywgaW5jbHVkaW5nIGNvbXBvbmVudC4kJCAoYnV0IG5lZWQgdG9cblx0XHQvLyBwcmVzZXJ2ZSBmaW5hbCBzdGF0ZT8pXG5cdFx0JCQub25fZGVzdHJveSA9ICQkLmZyYWdtZW50ID0gbnVsbDtcblx0XHQkJC5jdHggPSBbXTtcblx0fVxufVxuXG4vKiogQHJldHVybnMge3ZvaWR9ICovXG5mdW5jdGlvbiBtYWtlX2RpcnR5KGNvbXBvbmVudCwgaSkge1xuXHRpZiAoY29tcG9uZW50LiQkLmRpcnR5WzBdID09PSAtMSkge1xuXHRcdGRpcnR5X2NvbXBvbmVudHMucHVzaChjb21wb25lbnQpO1xuXHRcdHNjaGVkdWxlX3VwZGF0ZSgpO1xuXHRcdGNvbXBvbmVudC4kJC5kaXJ0eS5maWxsKDApO1xuXHR9XG5cdGNvbXBvbmVudC4kJC5kaXJ0eVsoaSAvIDMxKSB8IDBdIHw9IDEgPDwgaSAlIDMxO1xufVxuXG4vLyBUT0RPOiBEb2N1bWVudCB0aGUgb3RoZXIgcGFyYW1zXG4vKipcbiAqIEBwYXJhbSB7U3ZlbHRlQ29tcG9uZW50fSBjb21wb25lbnRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLkNvbXBvbmVudENvbnN0cnVjdG9yT3B0aW9uc30gb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3V0aWxzLmpzJylbJ25vdF9lcXVhbCddfSBub3RfZXF1YWwgVXNlZCB0byBjb21wYXJlIHByb3BzIGFuZCBzdGF0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0geyh0YXJnZXQ6IEVsZW1lbnQgfCBTaGFkb3dSb290KSA9PiB2b2lkfSBbYXBwZW5kX3N0eWxlc10gRnVuY3Rpb24gdGhhdCBhcHBlbmRzIHN0eWxlcyB0byB0aGUgRE9NIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBmaXJzdCBpbml0aWFsaXNlZC5cbiAqIFRoaXMgd2lsbCBiZSB0aGUgYGFkZF9jc3NgIGZ1bmN0aW9uIGZyb20gdGhlIGNvbXBpbGVkIGNvbXBvbmVudC5cbiAqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXQoXG5cdGNvbXBvbmVudCxcblx0b3B0aW9ucyxcblx0aW5zdGFuY2UsXG5cdGNyZWF0ZV9mcmFnbWVudCxcblx0bm90X2VxdWFsLFxuXHRwcm9wcyxcblx0YXBwZW5kX3N0eWxlcyA9IG51bGwsXG5cdGRpcnR5ID0gWy0xXVxuKSB7XG5cdGNvbnN0IHBhcmVudF9jb21wb25lbnQgPSBjdXJyZW50X2NvbXBvbmVudDtcblx0c2V0X2N1cnJlbnRfY29tcG9uZW50KGNvbXBvbmVudCk7XG5cdC8qKiBAdHlwZSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5UJCR9ICovXG5cdGNvbnN0ICQkID0gKGNvbXBvbmVudC4kJCA9IHtcblx0XHRmcmFnbWVudDogbnVsbCxcblx0XHRjdHg6IFtdLFxuXHRcdC8vIHN0YXRlXG5cdFx0cHJvcHMsXG5cdFx0dXBkYXRlOiBub29wLFxuXHRcdG5vdF9lcXVhbCxcblx0XHRib3VuZDogYmxhbmtfb2JqZWN0KCksXG5cdFx0Ly8gbGlmZWN5Y2xlXG5cdFx0b25fbW91bnQ6IFtdLFxuXHRcdG9uX2Rlc3Ryb3k6IFtdLFxuXHRcdG9uX2Rpc2Nvbm5lY3Q6IFtdLFxuXHRcdGJlZm9yZV91cGRhdGU6IFtdLFxuXHRcdGFmdGVyX3VwZGF0ZTogW10sXG5cdFx0Y29udGV4dDogbmV3IE1hcChvcHRpb25zLmNvbnRleHQgfHwgKHBhcmVudF9jb21wb25lbnQgPyBwYXJlbnRfY29tcG9uZW50LiQkLmNvbnRleHQgOiBbXSkpLFxuXHRcdC8vIGV2ZXJ5dGhpbmcgZWxzZVxuXHRcdGNhbGxiYWNrczogYmxhbmtfb2JqZWN0KCksXG5cdFx0ZGlydHksXG5cdFx0c2tpcF9ib3VuZDogZmFsc2UsXG5cdFx0cm9vdDogb3B0aW9ucy50YXJnZXQgfHwgcGFyZW50X2NvbXBvbmVudC4kJC5yb290XG5cdH0pO1xuXHRhcHBlbmRfc3R5bGVzICYmIGFwcGVuZF9zdHlsZXMoJCQucm9vdCk7XG5cdGxldCByZWFkeSA9IGZhbHNlO1xuXHQkJC5jdHggPSBpbnN0YW5jZVxuXHRcdD8gaW5zdGFuY2UoY29tcG9uZW50LCBvcHRpb25zLnByb3BzIHx8IHt9LCAoaSwgcmV0LCAuLi5yZXN0KSA9PiB7XG5cdFx0XHRcdGNvbnN0IHZhbHVlID0gcmVzdC5sZW5ndGggPyByZXN0WzBdIDogcmV0O1xuXHRcdFx0XHRpZiAoJCQuY3R4ICYmIG5vdF9lcXVhbCgkJC5jdHhbaV0sICgkJC5jdHhbaV0gPSB2YWx1ZSkpKSB7XG5cdFx0XHRcdFx0aWYgKCEkJC5za2lwX2JvdW5kICYmICQkLmJvdW5kW2ldKSAkJC5ib3VuZFtpXSh2YWx1ZSk7XG5cdFx0XHRcdFx0aWYgKHJlYWR5KSBtYWtlX2RpcnR5KGNvbXBvbmVudCwgaSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHQgIH0pXG5cdFx0OiBbXTtcblx0JCQudXBkYXRlKCk7XG5cdHJlYWR5ID0gdHJ1ZTtcblx0cnVuX2FsbCgkJC5iZWZvcmVfdXBkYXRlKTtcblx0Ly8gYGZhbHNlYCBhcyBhIHNwZWNpYWwgY2FzZSBvZiBubyBET00gY29tcG9uZW50XG5cdCQkLmZyYWdtZW50ID0gY3JlYXRlX2ZyYWdtZW50ID8gY3JlYXRlX2ZyYWdtZW50KCQkLmN0eCkgOiBmYWxzZTtcblx0aWYgKG9wdGlvbnMudGFyZ2V0KSB7XG5cdFx0aWYgKG9wdGlvbnMuaHlkcmF0ZSkge1xuXHRcdFx0c3RhcnRfaHlkcmF0aW5nKCk7XG5cdFx0XHQvLyBUT0RPOiB3aGF0IGlzIHRoZSBjb3JyZWN0IHR5cGUgaGVyZT9cblx0XHRcdC8vIEB0cy1leHBlY3QtZXJyb3Jcblx0XHRcdGNvbnN0IG5vZGVzID0gY2hpbGRyZW4ob3B0aW9ucy50YXJnZXQpO1xuXHRcdFx0JCQuZnJhZ21lbnQgJiYgJCQuZnJhZ21lbnQubChub2Rlcyk7XG5cdFx0XHRub2Rlcy5mb3JFYWNoKGRldGFjaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG5cdFx0XHQkJC5mcmFnbWVudCAmJiAkJC5mcmFnbWVudC5jKCk7XG5cdFx0fVxuXHRcdGlmIChvcHRpb25zLmludHJvKSB0cmFuc2l0aW9uX2luKGNvbXBvbmVudC4kJC5mcmFnbWVudCk7XG5cdFx0bW91bnRfY29tcG9uZW50KGNvbXBvbmVudCwgb3B0aW9ucy50YXJnZXQsIG9wdGlvbnMuYW5jaG9yKTtcblx0XHRlbmRfaHlkcmF0aW5nKCk7XG5cdFx0Zmx1c2goKTtcblx0fVxuXHRzZXRfY3VycmVudF9jb21wb25lbnQocGFyZW50X2NvbXBvbmVudCk7XG59XG5cbmV4cG9ydCBsZXQgU3ZlbHRlRWxlbWVudDtcblxuaWYgKHR5cGVvZiBIVE1MRWxlbWVudCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRTdmVsdGVFbGVtZW50ID0gY2xhc3MgZXh0ZW5kcyBIVE1MRWxlbWVudCB7XG5cdFx0LyoqIFRoZSBTdmVsdGUgY29tcG9uZW50IGNvbnN0cnVjdG9yICovXG5cdFx0JCRjdG9yO1xuXHRcdC8qKiBTbG90cyAqL1xuXHRcdCQkcztcblx0XHQvKiogVGhlIFN2ZWx0ZSBjb21wb25lbnQgaW5zdGFuY2UgKi9cblx0XHQkJGM7XG5cdFx0LyoqIFdoZXRoZXIgb3Igbm90IHRoZSBjdXN0b20gZWxlbWVudCBpcyBjb25uZWN0ZWQgKi9cblx0XHQkJGNuID0gZmFsc2U7XG5cdFx0LyoqIENvbXBvbmVudCBwcm9wcyBkYXRhICovXG5cdFx0JCRkID0ge307XG5cdFx0LyoqIGB0cnVlYCBpZiBjdXJyZW50bHkgaW4gdGhlIHByb2Nlc3Mgb2YgcmVmbGVjdGluZyBjb21wb25lbnQgcHJvcHMgYmFjayB0byBhdHRyaWJ1dGVzICovXG5cdFx0JCRyID0gZmFsc2U7XG5cdFx0LyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBDdXN0b21FbGVtZW50UHJvcERlZmluaXRpb24+fSBQcm9wcyBkZWZpbml0aW9uIChuYW1lLCByZWZsZWN0ZWQsIHR5cGUgZXRjKSAqL1xuXHRcdCQkcF9kID0ge307XG5cdFx0LyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBGdW5jdGlvbltdPn0gRXZlbnQgbGlzdGVuZXJzICovXG5cdFx0JCRsID0ge307XG5cdFx0LyoqIEB0eXBlIHtNYXA8RnVuY3Rpb24sIEZ1bmN0aW9uPn0gRXZlbnQgbGlzdGVuZXIgdW5zdWJzY3JpYmUgZnVuY3Rpb25zICovXG5cdFx0JCRsX3UgPSBuZXcgTWFwKCk7XG5cblx0XHRjb25zdHJ1Y3RvcigkJGNvbXBvbmVudEN0b3IsICQkc2xvdHMsIHVzZV9zaGFkb3dfZG9tKSB7XG5cdFx0XHRzdXBlcigpO1xuXHRcdFx0dGhpcy4kJGN0b3IgPSAkJGNvbXBvbmVudEN0b3I7XG5cdFx0XHR0aGlzLiQkcyA9ICQkc2xvdHM7XG5cdFx0XHRpZiAodXNlX3NoYWRvd19kb20pIHtcblx0XHRcdFx0dGhpcy5hdHRhY2hTaGFkb3coeyBtb2RlOiAnb3BlbicgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0YWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lciwgb3B0aW9ucykge1xuXHRcdFx0Ly8gV2UgY2FuJ3QgZGV0ZXJtaW5lIHVwZnJvbnQgaWYgdGhlIGV2ZW50IGlzIGEgY3VzdG9tIGV2ZW50IG9yIG5vdCwgc28gd2UgaGF2ZSB0b1xuXHRcdFx0Ly8gbGlzdGVuIHRvIGJvdGguIElmIHNvbWVvbmUgdXNlcyBhIGN1c3RvbSBldmVudCB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgYSByZWd1bGFyXG5cdFx0XHQvLyBicm93c2VyIGV2ZW50LCB0aGlzIGZpcmVzIHR3aWNlIC0gd2UgY2FuJ3QgYXZvaWQgdGhhdC5cblx0XHRcdHRoaXMuJCRsW3R5cGVdID0gdGhpcy4kJGxbdHlwZV0gfHwgW107XG5cdFx0XHR0aGlzLiQkbFt0eXBlXS5wdXNoKGxpc3RlbmVyKTtcblx0XHRcdGlmICh0aGlzLiQkYykge1xuXHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRjLiRvbih0eXBlLCBsaXN0ZW5lcik7XG5cdFx0XHRcdHRoaXMuJCRsX3Uuc2V0KGxpc3RlbmVyLCB1bnN1Yik7XG5cdFx0XHR9XG5cdFx0XHRzdXBlci5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcblx0XHR9XG5cblx0XHRyZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG5cdFx0XHRzdXBlci5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcblx0XHRcdGlmICh0aGlzLiQkYykge1xuXHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRsX3UuZ2V0KGxpc3RlbmVyKTtcblx0XHRcdFx0aWYgKHVuc3ViKSB7XG5cdFx0XHRcdFx0dW5zdWIoKTtcblx0XHRcdFx0XHR0aGlzLiQkbF91LmRlbGV0ZShsaXN0ZW5lcik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRhc3luYyBjb25uZWN0ZWRDYWxsYmFjaygpIHtcblx0XHRcdHRoaXMuJCRjbiA9IHRydWU7XG5cdFx0XHRpZiAoIXRoaXMuJCRjKSB7XG5cdFx0XHRcdC8vIFdlIHdhaXQgb25lIHRpY2sgdG8gbGV0IHBvc3NpYmxlIGNoaWxkIHNsb3QgZWxlbWVudHMgYmUgY3JlYXRlZC9tb3VudGVkXG5cdFx0XHRcdGF3YWl0IFByb21pc2UucmVzb2x2ZSgpO1xuXHRcdFx0XHRpZiAoIXRoaXMuJCRjbiB8fCB0aGlzLiQkYykge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRmdW5jdGlvbiBjcmVhdGVfc2xvdChuYW1lKSB7XG5cdFx0XHRcdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdFx0XHRcdGxldCBub2RlO1xuXHRcdFx0XHRcdFx0Y29uc3Qgb2JqID0ge1xuXHRcdFx0XHRcdFx0XHRjOiBmdW5jdGlvbiBjcmVhdGUoKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW1lbnQoJ3Nsb3QnKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAobmFtZSAhPT0gJ2RlZmF1bHQnKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRhdHRyKG5vZGUsICduYW1lJywgbmFtZSk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHQvKipcblx0XHRcdFx0XHRcdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdGFyZ2V0XG5cdFx0XHRcdFx0XHRcdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IFthbmNob3JdXG5cdFx0XHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdFx0XHRtOiBmdW5jdGlvbiBtb3VudCh0YXJnZXQsIGFuY2hvcikge1xuXHRcdFx0XHRcdFx0XHRcdGluc2VydCh0YXJnZXQsIG5vZGUsIGFuY2hvcik7XG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdGQ6IGZ1bmN0aW9uIGRlc3Ryb3koZGV0YWNoaW5nKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGRldGFjaGluZykge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGV0YWNoKG5vZGUpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdHJldHVybiBvYmo7XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCAkJHNsb3RzID0ge307XG5cdFx0XHRcdGNvbnN0IGV4aXN0aW5nX3Nsb3RzID0gZ2V0X2N1c3RvbV9lbGVtZW50c19zbG90cyh0aGlzKTtcblx0XHRcdFx0Zm9yIChjb25zdCBuYW1lIG9mIHRoaXMuJCRzKSB7XG5cdFx0XHRcdFx0aWYgKG5hbWUgaW4gZXhpc3Rpbmdfc2xvdHMpIHtcblx0XHRcdFx0XHRcdCQkc2xvdHNbbmFtZV0gPSBbY3JlYXRlX3Nsb3QobmFtZSldO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiB0aGlzLmF0dHJpYnV0ZXMpIHtcblx0XHRcdFx0XHQvLyB0aGlzLiQkZGF0YSB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgdGhpcy5hdHRyaWJ1dGVzXG5cdFx0XHRcdFx0Y29uc3QgbmFtZSA9IHRoaXMuJCRnX3AoYXR0cmlidXRlLm5hbWUpO1xuXHRcdFx0XHRcdGlmICghKG5hbWUgaW4gdGhpcy4kJGQpKSB7XG5cdFx0XHRcdFx0XHR0aGlzLiQkZFtuYW1lXSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShuYW1lLCBhdHRyaWJ1dGUudmFsdWUsIHRoaXMuJCRwX2QsICd0b1Byb3AnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gUG9ydCBvdmVyIHByb3BzIHRoYXQgd2VyZSBzZXQgcHJvZ3JhbW1hdGljYWxseSBiZWZvcmUgY2Ugd2FzIGluaXRpYWxpemVkXG5cdFx0XHRcdGZvciAoY29uc3Qga2V5IGluIHRoaXMuJCRwX2QpIHtcblx0XHRcdFx0XHRpZiAoIShrZXkgaW4gdGhpcy4kJGQpICYmIHRoaXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHR0aGlzLiQkZFtrZXldID0gdGhpc1trZXldOyAvLyBkb24ndCB0cmFuc2Zvcm0sIHRoZXNlIHdlcmUgc2V0IHRocm91Z2ggSmF2YVNjcmlwdFxuXHRcdFx0XHRcdFx0ZGVsZXRlIHRoaXNba2V5XTsgLy8gcmVtb3ZlIHRoZSBwcm9wZXJ0eSB0aGF0IHNoYWRvd3MgdGhlIGdldHRlci9zZXR0ZXJcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy4kJGMgPSBuZXcgdGhpcy4kJGN0b3Ioe1xuXHRcdFx0XHRcdHRhcmdldDogdGhpcy5zaGFkb3dSb290IHx8IHRoaXMsXG5cdFx0XHRcdFx0cHJvcHM6IHtcblx0XHRcdFx0XHRcdC4uLnRoaXMuJCRkLFxuXHRcdFx0XHRcdFx0JCRzbG90cyxcblx0XHRcdFx0XHRcdCQkc2NvcGU6IHtcblx0XHRcdFx0XHRcdFx0Y3R4OiBbXVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gUmVmbGVjdCBjb21wb25lbnQgcHJvcHMgYXMgYXR0cmlidXRlc1xuXHRcdFx0XHRjb25zdCByZWZsZWN0X2F0dHJpYnV0ZXMgPSAoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy4kJHIgPSB0cnVlO1xuXHRcdFx0XHRcdGZvciAoY29uc3Qga2V5IGluIHRoaXMuJCRwX2QpIHtcblx0XHRcdFx0XHRcdHRoaXMuJCRkW2tleV0gPSB0aGlzLiQkYy4kJC5jdHhbdGhpcy4kJGMuJCQucHJvcHNba2V5XV07XG5cdFx0XHRcdFx0XHRpZiAodGhpcy4kJHBfZFtrZXldLnJlZmxlY3QpIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgYXR0cmlidXRlX3ZhbHVlID0gZ2V0X2N1c3RvbV9lbGVtZW50X3ZhbHVlKFxuXHRcdFx0XHRcdFx0XHRcdGtleSxcblx0XHRcdFx0XHRcdFx0XHR0aGlzLiQkZFtrZXldLFxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuJCRwX2QsXG5cdFx0XHRcdFx0XHRcdFx0J3RvQXR0cmlidXRlJ1xuXHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRpZiAoYXR0cmlidXRlX3ZhbHVlID09IG51bGwpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnJlbW92ZUF0dHJpYnV0ZSh0aGlzLiQkcF9kW2tleV0uYXR0cmlidXRlIHx8IGtleSk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUodGhpcy4kJHBfZFtrZXldLmF0dHJpYnV0ZSB8fCBrZXksIGF0dHJpYnV0ZV92YWx1ZSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhpcy4kJHIgPSBmYWxzZTtcblx0XHRcdFx0fTtcblx0XHRcdFx0dGhpcy4kJGMuJCQuYWZ0ZXJfdXBkYXRlLnB1c2gocmVmbGVjdF9hdHRyaWJ1dGVzKTtcblx0XHRcdFx0cmVmbGVjdF9hdHRyaWJ1dGVzKCk7IC8vIG9uY2UgaW5pdGlhbGx5IGJlY2F1c2UgYWZ0ZXJfdXBkYXRlIGlzIGFkZGVkIHRvbyBsYXRlIGZvciBmaXJzdCByZW5kZXJcblxuXHRcdFx0XHRmb3IgKGNvbnN0IHR5cGUgaW4gdGhpcy4kJGwpIHtcblx0XHRcdFx0XHRmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuJCRsW3R5cGVdKSB7XG5cdFx0XHRcdFx0XHRjb25zdCB1bnN1YiA9IHRoaXMuJCRjLiRvbih0eXBlLCBsaXN0ZW5lcik7XG5cdFx0XHRcdFx0XHR0aGlzLiQkbF91LnNldChsaXN0ZW5lciwgdW5zdWIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLiQkbCA9IHt9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFdlIGRvbid0IG5lZWQgdGhpcyB3aGVuIHdvcmtpbmcgd2l0aGluIFN2ZWx0ZSBjb2RlLCBidXQgZm9yIGNvbXBhdGliaWxpdHkgb2YgcGVvcGxlIHVzaW5nIHRoaXMgb3V0c2lkZSBvZiBTdmVsdGVcblx0XHQvLyBhbmQgc2V0dGluZyBhdHRyaWJ1dGVzIHRocm91Z2ggc2V0QXR0cmlidXRlIGV0YywgdGhpcyBpcyBoZWxwZnVsXG5cdFx0YXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGF0dHIsIF9vbGRWYWx1ZSwgbmV3VmFsdWUpIHtcblx0XHRcdGlmICh0aGlzLiQkcikgcmV0dXJuO1xuXHRcdFx0YXR0ciA9IHRoaXMuJCRnX3AoYXR0cik7XG5cdFx0XHR0aGlzLiQkZFthdHRyXSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShhdHRyLCBuZXdWYWx1ZSwgdGhpcy4kJHBfZCwgJ3RvUHJvcCcpO1xuXHRcdFx0dGhpcy4kJGM/LiRzZXQoeyBbYXR0cl06IHRoaXMuJCRkW2F0dHJdIH0pO1xuXHRcdH1cblxuXHRcdGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuXHRcdFx0dGhpcy4kJGNuID0gZmFsc2U7XG5cdFx0XHQvLyBJbiBhIG1pY3JvdGFzaywgYmVjYXVzZSB0aGlzIGNvdWxkIGJlIGEgbW92ZSB3aXRoaW4gdGhlIERPTVxuXHRcdFx0UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG5cdFx0XHRcdGlmICghdGhpcy4kJGNuKSB7XG5cdFx0XHRcdFx0dGhpcy4kJGMuJGRlc3Ryb3koKTtcblx0XHRcdFx0XHR0aGlzLiQkYyA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0JCRnX3AoYXR0cmlidXRlX25hbWUpIHtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdE9iamVjdC5rZXlzKHRoaXMuJCRwX2QpLmZpbmQoXG5cdFx0XHRcdFx0KGtleSkgPT5cblx0XHRcdFx0XHRcdHRoaXMuJCRwX2Rba2V5XS5hdHRyaWJ1dGUgPT09IGF0dHJpYnV0ZV9uYW1lIHx8XG5cdFx0XHRcdFx0XHQoIXRoaXMuJCRwX2Rba2V5XS5hdHRyaWJ1dGUgJiYga2V5LnRvTG93ZXJDYXNlKCkgPT09IGF0dHJpYnV0ZV9uYW1lKVxuXHRcdFx0XHQpIHx8IGF0dHJpYnV0ZV9uYW1lXG5cdFx0XHQpO1xuXHRcdH1cblx0fTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcFxuICogQHBhcmFtIHthbnl9IHZhbHVlXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIEN1c3RvbUVsZW1lbnRQcm9wRGVmaW5pdGlvbj59IHByb3BzX2RlZmluaXRpb25cbiAqIEBwYXJhbSB7J3RvQXR0cmlidXRlJyB8ICd0b1Byb3AnfSBbdHJhbnNmb3JtXVxuICovXG5mdW5jdGlvbiBnZXRfY3VzdG9tX2VsZW1lbnRfdmFsdWUocHJvcCwgdmFsdWUsIHByb3BzX2RlZmluaXRpb24sIHRyYW5zZm9ybSkge1xuXHRjb25zdCB0eXBlID0gcHJvcHNfZGVmaW5pdGlvbltwcm9wXT8udHlwZTtcblx0dmFsdWUgPSB0eXBlID09PSAnQm9vbGVhbicgJiYgdHlwZW9mIHZhbHVlICE9PSAnYm9vbGVhbicgPyB2YWx1ZSAhPSBudWxsIDogdmFsdWU7XG5cdGlmICghdHJhbnNmb3JtIHx8ICFwcm9wc19kZWZpbml0aW9uW3Byb3BdKSB7XG5cdFx0cmV0dXJuIHZhbHVlO1xuXHR9IGVsc2UgaWYgKHRyYW5zZm9ybSA9PT0gJ3RvQXR0cmlidXRlJykge1xuXHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0Y2FzZSAnT2JqZWN0Jzpcblx0XHRcdGNhc2UgJ0FycmF5Jzpcblx0XHRcdFx0cmV0dXJuIHZhbHVlID09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuXHRcdFx0Y2FzZSAnQm9vbGVhbic6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA/ICcnIDogbnVsbDtcblx0XHRcdGNhc2UgJ051bWJlcic6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRzd2l0Y2ggKHR5cGUpIHtcblx0XHRcdGNhc2UgJ09iamVjdCc6XG5cdFx0XHRjYXNlICdBcnJheSc6XG5cdFx0XHRcdHJldHVybiB2YWx1ZSAmJiBKU09OLnBhcnNlKHZhbHVlKTtcblx0XHRcdGNhc2UgJ0Jvb2xlYW4nOlxuXHRcdFx0XHRyZXR1cm4gdmFsdWU7IC8vIGNvbnZlcnNpb24gYWxyZWFkeSBoYW5kbGVkIGFib3ZlXG5cdFx0XHRjYXNlICdOdW1iZXInOlxuXHRcdFx0XHRyZXR1cm4gdmFsdWUgIT0gbnVsbCA/ICt2YWx1ZSA6IHZhbHVlO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICpcbiAqIFR1cm4gYSBTdmVsdGUgY29tcG9uZW50IGludG8gYSBjdXN0b20gZWxlbWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLkNvbXBvbmVudFR5cGV9IENvbXBvbmVudCAgQSBTdmVsdGUgY29tcG9uZW50IGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIEN1c3RvbUVsZW1lbnRQcm9wRGVmaW5pdGlvbj59IHByb3BzX2RlZmluaXRpb24gIFRoZSBwcm9wcyB0byBvYnNlcnZlXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBzbG90cyAgVGhlIHNsb3RzIHRvIGNyZWF0ZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gYWNjZXNzb3JzICBPdGhlciBhY2Nlc3NvcnMgYmVzaWRlcyB0aGUgb25lcyBmb3IgcHJvcHMgdGhlIGNvbXBvbmVudCBoYXNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gdXNlX3NoYWRvd19kb20gIFdoZXRoZXIgdG8gdXNlIHNoYWRvdyBET01cbiAqIEBwYXJhbSB7KGNlOiBuZXcgKCkgPT4gSFRNTEVsZW1lbnQpID0+IG5ldyAoKSA9PiBIVE1MRWxlbWVudH0gW2V4dGVuZF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZV9jdXN0b21fZWxlbWVudChcblx0Q29tcG9uZW50LFxuXHRwcm9wc19kZWZpbml0aW9uLFxuXHRzbG90cyxcblx0YWNjZXNzb3JzLFxuXHR1c2Vfc2hhZG93X2RvbSxcblx0ZXh0ZW5kXG4pIHtcblx0bGV0IENsYXNzID0gY2xhc3MgZXh0ZW5kcyBTdmVsdGVFbGVtZW50IHtcblx0XHRjb25zdHJ1Y3RvcigpIHtcblx0XHRcdHN1cGVyKENvbXBvbmVudCwgc2xvdHMsIHVzZV9zaGFkb3dfZG9tKTtcblx0XHRcdHRoaXMuJCRwX2QgPSBwcm9wc19kZWZpbml0aW9uO1xuXHRcdH1cblx0XHRzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcblx0XHRcdHJldHVybiBPYmplY3Qua2V5cyhwcm9wc19kZWZpbml0aW9uKS5tYXAoKGtleSkgPT5cblx0XHRcdFx0KHByb3BzX2RlZmluaXRpb25ba2V5XS5hdHRyaWJ1dGUgfHwga2V5KS50b0xvd2VyQ2FzZSgpXG5cdFx0XHQpO1xuXHRcdH1cblx0fTtcblx0T2JqZWN0LmtleXMocHJvcHNfZGVmaW5pdGlvbikuZm9yRWFjaCgocHJvcCkgPT4ge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDbGFzcy5wcm90b3R5cGUsIHByb3AsIHtcblx0XHRcdGdldCgpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuJCRjICYmIHByb3AgaW4gdGhpcy4kJGMgPyB0aGlzLiQkY1twcm9wXSA6IHRoaXMuJCRkW3Byb3BdO1xuXHRcdFx0fSxcblx0XHRcdHNldCh2YWx1ZSkge1xuXHRcdFx0XHR2YWx1ZSA9IGdldF9jdXN0b21fZWxlbWVudF92YWx1ZShwcm9wLCB2YWx1ZSwgcHJvcHNfZGVmaW5pdGlvbik7XG5cdFx0XHRcdHRoaXMuJCRkW3Byb3BdID0gdmFsdWU7XG5cdFx0XHRcdHRoaXMuJCRjPy4kc2V0KHsgW3Byb3BdOiB2YWx1ZSB9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdGFjY2Vzc29ycy5mb3JFYWNoKChhY2Nlc3NvcikgPT4ge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDbGFzcy5wcm90b3R5cGUsIGFjY2Vzc29yLCB7XG5cdFx0XHRnZXQoKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLiQkYz8uW2FjY2Vzc29yXTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdGlmIChleHRlbmQpIHtcblx0XHQvLyBAdHMtZXhwZWN0LWVycm9yIC0gYXNzaWduaW5nIGhlcmUgaXMgZmluZVxuXHRcdENsYXNzID0gZXh0ZW5kKENsYXNzKTtcblx0fVxuXHRDb21wb25lbnQuZWxlbWVudCA9IC8qKiBAdHlwZSB7YW55fSAqLyAoQ2xhc3MpO1xuXHRyZXR1cm4gQ2xhc3M7XG59XG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgU3ZlbHRlIGNvbXBvbmVudHMuIFVzZWQgd2hlbiBkZXY9ZmFsc2UuXG4gKlxuICogQHRlbXBsYXRlIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbUHJvcHM9YW55XVxuICogQHRlbXBsYXRlIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbRXZlbnRzPWFueV1cbiAqL1xuZXhwb3J0IGNsYXNzIFN2ZWx0ZUNvbXBvbmVudCB7XG5cdC8qKlxuXHQgKiAjIyMgUFJJVkFURSBBUElcblx0ICpcblx0ICogRG8gbm90IHVzZSwgbWF5IGNoYW5nZSBhdCBhbnkgdGltZVxuXHQgKlxuXHQgKiBAdHlwZSB7YW55fVxuXHQgKi9cblx0JCQgPSB1bmRlZmluZWQ7XG5cdC8qKlxuXHQgKiAjIyMgUFJJVkFURSBBUElcblx0ICpcblx0ICogRG8gbm90IHVzZSwgbWF5IGNoYW5nZSBhdCBhbnkgdGltZVxuXHQgKlxuXHQgKiBAdHlwZSB7YW55fVxuXHQgKi9cblx0JCRzZXQgPSB1bmRlZmluZWQ7XG5cblx0LyoqIEByZXR1cm5zIHt2b2lkfSAqL1xuXHQkZGVzdHJveSgpIHtcblx0XHRkZXN0cm95X2NvbXBvbmVudCh0aGlzLCAxKTtcblx0XHR0aGlzLiRkZXN0cm95ID0gbm9vcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAdGVtcGxhdGUge0V4dHJhY3Q8a2V5b2YgRXZlbnRzLCBzdHJpbmc+fSBLXG5cdCAqIEBwYXJhbSB7S30gdHlwZVxuXHQgKiBAcGFyYW0geygoZTogRXZlbnRzW0tdKSA9PiB2b2lkKSB8IG51bGwgfCB1bmRlZmluZWR9IGNhbGxiYWNrXG5cdCAqIEByZXR1cm5zIHsoKSA9PiB2b2lkfVxuXHQgKi9cblx0JG9uKHR5cGUsIGNhbGxiYWNrKSB7XG5cdFx0aWYgKCFpc19mdW5jdGlvbihjYWxsYmFjaykpIHtcblx0XHRcdHJldHVybiBub29wO1xuXHRcdH1cblx0XHRjb25zdCBjYWxsYmFja3MgPSB0aGlzLiQkLmNhbGxiYWNrc1t0eXBlXSB8fCAodGhpcy4kJC5jYWxsYmFja3NbdHlwZV0gPSBbXSk7XG5cdFx0Y2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRjb25zdCBpbmRleCA9IGNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKTtcblx0XHRcdGlmIChpbmRleCAhPT0gLTEpIGNhbGxiYWNrcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtQYXJ0aWFsPFByb3BzPn0gcHJvcHNcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHQkc2V0KHByb3BzKSB7XG5cdFx0aWYgKHRoaXMuJCRzZXQgJiYgIWlzX2VtcHR5KHByb3BzKSkge1xuXHRcdFx0dGhpcy4kJC5za2lwX2JvdW5kID0gdHJ1ZTtcblx0XHRcdHRoaXMuJCRzZXQocHJvcHMpO1xuXHRcdFx0dGhpcy4kJC5za2lwX2JvdW5kID0gZmFsc2U7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQ3VzdG9tRWxlbWVudFByb3BEZWZpbml0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2F0dHJpYnV0ZV1cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3JlZmxlY3RdXG4gKiBAcHJvcGVydHkgeydTdHJpbmcnfCdCb29sZWFuJ3wnTnVtYmVyJ3wnQXJyYXknfCdPYmplY3QnfSBbdHlwZV1cbiAqL1xuIiwgIi8vIGdlbmVyYXRlZCBkdXJpbmcgcmVsZWFzZSwgZG8gbm90IG1vZGlmeVxuXG4vKipcbiAqIFRoZSBjdXJyZW50IHZlcnNpb24sIGFzIHNldCBpbiBwYWNrYWdlLmpzb24uXG4gKlxuICogaHR0cHM6Ly9zdmVsdGUuZGV2L2RvY3Mvc3ZlbHRlLWNvbXBpbGVyI3N2ZWx0ZS12ZXJzaW9uXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9ICc0LjIuMTEnO1xuZXhwb3J0IGNvbnN0IFBVQkxJQ19WRVJTSU9OID0gJzQnO1xuIiwgImltcG9ydCB7IFBVQkxJQ19WRVJTSU9OIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3ZlcnNpb24uanMnO1xuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpXG5cdC8vIEB0cy1pZ25vcmVcblx0KHdpbmRvdy5fX3N2ZWx0ZSB8fCAod2luZG93Ll9fc3ZlbHRlID0geyB2OiBuZXcgU2V0KCkgfSkpLnYuYWRkKFBVQkxJQ19WRVJTSU9OKTtcbiIsICI8c2NyaXB0IGxhbmc9XCJ0c1wiPlxuXHRpbXBvcnQgeyB0eXBlIEV2ZW50UmVmLCB0eXBlIFZhdWx0LCB0eXBlIFdvcmtzcGFjZSB9IGZyb20gXCJvYnNpZGlhblwiO1xuXHRpbXBvcnQgeyBjcmVhdGVUYXNrc1N0b3JlIH0gZnJvbSBcIi4vdGFza3Mvc3RvcmVcIjtcblx0aW1wb3J0IHtcblx0XHRjb2x1bW5UYWdUYWJsZVN0b3JlLFxuXHRcdGNyZWF0ZUNvbHVtblRhZ1RhYmxlLFxuXHRcdHR5cGUgQ29sdW1uQ29uZmlnLFxuXHRcdHR5cGUgQ29sdW1uVGFnLFxuXHRcdHR5cGUgRGVmYXVsdENvbHVtbnMsXG5cdH0gZnJvbSBcIi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuL3Rhc2tzL3Rhc2tcIjtcblx0aW1wb3J0IENvbHVtbiBmcm9tIFwiLi9jb21wb25lbnRzL2NvbHVtbi5zdmVsdGVcIjtcblxuXHRleHBvcnQgbGV0IHZhdWx0OiBWYXVsdDtcblx0ZXhwb3J0IGxldCB3b3Jrc3BhY2U6IFdvcmtzcGFjZTtcblx0ZXhwb3J0IGxldCByZWdpc3RlckV2ZW50OiAoZXZlbnRSZWY6IEV2ZW50UmVmKSA9PiB2b2lkO1xuXHRleHBvcnQgbGV0IGNvbHVtbkNvbmZpZzogQ29sdW1uQ29uZmlnID0ge1xuXHRcdGNvbHVtbnM6IFtcIkxhdGVyXCIsIFwiTmV4dCB3ZWVrXCIsIFwiVGhpcyB3ZWVrXCIsIFwiVG9kYXlcIiwgXCJQZW5kaW5nXCJdLFxuXHR9O1xuXG5cdCQ6IGNvbHVtblRhZ1RhYmxlU3RvcmUuc2V0KGNyZWF0ZUNvbHVtblRhZ1RhYmxlKGNvbHVtbkNvbmZpZykpO1xuXG5cdGNvbnN0IHsgdGFza3NTdG9yZSwgdGFza0FjdGlvbnMgfSA9IGNyZWF0ZVRhc2tzU3RvcmUoXG5cdFx0dmF1bHQsXG5cdFx0d29ya3NwYWNlLFxuXHRcdHJlZ2lzdGVyRXZlbnQsXG5cdFx0Y29sdW1uVGFnVGFibGVTdG9yZSxcblx0KTtcblxuXHRmdW5jdGlvbiBncm91cEJ5Q29sdW1uVGFnKFxuXHRcdHRhc2tzOiBUYXNrW10sXG5cdCk6IFJlY29yZDxDb2x1bW5UYWcgfCBEZWZhdWx0Q29sdW1ucywgVGFza1tdPiB7XG5cdFx0Y29uc3Qgb3V0cHV0OiBSZWNvcmQ8Q29sdW1uVGFnIHwgRGVmYXVsdENvbHVtbnMsIFRhc2tbXT4gPSB7XG5cdFx0XHR1bmNhdGVnb3Jpc2VkOiBbXSxcblx0XHRcdGRvbmU6IFtdLFxuXHRcdH07XG5cdFx0Zm9yIChjb25zdCB0YXNrIG9mIHRhc2tzKSB7XG5cdFx0XHRpZiAodGFzay5kb25lKSB7XG5cdFx0XHRcdG91dHB1dFtcImRvbmVcIl0gPSBvdXRwdXRbXCJkb25lXCJdLmNvbmNhdCh0YXNrKTtcblx0XHRcdH0gZWxzZSBpZiAodGFzay5jb2x1bW4pIHtcblx0XHRcdFx0b3V0cHV0W3Rhc2suY29sdW1uXSA9IChvdXRwdXRbdGFzay5jb2x1bW5dID8/IFtdKS5jb25jYXQodGFzayk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXRbXCJ1bmNhdGVnb3Jpc2VkXCJdID0gb3V0cHV0W1widW5jYXRlZ29yaXNlZFwiXS5jb25jYXQodGFzayk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH1cblxuXHRsZXQgY29sdW1uczogKFwidW5jYXRlZ29yaXNlZFwiIHwgQ29sdW1uVGFnKVtdO1xuXHQkOiBjb2x1bW5zID0gT2JqZWN0LmtleXMoJGNvbHVtblRhZ1RhYmxlU3RvcmUpIGFzIENvbHVtblRhZ1tdO1xuXG5cdCQ6IHRhc2tzQnlDb2x1bW4gPSBncm91cEJ5Q29sdW1uVGFnKCR0YXNrc1N0b3JlKTtcbjwvc2NyaXB0PlxuXG48c2VjdGlvbj5cblx0PGgxPlByb2plY3QgUGxhbm5lcjwvaDE+XG5cdDxkaXYgY2xhc3M9XCJjb2x1bW5zXCI+XG5cdFx0PGRpdj5cblx0XHRcdDxDb2x1bW5cblx0XHRcdFx0Y29sdW1uPXtcInVuY2F0ZWdvcmlzZWRcIn1cblx0XHRcdFx0aGlkZU9uRW1wdHk9e3RydWV9XG5cdFx0XHRcdHRhc2tzPXt0YXNrc0J5Q29sdW1uW1widW5jYXRlZ29yaXNlZFwiXX1cblx0XHRcdFx0e3Rhc2tBY3Rpb25zfVxuXHRcdFx0Lz5cblx0XHRcdHsjZWFjaCBjb2x1bW5zIGFzIGNvbHVtbn1cblx0XHRcdFx0PENvbHVtblxuXHRcdFx0XHRcdHtjb2x1bW59XG5cdFx0XHRcdFx0dGFza3M9e3Rhc2tzQnlDb2x1bW5bY29sdW1uXSA/PyBbXX1cblx0XHRcdFx0XHR7dGFza0FjdGlvbnN9XG5cdFx0XHRcdC8+XG5cdFx0XHR7L2VhY2h9XG5cdFx0XHQ8Q29sdW1uXG5cdFx0XHRcdGNvbHVtbj1cImRvbmVcIlxuXHRcdFx0XHR0YXNrcz17dGFza3NCeUNvbHVtbltcImRvbmVcIl0gPz8gW119XG5cdFx0XHRcdHt0YXNrQWN0aW9uc31cblx0XHRcdC8+XG5cdFx0PC9kaXY+XG5cdDwvZGl2PlxuPC9zZWN0aW9uPlxuXG48c3R5bGU+XG5cdC5jb2x1bW5zIHtcblx0XHRtYXgtd2lkdGg6IDEwMHZ3O1xuXHRcdG92ZXJmbG93LXg6IHNjcm9sbDtcblx0XHRwYWRkaW5nLWJvdHRvbTogdmFyKC0tc2l6ZS00LTMpO1xuXHR9XG5cblx0LmNvbHVtbnMgPiBkaXYge1xuXHRcdGRpc3BsYXk6IGZsZXg7XG5cdFx0Z2FwOiB2YXIoLS1zaXplLTQtMyk7XG5cdH1cbjwvc3R5bGU+XG4iLCAiaW1wb3J0IHsgVEZpbGUsIFZhdWx0LCB0eXBlIEV2ZW50UmVmLCBXb3Jrc3BhY2UgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IHVwZGF0ZU1hcHNGcm9tRmlsZSwgdHlwZSBNZXRhZGF0YSB9IGZyb20gXCIuL3Rhc2tzXCI7XG5pbXBvcnQgeyBUYXNrIH0gZnJvbSBcIi4vdGFza1wiO1xuaW1wb3J0IHsgd3JpdGFibGUsIHR5cGUgV3JpdGFibGUgfSBmcm9tIFwic3ZlbHRlL3N0b3JlXCI7XG5pbXBvcnQgdHlwZSB7IENvbHVtblRhZ1RhYmxlIH0gZnJvbSBcIi4uL2NvbHVtbnMvY29sdW1uc1wiO1xuaW1wb3J0IHsgY3JlYXRlVGFza0FjdGlvbnMsIHR5cGUgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi9hY3Rpb25zXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUYXNrc1N0b3JlKFxuXHR2YXVsdDogVmF1bHQsXG5cdHdvcmtzcGFjZTogV29ya3NwYWNlLFxuXHRyZWdpc3RlckV2ZW50OiAoZXZlbnRSZWY6IEV2ZW50UmVmKSA9PiB2b2lkLFxuXHRjb2x1bW5UYWdUYWJsZVN0b3JlOiBXcml0YWJsZTxDb2x1bW5UYWdUYWJsZT5cbik6IHsgdGFza3NTdG9yZTogV3JpdGFibGU8VGFza1tdPjsgdGFza0FjdGlvbnM6IFRhc2tBY3Rpb25zIH0ge1xuXHRjb25zdCB0YXNrc1N0b3JlID0gd3JpdGFibGU8VGFza1tdPihbXSk7XG5cdGxldCB0aW1lcjogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG5cdGNvbnN0IHRhc2tzQnlUYXNrSWQgPSBuZXcgTWFwPHN0cmluZywgVGFzaz4oKTtcblx0Y29uc3QgbWV0YWRhdGFCeVRhc2tJZCA9IG5ldyBNYXA8c3RyaW5nLCBNZXRhZGF0YT4oKTtcblx0Y29uc3QgdGFza0lkc0J5RmlsZUhhbmRsZSA9IG5ldyBNYXA8VEZpbGUsIFNldDxzdHJpbmc+PigpO1xuXG5cdGNvbnN0IGZpbGVIYW5kbGVzID0gdmF1bHQuZ2V0TWFya2Rvd25GaWxlcygpO1xuXG5cdGZ1bmN0aW9uIGRlYm91bmNlU2V0VGFza3MoKSB7XG5cdFx0aWYgKCF0aW1lcikge1xuXHRcdFx0dGltZXIgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdHRpbWVyID0gdW5kZWZpbmVkO1xuXHRcdFx0XHR0YXNrc1N0b3JlLnNldChbLi4udGFza3NCeVRhc2tJZC52YWx1ZXMoKV0pO1xuXHRcdFx0fSwgNTApO1xuXHRcdH1cblx0fVxuXG5cdGZvciAoY29uc3QgZmlsZUhhbmRsZSBvZiBmaWxlSGFuZGxlcykge1xuXHRcdHVwZGF0ZU1hcHNGcm9tRmlsZSh7XG5cdFx0XHRmaWxlSGFuZGxlLFxuXHRcdFx0dGFza3NCeVRhc2tJZCxcblx0XHRcdG1ldGFkYXRhQnlUYXNrSWQsXG5cdFx0XHR0YXNrSWRzQnlGaWxlSGFuZGxlLFxuXHRcdFx0dmF1bHQsXG5cdFx0XHRjb2x1bW5UYWdUYWJsZVN0b3JlLFxuXHRcdH0pLnRoZW4oKCkgPT4ge1xuXHRcdFx0ZGVib3VuY2VTZXRUYXNrcygpO1xuXHRcdH0pO1xuXHR9XG5cblx0cmVnaXN0ZXJFdmVudChcblx0XHR2YXVsdC5vbihcIm1vZGlmeVwiLCAoZmlsZUhhbmRsZSkgPT4ge1xuXHRcdFx0aWYgKGZpbGVIYW5kbGUgaW5zdGFuY2VvZiBURmlsZSkge1xuXHRcdFx0XHR1cGRhdGVNYXBzRnJvbUZpbGUoe1xuXHRcdFx0XHRcdGZpbGVIYW5kbGUsXG5cdFx0XHRcdFx0dGFza3NCeVRhc2tJZCxcblx0XHRcdFx0XHRtZXRhZGF0YUJ5VGFza0lkLFxuXHRcdFx0XHRcdHRhc2tJZHNCeUZpbGVIYW5kbGUsXG5cdFx0XHRcdFx0dmF1bHQsXG5cdFx0XHRcdFx0Y29sdW1uVGFnVGFibGVTdG9yZSxcblx0XHRcdFx0fSkudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0ZGVib3VuY2VTZXRUYXNrcygpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KVxuXHQpO1xuXG5cdHJlZ2lzdGVyRXZlbnQoXG5cdFx0dmF1bHQub24oXCJjcmVhdGVcIiwgKGZpbGVIYW5kbGUpID0+IHtcblx0XHRcdGlmIChmaWxlSGFuZGxlIGluc3RhbmNlb2YgVEZpbGUpIHtcblx0XHRcdFx0dXBkYXRlTWFwc0Zyb21GaWxlKHtcblx0XHRcdFx0XHRmaWxlSGFuZGxlLFxuXHRcdFx0XHRcdHRhc2tzQnlUYXNrSWQsXG5cdFx0XHRcdFx0bWV0YWRhdGFCeVRhc2tJZCxcblx0XHRcdFx0XHR0YXNrSWRzQnlGaWxlSGFuZGxlLFxuXHRcdFx0XHRcdHZhdWx0LFxuXHRcdFx0XHRcdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG5cdFx0XHRcdH0pLnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdGRlYm91bmNlU2V0VGFza3MoKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRyZWdpc3RlckV2ZW50KFxuXHRcdHZhdWx0Lm9uKFwiZGVsZXRlXCIsIChmaWxlSGFuZGxlKSA9PiB7XG5cdFx0XHRpZiAoZmlsZUhhbmRsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XG5cdFx0XHRcdC8vIFRPRE8gaW1wbGVtZW50XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRyZWdpc3RlckV2ZW50KFxuXHRcdHZhdWx0Lm9uKFwicmVuYW1lXCIsIChmaWxlSGFuZGxlKSA9PiB7XG5cdFx0XHRpZiAoZmlsZUhhbmRsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XG5cdFx0XHRcdC8vIFRPRE8gaW1wbGVtZW50XG5cdFx0XHR9XG5cdFx0fSlcblx0KTtcblxuXHRjb25zdCB0YXNrQWN0aW9ucyA9IGNyZWF0ZVRhc2tBY3Rpb25zKHtcblx0XHR0YXNrc0J5VGFza0lkLFxuXHRcdG1ldGFkYXRhQnlUYXNrSWQsXG5cdFx0dmF1bHQsXG5cdFx0d29ya3NwYWNlLFxuXHR9KTtcblxuXHRyZXR1cm4geyB0YXNrc1N0b3JlLCB0YXNrQWN0aW9ucyB9O1xufVxuIiwgImltcG9ydCBzaGEyNTYgZnJvbSBcImNyeXB0by1qcy9zaGEyNTZcIjtcbmltcG9ydCB0eXBlIHsgQnJhbmQgfSBmcm9tIFwic3JjL2JyYW5kXCI7XG5pbXBvcnQgdHlwZSB7XG5cdENvbHVtblRhZyxcblx0Q29sdW1uVGFnVGFibGUsXG5cdERlZmF1bHRDb2x1bW5zLFxufSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cbmV4cG9ydCBjbGFzcyBUYXNrIHtcblx0cmVhZG9ubHkgaWQ6IHN0cmluZztcblx0cmVhZG9ubHkgY29udGVudDogc3RyaW5nO1xuXHRyZWFkb25seSBkb25lOiBib29sZWFuO1xuXHRyZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cdHJlYWRvbmx5IHJvd0luZGV4OiBudW1iZXI7XG5cdHJlYWRvbmx5IGNvbHVtbjpcblx0XHR8IENvbHVtblRhZ1xuXHRcdHwgRXhjbHVkZTxEZWZhdWx0Q29sdW1ucywgXCJ1bmNhdGVnb3Jpc2VkXCI+XG5cdFx0fCB1bmRlZmluZWQ7XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cmF3Q29udGVudDogVGFza1N0cmluZyxcblx0XHRmaWxlSGFuZGxlOiB7IHBhdGg6IHN0cmluZyB9LFxuXHRcdHJvd0luZGV4OiBudW1iZXIsXG5cdFx0Y29sdW1uVGFnVGFibGU6IENvbHVtblRhZ1RhYmxlXG5cdCkge1xuXHRcdGNvbnN0IHRhc2sgPSB0aGlzLl9kZXNlcmlhbGlzZShyYXdDb250ZW50LCBmaWxlSGFuZGxlLCByb3dJbmRleCk7XG5cdFx0dGhpcy5pZCA9IHRhc2suaWQ7XG5cdFx0dGhpcy5jb250ZW50ID0gdGFzay5jb250ZW50O1xuXHRcdHRoaXMuZG9uZSA9IHRhc2suZG9uZTtcblx0XHR0aGlzLnBhdGggPSBmaWxlSGFuZGxlLnBhdGg7XG5cdFx0dGhpcy5yb3dJbmRleCA9IHJvd0luZGV4O1xuXG5cdFx0bGV0IGNvbHVtbjogQ29sdW1uVGFnIHwgdW5kZWZpbmVkO1xuXHRcdGZvciAoY29uc3QgdGFnIG9mIHRhc2sudGFncykge1xuXHRcdFx0aWYgKHRhZyBpbiBjb2x1bW5UYWdUYWJsZSB8fCB0YWcgPT09IFwiZG9uZVwiKSB7XG5cdFx0XHRcdGNvbHVtbiA9IHRhZyBhcyBDb2x1bW5UYWc7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuY29sdW1uID0gY29sdW1uO1xuXHR9XG5cblx0cHJpdmF0ZSBfZGVzZXJpYWxpc2UoXG5cdFx0cmF3Q29udGVudDogVGFza1N0cmluZyxcblx0XHRmaWxlSGFuZGxlOiB7IHBhdGg6IHN0cmluZyB9LFxuXHRcdHJvd0luZGV4OiBudW1iZXJcblx0KToge1xuXHRcdGlkOiBzdHJpbmc7XG5cdFx0Y29udGVudDogc3RyaW5nO1xuXHRcdGRvbmU6IGJvb2xlYW47XG5cdFx0dGFnczogc3RyaW5nW107XG5cdH0ge1xuXHRcdGNvbnN0IFssIHJlbWFpbmRlciA9IFwiXCJdID0gcmF3Q29udGVudC5zcGxpdChcIi0gW1wiKTtcblx0XHRjb25zdCBbc3RhdHVzLCBjb250ZW50ID0gXCJcIl0gPSByZW1haW5kZXIuc3BsaXQoXCJdIFwiKTtcblxuXHRcdGNvbnN0IHsgdGFncywgY2xlYW5lZENvbnRlbnQgfSA9IGdldFRhZ3MoY29udGVudCk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0aWQ6IHNoYTI1Nihjb250ZW50ICsgZmlsZUhhbmRsZS5wYXRoICsgcm93SW5kZXgpLnRvU3RyaW5nKCksXG5cdFx0XHRkb25lOiBzdGF0dXMgPT09IFwieFwiLFxuXHRcdFx0Y29udGVudDogY2xlYW5lZENvbnRlbnQsXG5cdFx0XHR0YWdzLFxuXHRcdH07XG5cdH1cblxuXHRzZXJpYWxpc2UoXG5cdFx0ZGF0YTogUGFydGlhbDx7XG5cdFx0XHRjb2x1bW46IENvbHVtblRhZyB8IEV4Y2x1ZGU8RGVmYXVsdENvbHVtbnMsIFwidW5jYXRlZ29yaXNlZFwiPjtcblx0XHR9PlxuXHQpOiBzdHJpbmcge1xuXHRcdGNvbnN0IGRvbmUgPSBkYXRhLmNvbHVtbiA9PT0gXCJkb25lXCIgfHwgdGhpcy5kb25lO1xuXHRcdGNvbnN0IGNvbHVtbjpcblx0XHRcdHwgQ29sdW1uVGFnXG5cdFx0XHR8IEV4Y2x1ZGU8RGVmYXVsdENvbHVtbnMsIFwidW5jYXRlZ29yaXNlZFwiPlxuXHRcdFx0fCB1bmRlZmluZWQgPSBkYXRhLmNvbHVtbiA/PyB0aGlzLmNvbHVtbjtcblxuXHRcdHJldHVybiBgLSBbJHtkb25lID8gXCJ4XCIgOiBcIiBcIn1dICR7dGhpcy5jb250ZW50fSR7XG5cdFx0XHRjb2x1bW4gPyBgICMke2NvbHVtbn1gIDogXCJcIlxuXHRcdH1gO1xuXHR9XG59XG5cbnR5cGUgVGFza1N0cmluZyA9IEJyYW5kPHN0cmluZywgXCJUYXNrU3RyaW5nXCI+O1xuXG5leHBvcnQgZnVuY3Rpb24gaXNUYXNrU3RyaW5nKGlucHV0OiBzdHJpbmcpOiBpbnB1dCBpcyBUYXNrU3RyaW5nIHtcblx0cmV0dXJuIHRhc2tTdHJpbmdSZWdleC50ZXN0KGlucHV0KTtcbn1cblxuLy8gYmVnaW5zIHdpdGggMCBvciBtb3JlIHdoaXRlc3BhY2UgY2hhcnNcbi8vIHRoZW4gZm9sbG93cyB0aGUgcGF0dGVybiBcIi0gWyBdXCIgT1IgXCItIFt4XVwiXG4vLyB0aGVuIGNvbnRhaW5zIGFuIGFkZGl0aW9uYWwgd2hpdGVzcGFjZSBiZWZvcmUgYW55IHRyYWlsaW5nIGNvbnRlbnRcbmNvbnN0IHRhc2tTdHJpbmdSZWdleCA9IC9eXFxzKi1cXHNcXFtbeFxcc11cXF1cXHMvO1xuXG5mdW5jdGlvbiBnZXRUYWdzKGNvbnRlbnQ6IHN0cmluZyk6IHsgdGFnczogc3RyaW5nW107IGNsZWFuZWRDb250ZW50OiBzdHJpbmcgfSB7XG5cdGNvbnN0IHRhZ3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcblx0bGV0IGNsZWFuZWRDb250ZW50ID0gY29udGVudDtcblxuXHQvLyBzdGFydHMgd2l0aCBcIiNcIiwgZW5kcyB3aXRoIFwiIFwiLCBvbmx5IGNvbnRhaW5zIGFscGhhbnVtZXJpY3Mgb3IgXCItXCJcblx0Y29uc3QgYWxsTWF0Y2hlcyA9IGNvbnRlbnQubWF0Y2hBbGwoLyMoW1xcdy1dKykvZyk7XG5cdGZvciAoY29uc3QgbWF0Y2ggb2YgWy4uLmFsbE1hdGNoZXNdKSB7XG5cdFx0Y29uc3QgbWF5YmVUYWcgPSBtYXRjaFsxXTtcblx0XHRpZiAobWF5YmVUYWcpIHtcblx0XHRcdHRhZ3MuYWRkKG1heWJlVGFnKTtcblxuXHRcdFx0Y2xlYW5lZENvbnRlbnQgPSBjbGVhbmVkQ29udGVudC5yZXBsYWNlQWxsKGAjJHttYXliZVRhZ31gLCBcIlwiKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4geyB0YWdzOiBbLi4udGFnc10sIGNsZWFuZWRDb250ZW50OiBjbGVhbmVkQ29udGVudC50cmltKCkgfTtcbn1cbiIsICJpbXBvcnQge1xuXHRydW5fYWxsLFxuXHRzdWJzY3JpYmUsXG5cdG5vb3AsXG5cdHNhZmVfbm90X2VxdWFsLFxuXHRpc19mdW5jdGlvbixcblx0Z2V0X3N0b3JlX3ZhbHVlXG59IGZyb20gJy4uL2ludGVybmFsL2luZGV4LmpzJztcblxuY29uc3Qgc3Vic2NyaWJlcl9xdWV1ZSA9IFtdO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBgUmVhZGFibGVgIHN0b3JlIHRoYXQgYWxsb3dzIHJlYWRpbmcgYnkgc3Vic2NyaXB0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNyZWFkYWJsZVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7VH0gW3ZhbHVlXSBpbml0aWFsIHZhbHVlXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdGFydFN0b3BOb3RpZmllcjxUPn0gW3N0YXJ0XVxuICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5SZWFkYWJsZTxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRhYmxlKHZhbHVlLCBzdGFydCkge1xuXHRyZXR1cm4ge1xuXHRcdHN1YnNjcmliZTogd3JpdGFibGUodmFsdWUsIHN0YXJ0KS5zdWJzY3JpYmVcblx0fTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBgV3JpdGFibGVgIHN0b3JlIHRoYXQgYWxsb3dzIGJvdGggdXBkYXRpbmcgYW5kIHJlYWRpbmcgYnkgc3Vic2NyaXB0aW9uLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSN3cml0YWJsZVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7VH0gW3ZhbHVlXSBpbml0aWFsIHZhbHVlXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdGFydFN0b3BOb3RpZmllcjxUPn0gW3N0YXJ0XVxuICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5Xcml0YWJsZTxUPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRhYmxlKHZhbHVlLCBzdGFydCA9IG5vb3ApIHtcblx0LyoqIEB0eXBlIHtpbXBvcnQoJy4vcHVibGljLmpzJykuVW5zdWJzY3JpYmVyfSAqL1xuXHRsZXQgc3RvcDtcblx0LyoqIEB0eXBlIHtTZXQ8aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdWJzY3JpYmVJbnZhbGlkYXRlVHVwbGU8VD4+fSAqL1xuXHRjb25zdCBzdWJzY3JpYmVycyA9IG5ldyBTZXQoKTtcblx0LyoqIEBwYXJhbSB7VH0gbmV3X3ZhbHVlXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxuXHQgKi9cblx0ZnVuY3Rpb24gc2V0KG5ld192YWx1ZSkge1xuXHRcdGlmIChzYWZlX25vdF9lcXVhbCh2YWx1ZSwgbmV3X3ZhbHVlKSkge1xuXHRcdFx0dmFsdWUgPSBuZXdfdmFsdWU7XG5cdFx0XHRpZiAoc3RvcCkge1xuXHRcdFx0XHQvLyBzdG9yZSBpcyByZWFkeVxuXHRcdFx0XHRjb25zdCBydW5fcXVldWUgPSAhc3Vic2NyaWJlcl9xdWV1ZS5sZW5ndGg7XG5cdFx0XHRcdGZvciAoY29uc3Qgc3Vic2NyaWJlciBvZiBzdWJzY3JpYmVycykge1xuXHRcdFx0XHRcdHN1YnNjcmliZXJbMV0oKTtcblx0XHRcdFx0XHRzdWJzY3JpYmVyX3F1ZXVlLnB1c2goc3Vic2NyaWJlciwgdmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChydW5fcXVldWUpIHtcblx0XHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHN1YnNjcmliZXJfcXVldWUubGVuZ3RoOyBpICs9IDIpIHtcblx0XHRcdFx0XHRcdHN1YnNjcmliZXJfcXVldWVbaV1bMF0oc3Vic2NyaWJlcl9xdWV1ZVtpICsgMV0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzdWJzY3JpYmVyX3F1ZXVlLmxlbmd0aCA9IDA7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQHBhcmFtIHtpbXBvcnQoJy4vcHVibGljLmpzJykuVXBkYXRlcjxUPn0gZm5cblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRmdW5jdGlvbiB1cGRhdGUoZm4pIHtcblx0XHRzZXQoZm4odmFsdWUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAcGFyYW0ge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5TdWJzY3JpYmVyPFQ+fSBydW5cblx0ICogQHBhcmFtIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLkludmFsaWRhdG9yPFQ+fSBbaW52YWxpZGF0ZV1cblx0ICogQHJldHVybnMge2ltcG9ydCgnLi9wdWJsaWMuanMnKS5VbnN1YnNjcmliZXJ9XG5cdCAqL1xuXHRmdW5jdGlvbiBzdWJzY3JpYmUocnVuLCBpbnZhbGlkYXRlID0gbm9vcCkge1xuXHRcdC8qKiBAdHlwZSB7aW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdWJzY3JpYmVJbnZhbGlkYXRlVHVwbGU8VD59ICovXG5cdFx0Y29uc3Qgc3Vic2NyaWJlciA9IFtydW4sIGludmFsaWRhdGVdO1xuXHRcdHN1YnNjcmliZXJzLmFkZChzdWJzY3JpYmVyKTtcblx0XHRpZiAoc3Vic2NyaWJlcnMuc2l6ZSA9PT0gMSkge1xuXHRcdFx0c3RvcCA9IHN0YXJ0KHNldCwgdXBkYXRlKSB8fCBub29wO1xuXHRcdH1cblx0XHRydW4odmFsdWUpO1xuXHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRzdWJzY3JpYmVycy5kZWxldGUoc3Vic2NyaWJlcik7XG5cdFx0XHRpZiAoc3Vic2NyaWJlcnMuc2l6ZSA9PT0gMCAmJiBzdG9wKSB7XG5cdFx0XHRcdHN0b3AoKTtcblx0XHRcdFx0c3RvcCA9IG51bGw7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXHRyZXR1cm4geyBzZXQsIHVwZGF0ZSwgc3Vic2NyaWJlIH07XG59XG5cbi8qKlxuICogRGVyaXZlZCB2YWx1ZSBzdG9yZSBieSBzeW5jaHJvbml6aW5nIG9uZSBvciBtb3JlIHJlYWRhYmxlIHN0b3JlcyBhbmRcbiAqIGFwcGx5aW5nIGFuIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIG92ZXIgaXRzIGlucHV0IHZhbHVlcy5cbiAqXG4gKiBodHRwczovL3N2ZWx0ZS5kZXYvZG9jcy9zdmVsdGUtc3RvcmUjZGVyaXZlZFxuICogQHRlbXBsYXRlIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc30gU1xuICogQHRlbXBsYXRlIFRcbiAqIEBvdmVybG9hZFxuICogQHBhcmFtIHtTfSBzdG9yZXMgLSBpbnB1dCBzdG9yZXNcbiAqIEBwYXJhbSB7KHZhbHVlczogaW1wb3J0KCcuL3ByaXZhdGUuanMnKS5TdG9yZXNWYWx1ZXM8Uz4sIHNldDogKHZhbHVlOiBUKSA9PiB2b2lkLCB1cGRhdGU6IChmbjogaW1wb3J0KCcuL3B1YmxpYy5qcycpLlVwZGF0ZXI8VD4pID0+IHZvaWQpID0+IGltcG9ydCgnLi9wdWJsaWMuanMnKS5VbnN1YnNjcmliZXIgfCB2b2lkfSBmbiAtIGZ1bmN0aW9uIGNhbGxiYWNrIHRoYXQgYWdncmVnYXRlcyB0aGUgdmFsdWVzXG4gKiBAcGFyYW0ge1R9IFtpbml0aWFsX3ZhbHVlXSAtIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8VD59XG4gKi9cblxuLyoqXG4gKiBEZXJpdmVkIHZhbHVlIHN0b3JlIGJ5IHN5bmNocm9uaXppbmcgb25lIG9yIG1vcmUgcmVhZGFibGUgc3RvcmVzIGFuZFxuICogYXBwbHlpbmcgYW4gYWdncmVnYXRpb24gZnVuY3Rpb24gb3ZlciBpdHMgaW5wdXQgdmFsdWVzLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNkZXJpdmVkXG4gKiBAdGVtcGxhdGUge2ltcG9ydCgnLi9wcml2YXRlLmpzJykuU3RvcmVzfSBTXG4gKiBAdGVtcGxhdGUgVFxuICogQG92ZXJsb2FkXG4gKiBAcGFyYW0ge1N9IHN0b3JlcyAtIGlucHV0IHN0b3Jlc1xuICogQHBhcmFtIHsodmFsdWVzOiBpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc1ZhbHVlczxTPikgPT4gVH0gZm4gLSBmdW5jdGlvbiBjYWxsYmFjayB0aGF0IGFnZ3JlZ2F0ZXMgdGhlIHZhbHVlc1xuICogQHBhcmFtIHtUfSBbaW5pdGlhbF92YWx1ZV0gLSBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fVxuICovXG5cbi8qKlxuICogQHRlbXBsYXRlIHtpbXBvcnQoJy4vcHJpdmF0ZS5qcycpLlN0b3Jlc30gU1xuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7U30gc3RvcmVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHBhcmFtIHtUfSBbaW5pdGlhbF92YWx1ZV1cbiAqIEByZXR1cm5zIHtpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8VD59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVkKHN0b3JlcywgZm4sIGluaXRpYWxfdmFsdWUpIHtcblx0Y29uc3Qgc2luZ2xlID0gIUFycmF5LmlzQXJyYXkoc3RvcmVzKTtcblx0LyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoJy4vcHVibGljLmpzJykuUmVhZGFibGU8YW55Pj59ICovXG5cdGNvbnN0IHN0b3Jlc19hcnJheSA9IHNpbmdsZSA/IFtzdG9yZXNdIDogc3RvcmVzO1xuXHRpZiAoIXN0b3Jlc19hcnJheS5ldmVyeShCb29sZWFuKSkge1xuXHRcdHRocm93IG5ldyBFcnJvcignZGVyaXZlZCgpIGV4cGVjdHMgc3RvcmVzIGFzIGlucHV0LCBnb3QgYSBmYWxzeSB2YWx1ZScpO1xuXHR9XG5cdGNvbnN0IGF1dG8gPSBmbi5sZW5ndGggPCAyO1xuXHRyZXR1cm4gcmVhZGFibGUoaW5pdGlhbF92YWx1ZSwgKHNldCwgdXBkYXRlKSA9PiB7XG5cdFx0bGV0IHN0YXJ0ZWQgPSBmYWxzZTtcblx0XHRjb25zdCB2YWx1ZXMgPSBbXTtcblx0XHRsZXQgcGVuZGluZyA9IDA7XG5cdFx0bGV0IGNsZWFudXAgPSBub29wO1xuXHRcdGNvbnN0IHN5bmMgPSAoKSA9PiB7XG5cdFx0XHRpZiAocGVuZGluZykge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjbGVhbnVwKCk7XG5cdFx0XHRjb25zdCByZXN1bHQgPSBmbihzaW5nbGUgPyB2YWx1ZXNbMF0gOiB2YWx1ZXMsIHNldCwgdXBkYXRlKTtcblx0XHRcdGlmIChhdXRvKSB7XG5cdFx0XHRcdHNldChyZXN1bHQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y2xlYW51cCA9IGlzX2Z1bmN0aW9uKHJlc3VsdCkgPyByZXN1bHQgOiBub29wO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Y29uc3QgdW5zdWJzY3JpYmVycyA9IHN0b3Jlc19hcnJheS5tYXAoKHN0b3JlLCBpKSA9PlxuXHRcdFx0c3Vic2NyaWJlKFxuXHRcdFx0XHRzdG9yZSxcblx0XHRcdFx0KHZhbHVlKSA9PiB7XG5cdFx0XHRcdFx0dmFsdWVzW2ldID0gdmFsdWU7XG5cdFx0XHRcdFx0cGVuZGluZyAmPSB+KDEgPDwgaSk7XG5cdFx0XHRcdFx0aWYgKHN0YXJ0ZWQpIHtcblx0XHRcdFx0XHRcdHN5bmMoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdCgpID0+IHtcblx0XHRcdFx0XHRwZW5kaW5nIHw9IDEgPDwgaTtcblx0XHRcdFx0fVxuXHRcdFx0KVxuXHRcdCk7XG5cdFx0c3RhcnRlZCA9IHRydWU7XG5cdFx0c3luYygpO1xuXHRcdHJldHVybiBmdW5jdGlvbiBzdG9wKCkge1xuXHRcdFx0cnVuX2FsbCh1bnN1YnNjcmliZXJzKTtcblx0XHRcdGNsZWFudXAoKTtcblx0XHRcdC8vIFdlIG5lZWQgdG8gc2V0IHRoaXMgdG8gZmFsc2UgYmVjYXVzZSBjYWxsYmFja3MgY2FuIHN0aWxsIGhhcHBlbiBkZXNwaXRlIGhhdmluZyB1bnN1YnNjcmliZWQ6XG5cdFx0XHQvLyBDYWxsYmFja3MgbWlnaHQgYWxyZWFkeSBiZSBwbGFjZWQgaW4gdGhlIHF1ZXVlIHdoaWNoIGRvZXNuJ3Qga25vdyBpdCBzaG91bGQgbm8gbG9uZ2VyXG5cdFx0XHQvLyBpbnZva2UgdGhpcyBkZXJpdmVkIHN0b3JlLlxuXHRcdFx0c3RhcnRlZCA9IGZhbHNlO1xuXHRcdH07XG5cdH0pO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc3RvcmUgYW5kIHJldHVybnMgYSBuZXcgb25lIGRlcml2ZWQgZnJvbSB0aGUgb2xkIG9uZSB0aGF0IGlzIHJlYWRhYmxlLlxuICpcbiAqIGh0dHBzOi8vc3ZlbHRlLmRldi9kb2NzL3N2ZWx0ZS1zdG9yZSNyZWFkb25seVxuICogQHRlbXBsYXRlIFRcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fSBzdG9yZSAgLSBzdG9yZSB0byBtYWtlIHJlYWRvbmx5XG4gKiBAcmV0dXJucyB7aW1wb3J0KCcuL3B1YmxpYy5qcycpLlJlYWRhYmxlPFQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZG9ubHkoc3RvcmUpIHtcblx0cmV0dXJuIHtcblx0XHRzdWJzY3JpYmU6IHN0b3JlLnN1YnNjcmliZS5iaW5kKHN0b3JlKVxuXHR9O1xufVxuXG5leHBvcnQgeyBnZXRfc3RvcmVfdmFsdWUgYXMgZ2V0IH07XG4iLCAiaW1wb3J0IHR5cGUgeyBURmlsZSwgVmF1bHQgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IGlzVGFza1N0cmluZywgVGFzayB9IGZyb20gXCIuL3Rhc2tcIjtcbmltcG9ydCB0eXBlIHsgQ29sdW1uVGFnVGFibGUgfSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5pbXBvcnQgeyBnZXQsIHR5cGUgV3JpdGFibGUgfSBmcm9tIFwic3ZlbHRlL3N0b3JlXCI7XG5cbmV4cG9ydCB0eXBlIE1ldGFkYXRhID0ge1xuXHRyb3dJbmRleDogbnVtYmVyO1xuXHRmaWxlSGFuZGxlOiBURmlsZTtcbn07XG5cbi8qKlxuICogbXV0YXRlcyB0aGUgc3VwcGxpZWQgTWFwc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlTWFwc0Zyb21GaWxlKHtcblx0ZmlsZUhhbmRsZSxcblx0dGFza0lkc0J5RmlsZUhhbmRsZSxcblx0dGFza3NCeVRhc2tJZCxcblx0bWV0YWRhdGFCeVRhc2tJZCxcblx0dmF1bHQsXG5cdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG59OiB7XG5cdGZpbGVIYW5kbGU6IFRGaWxlO1xuXHR0YXNrc0J5VGFza0lkOiBNYXA8c3RyaW5nLCBUYXNrPjtcblx0bWV0YWRhdGFCeVRhc2tJZDogTWFwPHN0cmluZywgTWV0YWRhdGE+O1xuXHR0YXNrSWRzQnlGaWxlSGFuZGxlOiBNYXA8VEZpbGUsIFNldDxzdHJpbmc+Pjtcblx0dmF1bHQ6IFZhdWx0O1xuXHRjb2x1bW5UYWdUYWJsZVN0b3JlOiBXcml0YWJsZTxDb2x1bW5UYWdUYWJsZT47XG59KSB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgcHJldmlvdXNUYXNrSWRzID1cblx0XHRcdHRhc2tJZHNCeUZpbGVIYW5kbGUuZ2V0KGZpbGVIYW5kbGUpID8/IG5ldyBTZXQoKTtcblx0XHRjb25zdCBuZXdUYXNrSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cblx0XHRjb25zdCBjb250ZW50cyA9IGF3YWl0IHZhdWx0LnJlYWQoZmlsZUhhbmRsZSk7XG5cdFx0Y29uc3Qgcm93cyA9IGNvbnRlbnRzLnNwbGl0KFwiXFxuXCIpO1xuXHRcdGNvbnN0IGNvbHVtblRhZ1RhYmxlID0gZ2V0KGNvbHVtblRhZ1RhYmxlU3RvcmUpO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCByb3dzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCByb3cgPSByb3dzW2ldO1xuXHRcdFx0aWYgKCFyb3cpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChpc1Rhc2tTdHJpbmcocm93KSkge1xuXHRcdFx0XHRjb25zdCB0YXNrID0gbmV3IFRhc2socm93LCBmaWxlSGFuZGxlLCBpLCBjb2x1bW5UYWdUYWJsZSk7XG5cblx0XHRcdFx0bmV3VGFza0lkcy5hZGQodGFzay5pZCk7XG5cdFx0XHRcdHRhc2tzQnlUYXNrSWQuc2V0KHRhc2suaWQsIHRhc2spO1xuXHRcdFx0XHRtZXRhZGF0YUJ5VGFza0lkLnNldCh0YXNrLmlkLCB7IHJvd0luZGV4OiBpLCBmaWxlSGFuZGxlIH0pO1xuXHRcdFx0XHRwcmV2aW91c1Rhc2tJZHMuZGVsZXRlKHRhc2suaWQpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvciAoY29uc3QgcHJldklkIG9mIHByZXZpb3VzVGFza0lkcykge1xuXHRcdFx0dGFza3NCeVRhc2tJZC5kZWxldGUocHJldklkKTtcblx0XHRcdG1ldGFkYXRhQnlUYXNrSWQuZGVsZXRlKHByZXZJZCk7XG5cdFx0fVxuXG5cdFx0dGFza0lkc0J5RmlsZUhhbmRsZS5zZXQoZmlsZUhhbmRsZSwgbmV3VGFza0lkcyk7XG5cdH0gY2F0Y2gge1xuXHRcdC8vXG5cdH1cbn1cbiIsICJpbXBvcnQgeyBNYXJrZG93blZpZXcsIHR5cGUgVEZpbGUsIHR5cGUgVmF1bHQsIHR5cGUgV29ya3NwYWNlIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi90YXNrXCI7XG5pbXBvcnQgdHlwZSB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vdGFza3NcIjtcbmltcG9ydCB0eXBlIHsgQ29sdW1uVGFnLCBEZWZhdWx0Q29sdW1ucyB9IGZyb20gXCIuLi9jb2x1bW5zL2NvbHVtbnNcIjtcblxuZXhwb3J0IHR5cGUgVGFza0FjdGlvbnMgPSB7XG5cdGNoYW5nZUNvbHVtbjogKFxuXHRcdGlkOiBzdHJpbmcsXG5cdFx0bmV3Q29sdW1uOiBDb2x1bW5UYWcgfCBFeGNsdWRlPERlZmF1bHRDb2x1bW5zLCBcInVuY2F0ZWdvcmlzZWRcIj5cblx0KSA9PiBQcm9taXNlPHZvaWQ+O1xuXHR2aWV3RmlsZTogKGlkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGFza0FjdGlvbnMoe1xuXHR0YXNrc0J5VGFza0lkLFxuXHRtZXRhZGF0YUJ5VGFza0lkLFxuXHR2YXVsdCxcblx0d29ya3NwYWNlLFxufToge1xuXHR0YXNrc0J5VGFza0lkOiBNYXA8c3RyaW5nLCBUYXNrPjtcblx0bWV0YWRhdGFCeVRhc2tJZDogTWFwPHN0cmluZywgTWV0YWRhdGE+O1xuXHR2YXVsdDogVmF1bHQ7XG5cdHdvcmtzcGFjZTogV29ya3NwYWNlO1xufSk6IFRhc2tBY3Rpb25zIHtcblx0YXN5bmMgZnVuY3Rpb24gY2hhbmdlQ29sdW1uKFxuXHRcdGlkOiBzdHJpbmcsXG5cdFx0bmV3Q29sdW1uOiBDb2x1bW5UYWcgfCBFeGNsdWRlPERlZmF1bHRDb2x1bW5zLCBcInVuY2F0ZWdvcmlzZWRcIj5cblx0KSB7XG5cdFx0Y29uc3QgbWV0YWRhdGEgPSBtZXRhZGF0YUJ5VGFza0lkLmdldChpZCk7XG5cdFx0Y29uc3QgdGFzayA9IHRhc2tzQnlUYXNrSWQuZ2V0KGlkKTtcblxuXHRcdGlmICghbWV0YWRhdGEgfHwgIXRhc2spIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBuZXdUYXNrU3RyaW5nID0gdGFzay5zZXJpYWxpc2UoeyBjb2x1bW46IG5ld0NvbHVtbiB9KTtcblx0XHRhd2FpdCB1cGRhdGVSb3coXG5cdFx0XHR2YXVsdCxcblx0XHRcdG1ldGFkYXRhLmZpbGVIYW5kbGUsXG5cdFx0XHRtZXRhZGF0YS5yb3dJbmRleCxcblx0XHRcdG5ld1Rhc2tTdHJpbmdcblx0XHQpO1xuXHR9XG5cblx0YXN5bmMgZnVuY3Rpb24gdmlld0ZpbGUoaWQ6IHN0cmluZykge1xuXHRcdGNvbnN0IG1ldGFkYXRhID0gbWV0YWRhdGFCeVRhc2tJZC5nZXQoaWQpO1xuXG5cdFx0aWYgKCFtZXRhZGF0YSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IHsgZmlsZUhhbmRsZSwgcm93SW5kZXggfSA9IG1ldGFkYXRhO1xuXG5cdFx0Y29uc3QgbGVhZiA9IHdvcmtzcGFjZS5nZXRMZWFmKFwidGFiXCIpO1xuXHRcdGF3YWl0IGxlYWYub3BlbkZpbGUoZmlsZUhhbmRsZSk7XG5cdFx0Y29uc3QgZWRpdG9yVmlldyA9IHdvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG5cdFx0ZWRpdG9yVmlldz8uZWRpdG9yLnNldEN1cnNvcihyb3dJbmRleCk7XG5cdH1cblxuXHRyZXR1cm4geyBjaGFuZ2VDb2x1bW4sIHZpZXdGaWxlIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVJvdyhcblx0dmF1bHQ6IFZhdWx0LFxuXHRmaWxlSGFuZGxlOiBURmlsZSxcblx0cm93OiBudW1iZXIsXG5cdG5ld1RleHQ6IHN0cmluZ1xuKSB7XG5cdGNvbnN0IGZpbGUgPSBhd2FpdCB2YXVsdC5yZWFkKGZpbGVIYW5kbGUpO1xuXHRjb25zdCByb3dzID0gZmlsZS5zcGxpdChcIlxcblwiKTtcblxuXHRpZiAocm93cy5sZW5ndGggPCByb3cpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRyb3dzW3Jvd10gPSBuZXdUZXh0O1xuXHRjb25zdCBuZXdGaWxlID0gcm93cy5qb2luKFwiXFxuXCIpO1xuXHRhd2FpdCB2YXVsdC5tb2RpZnkoZmlsZUhhbmRsZSwgbmV3RmlsZSk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBCcmFuZCB9IGZyb20gXCJzcmMvYnJhbmRcIjtcbmltcG9ydCB7IHdyaXRhYmxlIH0gZnJvbSBcInN2ZWx0ZS9zdG9yZVwiO1xuXG5leHBvcnQgdHlwZSBDb2x1bW5Db25maWcgPSB7XG5cdGNvbHVtbnM6IHN0cmluZ1tdO1xufTtcblxuZXhwb3J0IHR5cGUgRGVmYXVsdENvbHVtbnMgPSBcInVuY2F0ZWdvcmlzZWRcIiB8IFwiZG9uZVwiO1xuZXhwb3J0IHR5cGUgQ29sdW1uVGFnID0gQnJhbmQ8c3RyaW5nLCBcIkNvbHVtblRhZ1wiPjtcblxuZXhwb3J0IHR5cGUgQ29sdW1uVGFnVGFibGUgPSBSZWNvcmQ8Q29sdW1uVGFnLCBzdHJpbmc+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29sdW1uVGFnVGFibGUoe1xuXHRjb2x1bW5zLFxufTogQ29sdW1uQ29uZmlnKTogQ29sdW1uVGFnVGFibGUge1xuXHRjb25zdCBvdXRwdXQ6IENvbHVtblRhZ1RhYmxlID0ge307XG5cblx0Zm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuXHRcdG91dHB1dFtrZWJhYihjb2x1bW4pXSA9IGNvbHVtbjtcblx0fVxuXG5cdHJldHVybiBvdXRwdXQ7XG59XG5cbmZ1bmN0aW9uIGtlYmFiKGlucHV0OiBzdHJpbmcpOiBDb2x1bW5UYWcge1xuXHRyZXR1cm4gaW5wdXRcblx0XHQudG9Mb3dlckNhc2UoKSAvLyBhbGwgYWxwaGFudW1lcmljIGNoYXJzIHRvIGxvd2VyIGNhc2Vcblx0XHQucmVwbGFjZUFsbCgvXFxzL2csIFwiLVwiKSAvLyByZXBsYWNlIGFsbCB3aGl0ZXNwYWNlIHdpdGggXCItXCJcblx0XHQucmVwbGFjZUFsbCgvW15hLXowLTktXS9nLCBcIlwiKSAvLyByZXBsYWNlIGFsbCBvdGhlciBjaGFycyB3aXRoIFwiXCJcblx0XHQucmVwbGFjZUFsbCgvLSsvZywgXCItXCIpIGFzIENvbHVtblRhZzsgLy8gY29sbGFwc2UgYW55IGNvbnNlY3V0aXZlIFwiLVwiIGludG8gYSBzaW5nbGUgXCItXCJcbn1cblxuZXhwb3J0IGNvbnN0IGNvbHVtblRhZ1RhYmxlU3RvcmUgPSB3cml0YWJsZTxDb2x1bW5UYWdUYWJsZT4oe30pO1xuIiwgIjxzY3JpcHQgbGFuZz1cInRzXCI+XG5cdGltcG9ydCB7IE1lbnUsIHNldEljb24gfSBmcm9tIFwib2JzaWRpYW5cIjtcblx0aW1wb3J0IHsgY29sdW1uVGFnVGFibGVTdG9yZSwgdHlwZSBDb2x1bW5UYWcgfSBmcm9tIFwiLi4vY29sdW1ucy9jb2x1bW5zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuLi90YXNrcy90YXNrXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi4vdGFza3MvYWN0aW9uc1wiO1xuXG5cdGV4cG9ydCBsZXQgdGFzazogVGFzaztcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG5cblx0bGV0IGVsZW1lbnQ6IEhUTUxTcGFuRWxlbWVudDtcblx0JDoge1xuXHRcdGlmIChlbGVtZW50KSB7XG5cdFx0XHRzZXRJY29uKGVsZW1lbnQsIFwibHVjaWRlLW1vcmUtdmVydGljYWxcIik7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gc2hvd01lbnUoZTogTW91c2VFdmVudCkge1xuXHRcdGNvbnN0IG1lbnUgPSBuZXcgTWVudSgpO1xuXG5cdFx0bWVudS5hZGRJdGVtKChpKSA9PiB7XG5cdFx0XHRpLnNldFRpdGxlKGBHbyB0byBmaWxlYCkub25DbGljaygoKSA9PlxuXHRcdFx0XHR0YXNrQWN0aW9ucy52aWV3RmlsZSh0YXNrLmlkKSxcblx0XHRcdCk7XG5cdFx0fSk7XG5cblx0XHRtZW51LmFkZFNlcGFyYXRvcigpO1xuXG5cdFx0Zm9yIChjb25zdCBbdGFnLCBsYWJlbF0gb2YgT2JqZWN0LmVudHJpZXMoJGNvbHVtblRhZ1RhYmxlU3RvcmUpKSB7XG5cdFx0XHRtZW51LmFkZEl0ZW0oKGkpID0+IHtcblx0XHRcdFx0aS5zZXRUaXRsZShgTW92ZSB0byAke2xhYmVsfWApLm9uQ2xpY2soKCkgPT5cblx0XHRcdFx0XHR0YXNrQWN0aW9ucy5jaGFuZ2VDb2x1bW4odGFzay5pZCwgdGFnIGFzIENvbHVtblRhZyksXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGlmICh0YXNrLmNvbHVtbiA9PT0gdGFnKSB7XG5cdFx0XHRcdFx0aS5zZXREaXNhYmxlZCh0cnVlKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0bWVudS5hZGRTZXBhcmF0b3IoKTtcblxuXHRcdG1lbnUuYWRkSXRlbSgoaSkgPT4ge1xuXHRcdFx0aS5zZXRUaXRsZShgTW92ZSB0byBkb25lYCkub25DbGljaygoKSA9PlxuXHRcdFx0XHR0YXNrQWN0aW9ucy5jaGFuZ2VDb2x1bW4odGFzay5pZCwgXCJkb25lXCIpLFxuXHRcdFx0KTtcblx0XHRcdGlmICh0YXNrLmNvbHVtbiA9PT0gXCJkb25lXCIpIHtcblx0XHRcdFx0aS5zZXREaXNhYmxlZCh0cnVlKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdG1lbnUuc2hvd0F0TW91c2VFdmVudChlKTtcblx0fVxuPC9zY3JpcHQ+XG5cbjwhLS0gc3ZlbHRlLWlnbm9yZSBhMTF5LWNsaWNrLWV2ZW50cy1oYXZlLWtleS1ldmVudHMgLS0+XG48c3BhblxuXHRiaW5kOnRoaXM9e2VsZW1lbnR9XG5cdHJvbGU9XCJidXR0b25cIlxuXHR0YWJpbmRleD1cIjBcIlxuXHRvbjpjbGljaz17KGUpID0+IHNob3dNZW51KGUpfVxuPjwvc3Bhbj5cblxuPHN0eWxlIGxhbmc9XCJzY3NzXCI+XG5cdHNwYW4ge1xuXHRcdHdpZHRoOiAyNHB4O1xuXHRcdGhlaWdodDogMjRweDtcblx0XHRkaXNwbGF5OiBmbGV4O1xuXHRcdGp1c3RpZnktY29udGVudDogY2VudGVyO1xuXHRcdGFsaWduLWl0ZW1zOiBjZW50ZXI7XG5cdFx0Ym9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLXMpO1xuXHRcdHRyYW5zaXRpb246IGJhY2tncm91bmQgbGluZWFyIDEwMG1zO1xuXHRcdGN1cnNvcjogcG9pbnRlcjtcblxuXHRcdCY6aG92ZXIge1xuXHRcdFx0YmFja2dyb3VuZDogdmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ob3Zlcik7XG5cdFx0fVxuXHR9XG48L3N0eWxlPlxuIiwgIjxzY3JpcHQgbGFuZz1cInRzXCI+XG5cdGltcG9ydCB0eXBlIHsgVGFza0FjdGlvbnMgfSBmcm9tIFwiLi4vdGFza3MvYWN0aW9uc1wiO1xuXHRpbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza3MvdGFza1wiO1xuXHRpbXBvcnQgVGFza01lbnUgZnJvbSBcIi4vdGFza19tZW51LnN2ZWx0ZVwiO1xuXG5cdGV4cG9ydCBsZXQgdGFzazogVGFzaztcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG48L3NjcmlwdD5cblxuPGRpdiBjbGFzcz1cInRhc2tcIj5cblx0PGRpdiBjbGFzcz1cInRhc2stY29udGVudFwiPlxuXHRcdDxwPnt0YXNrLmNvbnRlbnR9PC9wPlxuXHQ8L2Rpdj5cblx0PFRhc2tNZW51IHt0YXNrfSB7dGFza0FjdGlvbnN9IC8+XG48L2Rpdj5cblxuPHN0eWxlIGxhbmc9XCJzY3NzXCI+XG5cdC50YXNrIHtcblx0XHRiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXByaW1hcnktYWx0KTtcblx0XHRib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtbSk7XG5cdFx0Ym9yZGVyOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcblx0XHRwYWRkaW5nOiB2YXIoLS1zaXplLTQtMik7XG5cdFx0ZGlzcGxheTogZ3JpZDtcblx0XHRncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmciBhdXRvO1xuXG5cdFx0cCB7XG5cdFx0XHRtYXJnaW4tdG9wOiAwO1xuXG5cdFx0XHQmOmxhc3QtY2hpbGQge1xuXHRcdFx0XHRtYXJnaW4tYm90dG9tOiAwO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuPC9zdHlsZT5cbiIsICI8c2NyaXB0IGxhbmc9XCJ0c1wiPlxuXHRpbXBvcnQge1xuXHRcdGNvbHVtblRhZ1RhYmxlU3RvcmUsXG5cdFx0dHlwZSBDb2x1bW5UYWcsXG5cdFx0dHlwZSBEZWZhdWx0Q29sdW1ucyxcblx0XHR0eXBlIENvbHVtblRhZ1RhYmxlLFxuXHR9IGZyb20gXCIuLi9jb2x1bW5zL2NvbHVtbnNcIjtcblx0aW1wb3J0IHR5cGUgeyBUYXNrQWN0aW9ucyB9IGZyb20gXCIuLi90YXNrcy9hY3Rpb25zXCI7XG5cdGltcG9ydCB0eXBlIHsgVGFzayB9IGZyb20gXCIuLi90YXNrcy90YXNrXCI7XG5cdGltcG9ydCBUYXNrQ29tcG9uZW50IGZyb20gXCIuL3Rhc2suc3ZlbHRlXCI7XG5cblx0ZXhwb3J0IGxldCBjb2x1bW46IENvbHVtblRhZyB8IERlZmF1bHRDb2x1bW5zO1xuXHRleHBvcnQgbGV0IGhpZGVPbkVtcHR5OiBib29sZWFuID0gZmFsc2U7XG5cdGV4cG9ydCBsZXQgdGFza3M6IFRhc2tbXTtcblx0ZXhwb3J0IGxldCB0YXNrQWN0aW9uczogVGFza0FjdGlvbnM7XG5cblx0ZnVuY3Rpb24gZ2V0Q29sdW1uVGl0bGUoXG5cdFx0Y29sdW1uOiBDb2x1bW5UYWcgfCBEZWZhdWx0Q29sdW1ucyxcblx0XHRjb2x1bW5UYWdUYWJsZTogQ29sdW1uVGFnVGFibGUsXG5cdCkge1xuXHRcdHN3aXRjaCAoY29sdW1uKSB7XG5cdFx0XHRjYXNlIFwiZG9uZVwiOlxuXHRcdFx0XHRyZXR1cm4gXCJEb25lXCI7XG5cdFx0XHRjYXNlIFwidW5jYXRlZ29yaXNlZFwiOlxuXHRcdFx0XHRyZXR1cm4gXCJVbmNhdGVnb3Jpc2VkXCI7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRyZXR1cm4gY29sdW1uVGFnVGFibGVbY29sdW1uXTtcblx0XHR9XG5cdH1cblxuXHQkOiBjb2x1bW5UaXRsZSA9IGdldENvbHVtblRpdGxlKGNvbHVtbiwgJGNvbHVtblRhZ1RhYmxlU3RvcmUpO1xuXG5cdCQ6IHNvcnRlZFRhc2tzID0gdGFza3Muc29ydCgoYSwgYikgPT4ge1xuXHRcdGlmIChhLnBhdGggPT09IGIucGF0aCkge1xuXHRcdFx0cmV0dXJuIGEucm93SW5kZXggLSBiLnJvd0luZGV4O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gYS5wYXRoLmxvY2FsZUNvbXBhcmUoYi5wYXRoKTtcblx0XHR9XG5cdH0pO1xuPC9zY3JpcHQ+XG5cbnsjaWYgIWhpZGVPbkVtcHR5IHx8IHRhc2tzLmxlbmd0aH1cblx0PGRpdiBjbGFzcz1cImNvbHVtblwiPlxuXHRcdDxoMj57Y29sdW1uVGl0bGV9PC9oMj5cblx0XHQ8ZGl2IGNsYXNzPVwiZGl2aWRlXCIgLz5cblx0XHQ8ZGl2IGNsYXNzPVwidGFza3NcIj5cblx0XHRcdHsjZWFjaCBzb3J0ZWRUYXNrcyBhcyB0YXNrfVxuXHRcdFx0XHQ8VGFza0NvbXBvbmVudCB7dGFza30ge3Rhc2tBY3Rpb25zfSAvPlxuXHRcdFx0ey9lYWNofVxuXHRcdDwvZGl2PlxuXHQ8L2Rpdj5cbnsvaWZ9XG5cbjxzdHlsZT5cblx0LmNvbHVtbiB7XG5cdFx0d2lkdGg6IDIyMHB4O1xuXHRcdGZsZXgtc2hyaW5rOiAwO1xuXHRcdHBhZGRpbmc6IHZhcigtLXNpemUtNC0zKTtcblx0XHRib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtbSk7XG5cdFx0Ym9yZGVyOiB2YXIoLS1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWJhY2tncm91bmQtbW9kaWZpZXItYm9yZGVyKTtcblx0XHRiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLXByaW1hcnkpO1xuXHR9XG5cblx0LmNvbHVtbiBoMiB7XG5cdFx0Zm9udC1zaXplOiB2YXIoLS1mb250LXVpLWxhcmdlcik7XG5cdFx0Zm9udC13ZWlnaHQ6IHZhcigtLWZvbnQtYm9sZCk7XG5cdFx0bWFyZ2luOiAwO1xuXHR9XG5cblx0LmNvbHVtbiAuZGl2aWRlIHtcblx0XHR3aWR0aDogY2FsYygxMDAlICsgY2FsYygyICogdmFyKC0tc2l6ZS00LTMpKSk7XG5cdFx0Ym9yZGVyLWJvdHRvbTogdmFyKC0tYm9yZGVyLXdpZHRoKSBzb2xpZFxuXHRcdFx0dmFyKC0tYmFja2dyb3VuZC1tb2RpZmllci1ib3JkZXIpO1xuXHRcdG1hcmdpbjogdmFyKC0tc2l6ZS00LTMpIGNhbGMoLTEgKiB2YXIoLS1zaXplLTQtMykpO1xuXHR9XG5cblx0LmNvbHVtbiAudGFza3Mge1xuXHRcdGRpc3BsYXk6IGZsZXg7XG5cdFx0ZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcblx0XHRnYXA6IHZhcigtLXNpemUtNC0yKTtcblx0fVxuPC9zdHlsZT5cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBLDRDQUFBQSxTQUFBO0FBQUMsS0FBQyxTQUFVLE1BQU0sU0FBUztBQUMxQixVQUFJLE9BQU8sWUFBWSxVQUFVO0FBRWhDLFFBQUFBLFFBQU8sVUFBVSxVQUFVLFFBQVE7QUFBQSxNQUNwQyxXQUNTLE9BQU8sV0FBVyxjQUFjLE9BQU8sS0FBSztBQUVwRCxlQUFPLENBQUMsR0FBRyxPQUFPO0FBQUEsTUFDbkIsT0FDSztBQUVKLGFBQUssV0FBVyxRQUFRO0FBQUEsTUFDekI7QUFBQSxJQUNELEdBQUUsU0FBTSxXQUFZO0FBT25CLFVBQUksV0FBVyxZQUFhLFNBQVVDLE9BQU1DLFlBQVc7QUFFbkQsWUFBSTtBQUdKLFlBQUksT0FBTyxXQUFXLGVBQWUsT0FBTyxRQUFRO0FBQ2hELG1CQUFTLE9BQU87QUFBQSxRQUNwQjtBQUdBLFlBQUksT0FBTyxTQUFTLGVBQWUsS0FBSyxRQUFRO0FBQzVDLG1CQUFTLEtBQUs7QUFBQSxRQUNsQjtBQUdBLFlBQUksT0FBTyxlQUFlLGVBQWUsV0FBVyxRQUFRO0FBQ3hELG1CQUFTLFdBQVc7QUFBQSxR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UjtBQUFBLEVBRUEsTUFBTSxTQUFTO0FBQ2QsU0FBSyxZQUFZLElBQUksYUFBSztBQUFBLE1BQ3pCLFFBQVEsS0FBSztBQUFBLE1BQ2IsT0FBTztBQUFBLFFBQ04sV0FBVyxLQUFLLElBQUk7QUFBQSxRQUNwQixPQUFPLEtBQUssSUFBSTtBQUFBLFFBQ2hCLGVBQWUsS0FBSyxjQUFjLEtBQUssSUFBSTtBQUFBLE1BQzVDO0FBQUEsSUFDRCxDQUFDO0FBQUEsRUFDRjtBQUFBLEVBRUEsTUFBTSxVQUFVO0FBOUJqQjtBQStCRSxlQUFLLGNBQUwsbUJBQWdCO0FBQUEsRUFDakI7QUFDRDs7O0FEOUJBLElBQXFCLE9BQXJCLGNBQWtDLHdCQUFPO0FBQUEsRUFDeEMsTUFBTSxTQUFTO0FBQ2QsU0FBSyxhQUFhLGVBQWUsQ0FBQyxTQUFTLElBQUksUUFBUSxJQUFJLENBQUM7QUFDNUQsU0FBSztBQUFBLE1BQWM7QUFBQSxNQUFpQjtBQUFBLE1BQWUsTUFDbEQsS0FBSyxhQUFhO0FBQUEsSUFDbkI7QUFBQSxFQUNEO0FBQUEsRUFFQSxXQUFXO0FBQUEsRUFBQztBQUFBLEVBRVosTUFBTSxlQUFlO0FBQ3BCLFVBQU0sRUFBRSxVQUFVLElBQUksS0FBSztBQUUzQixRQUFJO0FBQ0osVUFBTSxTQUFTLFVBQVUsZ0JBQWdCLGFBQWE7QUFFdEQsUUFBSSxPQUFPLFNBQVMsR0FBRztBQUV0QixhQUFPLE9BQU8sQ0FBQztBQUFBLElBQ2hCLE9BQU87QUFHTixhQUFPLFVBQVUsUUFBUSxLQUFLO0FBQzlCLFlBQU0sS0FBSyxhQUFhLEVBQUUsTUFBTSxlQUFlLFFBQVEsS0FBSyxDQUFDO0FBQUEsSUFDOUQ7QUFHQSxZQUFRLFVBQVUsV0FBVyxJQUFJO0FBQUEsRUFDbEM7QUFDRDsiLAogICJuYW1lcyI6IFsibW9kdWxlIiwgIk1hdGgiLCAidW5kZWZpbmVkIiwgIkJhc2UiLCAiaW5zdGFuY2UiLCAibW9kdWxlIiwgIk1hdGgiLCAibiIsICJIIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiZWxlbWVudCIsICJfYSIsICJlbGVtZW50IiwgInRleHQiLCAiZWxlbWVudCIsICJkZXRhY2giLCAiaW5zdGFuY2UiLCAiY3JlYXRlX2ZyYWdtZW50IiwgImFwcGVuZF9zdHlsZXMiLCAiYXR0ciIsICJpbXBvcnRfb2JzaWRpYW4iLCAic2hhMjU2IiwgInVwZGF0ZSIsICJzdWJzY3JpYmUiLCAicnVuIiwgImNvbHVtblRhZ1RhYmxlU3RvcmUiLCAiY29sdW1uVGFnVGFibGVTdG9yZSIsICJlbGVtZW50IiwgImN0eCIsICJjdHgiLCAiX2EiLCAiY3R4Il0KfQo= diff --git a/versions.json b/versions.json index 26382a157..fcd4ae5a8 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ { - "1.0.0": "0.15.0" + "1.0.0": "1.5.3" } From 3940e811e99f30c06dd0c3c0ec5a6d85141b7be2 Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Thu, 22 Feb 2024 06:44:40 +1000 Subject: [PATCH 004/195] tightened up styles and column logic --- src/ui/components/column.svelte | 2 +- src/ui/components/task.svelte | 2 +- src/ui/components/task_menu.svelte | 4 +- src/ui/main.svelte | 40 +++++---- src/ui/tasks/actions.ts | 34 +++++--- src/ui/tasks/task.ts | 128 ++++++++++++++--------------- 6 files changed, 109 insertions(+), 101 deletions(-) diff --git a/src/ui/components/column.svelte b/src/ui/components/column.svelte index 1a1c5c46a..bcbd17962 100644 --- a/src/ui/components/column.svelte +++ b/src/ui/components/column.svelte @@ -58,7 +58,7 @@ padding: var(--size-4-3); border-radius: var(--radius-m); border: var(--border-width) solid var(--background-modifier-border); - background-color: var(--background-primary); + background-color: var(--background-secondary); } .column h2 { diff --git a/src/ui/components/task.svelte b/src/ui/components/task.svelte index 025c968be..43c5ce966 100644 --- a/src/ui/components/task.svelte +++ b/src/ui/components/task.svelte @@ -16,7 +16,7 @@ diff --git a/src/ui/components/icon_button.svelte b/src/ui/components/icon_button.svelte new file mode 100644 index 000000000..57547f9ff --- /dev/null +++ b/src/ui/components/icon_button.svelte @@ -0,0 +1,32 @@ + + + + + + diff --git a/src/ui/components/task.svelte b/src/ui/components/task.svelte index 43c5ce966..845a3bb3f 100644 --- a/src/ui/components/task.svelte +++ b/src/ui/components/task.svelte @@ -1,17 +1,69 @@ -
-
-

{task.content}

+
+
+
+

+ {task.content} +

+
+ +
+ -
+ diff --git a/src/ui/dnd/store.ts b/src/ui/dnd/store.ts new file mode 100644 index 000000000..ee3536bb5 --- /dev/null +++ b/src/ui/dnd/store.ts @@ -0,0 +1,3 @@ +import { writable } from "svelte/store"; + +export const isDraggingStore = writable(false); diff --git a/src/ui/tasks/actions.ts b/src/ui/tasks/actions.ts index 489231684..949d0cbeb 100644 --- a/src/ui/tasks/actions.ts +++ b/src/ui/tasks/actions.ts @@ -4,9 +4,11 @@ import type { Metadata } from "./tasks"; import type { ColumnTag } from "../columns/columns"; export type TaskActions = { - changeColumn: (id: string, newColumn: ColumnTag) => Promise; + changeColumn: (id: string, column: ColumnTag) => Promise; markDone: (id: string) => Promise; + updateContent: (id: string, content: string) => Promise; viewFile: (id: string) => Promise; + archiveTasks: (ids: string[]) => Promise; }; export function createTaskActions({ @@ -20,7 +22,10 @@ export function createTaskActions({ vault: Vault; workspace: Workspace; }): TaskActions { - async function changeColumn(id: string, newColumn: ColumnTag) { + async function updateRowWithTask( + id: string, + updater: (task: Task) => void + ) { const metadata = metadataByTaskId.get(id); const task = tasksByTaskId.get(id); @@ -28,7 +33,9 @@ export function createTaskActions({ return; } - const newTaskString = task.serialisedWithColumn(newColumn); + updater(task); + + const newTaskString = task.serialise(); await updateRow( vault, metadata.fileHandle, @@ -37,39 +44,40 @@ export function createTaskActions({ ); } - async function markDone(id: string) { - const metadata = metadataByTaskId.get(id); - const task = tasksByTaskId.get(id); + return { + async changeColumn(id: string, column: ColumnTag) { + await updateRowWithTask(id, (task) => (task.column = column)); + }, - if (!metadata || !task) { - return; - } + async markDone(id: string) { + await updateRowWithTask(id, (task) => (task.done = true)); + }, - const newTaskString = task.serialisedAsDone(true); - await updateRow( - vault, - metadata.fileHandle, - metadata.rowIndex, - newTaskString - ); - } + async updateContent(id: string, content: string) { + await updateRowWithTask(id, (task) => (task.content = content)); + }, - async function viewFile(id: string) { - const metadata = metadataByTaskId.get(id); + async archiveTasks(ids: string[]) { + for (const id of ids) { + await updateRowWithTask(id, (task) => task.archive()); + } + }, - if (!metadata) { - return; - } + async viewFile(id: string) { + const metadata = metadataByTaskId.get(id); - const { fileHandle, rowIndex } = metadata; + if (!metadata) { + return; + } - const leaf = workspace.getLeaf("tab"); - await leaf.openFile(fileHandle); - const editorView = workspace.getActiveViewOfType(MarkdownView); - editorView?.editor.setCursor(rowIndex); - } + const { fileHandle, rowIndex } = metadata; - return { changeColumn, markDone, viewFile }; + const leaf = workspace.getLeaf("tab"); + await leaf.openFile(fileHandle); + const editorView = workspace.getActiveViewOfType(MarkdownView); + editorView?.editor.setCursor(rowIndex); + }, + }; } async function updateRow( diff --git a/src/ui/tasks/store.ts b/src/ui/tasks/store.ts index f1cf5fd00..311db7eeb 100644 --- a/src/ui/tasks/store.ts +++ b/src/ui/tasks/store.ts @@ -24,24 +24,39 @@ export function createTasksStore( if (!timer) { timer = window.setTimeout(() => { timer = undefined; - tasksStore.set([...tasksByTaskId.values()]); + tasksStore.set( + [...tasksByTaskId.values()].sort((a, b) => { + if (a.path !== b.path) { + return a.path.localeCompare(b.path); + } + return a.rowIndex - b.rowIndex; + }) + ); }, 50); } } - for (const fileHandle of fileHandles) { - updateMapsFromFile({ - fileHandle, - tasksByTaskId, - metadataByTaskId, - taskIdsByFileHandle, - vault, - columnTagTableStore, - }).then(() => { - debounceSetTasks(); - }); + function initialise() { + tasksByTaskId.clear(); + metadataByTaskId.clear(); + taskIdsByFileHandle.clear(); + + for (const fileHandle of fileHandles) { + updateMapsFromFile({ + fileHandle, + tasksByTaskId, + metadataByTaskId, + taskIdsByFileHandle, + vault, + columnTagTableStore, + }).then(() => { + debounceSetTasks(); + }); + } } + initialise(); + registerEvent( vault.on("modify", (fileHandle) => { if (fileHandle instanceof TFile) { @@ -79,7 +94,14 @@ export function createTasksStore( registerEvent( vault.on("delete", (fileHandle) => { if (fileHandle instanceof TFile) { - // TODO implement + const tasksToDelete = taskIdsByFileHandle.get(fileHandle); + if (!tasksToDelete) return; + + for (const taskId of tasksToDelete) { + tasksByTaskId.delete(taskId); + metadataByTaskId.delete(taskId); + } + taskIdsByFileHandle.delete(fileHandle); } }) ); @@ -87,7 +109,7 @@ export function createTasksStore( registerEvent( vault.on("rename", (fileHandle) => { if (fileHandle instanceof TFile) { - // TODO implement + initialise(); } }) ); diff --git a/src/ui/tasks/task.ts b/src/ui/tasks/task.ts index 3dfd2ef30..cba299016 100644 --- a/src/ui/tasks/task.ts +++ b/src/ui/tasks/task.ts @@ -6,7 +6,7 @@ export class Task { constructor( rawContent: TaskString, fileHandle: { path: string }, - rowIndex: number, + readonly rowIndex: number, columnTagTable: ColumnTagTable ) { const [, remainder = ""] = rawContent.split("- ["); @@ -15,7 +15,7 @@ export class Task { this._tags = getTags(content); this._id = sha256(content + fileHandle.path + rowIndex).toString(); - this._content = content; + this.content = content; this._done = status === "x"; this._path = fileHandle.path; @@ -27,7 +27,7 @@ export class Task { this._tags.delete(tag); } - this._content = this._content.replaceAll(`#${tag}`, "").trim(); + this.content = this.content.replaceAll(`#${tag}`, "").trim(); } if (this._done) { this._column = undefined; @@ -38,13 +38,10 @@ export class Task { get id() { return this._id; } - private _content: string; - get content() { - return this._content; - } + content: string; private _done: boolean; - get done() { + get done(): boolean { return this._done; } @@ -53,26 +50,24 @@ export class Task { return this._path; } - private _column: ColumnTag | undefined; - get column() { + private _column: ColumnTag | "archived" | undefined; + get column(): ColumnTag | "archived" | undefined { return this._column; } private readonly _tags: Set; - serialisedAsDone(done: boolean): string { + set done(done: true) { this._done = done; this._column = undefined; - return this.serialise(); } - serialisedWithColumn(column: ColumnTag) { + set column(column: ColumnTag) { this._column = column; this._done = false; - return this.serialise(); } - private serialise(): string { + serialise(): string { return [ `- [${this.done ? "x" : " "}] `, this.content.trim(), @@ -80,11 +75,19 @@ export class Task { [...this._tags].map((tag) => ` #${tag}`).join(""), ].join(""); } + + archive() { + this._done = true; + this._column = "archived"; + } } type TaskString = Brand; export function isTaskString(input: string): input is TaskString { + if (input.includes("#archived")) { + return false; + } return taskStringRegex.test(input); } From ff63bc25c6d638f7e29652a0b73d61ca9518f6de Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Thu, 22 Feb 2024 09:51:44 +1000 Subject: [PATCH 006/195] drag and drop bugs --- src/ui/components/column.svelte | 13 ++++++++-- src/ui/components/task.svelte | 42 +++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/ui/components/column.svelte b/src/ui/components/column.svelte index dfc14b01b..a901befe0 100644 --- a/src/ui/components/column.svelte +++ b/src/ui/components/column.svelte @@ -71,8 +71,17 @@ e.preventDefault(); // Get the id of the target and add the moved element to the target's DOM const droppedId = e.dataTransfer?.getData("text/plain"); - if (droppedId && column !== "done" && column !== "uncategorised") { - taskActions.changeColumn(droppedId, column); + if (droppedId) { + switch (column) { + case "uncategorised": + break; + case "done": + taskActions.markDone(droppedId); + break; + default: + taskActions.changeColumn(droppedId, column); + break; + } } } diff --git a/src/ui/components/task.svelte b/src/ui/components/task.svelte index 845a3bb3f..5eff08597 100644 --- a/src/ui/components/task.svelte +++ b/src/ui/components/task.svelte @@ -7,9 +7,11 @@ export let task: Task; export let taskActions: TaskActions; - function handleSaveContent( + function handleContentBlur( e: FocusEvent & { currentTarget: HTMLParagraphElement }, ) { + isEditing = false; + const content = e.currentTarget.textContent; if (!content) return; @@ -25,8 +27,10 @@ } let isDragging = false; + let isEditing = false; function handleDragStart(e: DragEvent) { + isEditing = false; isDragging = true; isDraggingStore.set(true); if (e.dataTransfer) { @@ -39,6 +43,27 @@ isDragging = false; isDraggingStore.set(false); } + + function handleDblClick(e: MouseEvent) { + const target = e.target as HTMLParagraphElement | null; + if (!target) { + return; + } + + isEditing = true; + target.focus(); + + function onClickOutside(clickEvent: MouseEvent) { + if (!target.contains(clickEvent.targetNode)) { + isEditing = false; + window.removeEventListener("click", onClickOutside); + } + } + + window.addEventListener("click", onClickOutside); + } + + $: editableContentProps = isEditing ? { contenteditable: true } : {};
+

{task.content} @@ -83,12 +111,12 @@ grid-template-columns: 1fr auto; p { - cursor: text; word-break: break-word; - margin-top: 0; + margin: 0; - &:last-child { - margin-bottom: 0; + &.editing { + cursor: text; + background-color: var(--color-base-25); } } } From 43bb9a221f2767974ae3feffcaddf65a619d859e Mon Sep 17 00:00:00 2001 From: Chris Kerr Date: Thu, 22 Feb 2024 17:43:07 +1000 Subject: [PATCH 007/195] added markdown support, made the editor much cleaner, and tidied styles --- package-lock.json | 33 +++++++++++++- package.json | 4 +- src/ui/components/column.svelte | 5 ++ src/ui/components/task.svelte | 81 ++++++++++++++++++++------------- 4 files changed, 89 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 158344eff..583c16b0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,14 @@ "dependencies": { "@floating-ui/dom": "^1.6.3", "crypto-js": "^4.2.0", - "sass": "^1.71.1" + "sass": "^1.71.1", + "showdown": "^2.1.0" }, "devDependencies": { "@tsconfig/svelte": "^5.0.2", "@types/crypto-js": "^4.2.2", "@types/node": "^20.11.19", + "@types/showdown": "^2.0.6", "@typescript-eslint/eslint-plugin": "7.0.1", "@typescript-eslint/parser": "7.0.1", "builtin-modules": "3.3.0", @@ -740,6 +742,12 @@ "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", "dev": true }, + "node_modules/@types/showdown": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.6.tgz", + "integrity": "sha512-pTvD/0CIeqe4x23+YJWlX2gArHa8G0J0Oh6GKaVXV7TAeickpkkZiNOgFcFcmLQ5lB/K0qBJL1FtRYltBfbGCQ==", + "dev": true + }, "node_modules/@types/tern": { "version": "0.23.9", "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", @@ -1206,6 +1214,14 @@ "dev": true, "peer": true }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2488,6 +2504,21 @@ "node": ">=8" } }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index 0f997a025..2f99ed2ed 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@tsconfig/svelte": "^5.0.2", "@types/crypto-js": "^4.2.2", "@types/node": "^20.11.19", + "@types/showdown": "^2.0.6", "@typescript-eslint/eslint-plugin": "7.0.1", "@typescript-eslint/parser": "7.0.1", "builtin-modules": "3.3.0", @@ -29,6 +30,7 @@ "dependencies": { "@floating-ui/dom": "^1.6.3", "crypto-js": "^4.2.0", - "sass": "^1.71.1" + "sass": "^1.71.1", + "showdown": "^2.1.0" } } diff --git a/src/ui/components/column.svelte b/src/ui/components/column.svelte index a901befe0..0e8455dca 100644 --- a/src/ui/components/column.svelte +++ b/src/ui/components/column.svelte @@ -117,6 +117,7 @@ .column { display: flex; flex-direction: column; + align-self: flex-start; width: 300px; flex-shrink: 0; padding: var(--size-4-3); @@ -141,6 +142,9 @@ .header { display: flex; justify-content: space-between; + align-items: center; + height: 24px; + flex-shrink: 0; h2 { font-size: var(--font-ui-larger); @@ -158,6 +162,7 @@ .tasks-wrapper { height: 100%; + min-height: 50px; border: var(--border-width) dashed transparent; border-radius: var(--radius-m); diff --git a/src/ui/components/task.svelte b/src/ui/components/task.svelte index 5eff08597..e322a8f0d 100644 --- a/src/ui/components/task.svelte +++ b/src/ui/components/task.svelte @@ -3,23 +3,30 @@ import type { TaskActions } from "../tasks/actions"; import type { Task } from "../tasks/task"; import TaskMenu from "./task_menu.svelte"; + import { Converter } from "showdown"; export let task: Task; export let taskActions: TaskActions; + const mdConverted = new Converter({ + simplifiedAutoLink: true, + openLinksInNewWindow: true, + emoji: true, + }); + function handleContentBlur( - e: FocusEvent & { currentTarget: HTMLParagraphElement }, + e: FocusEvent & { currentTarget: HTMLTextAreaElement }, ) { isEditing = false; - const content = e.currentTarget.textContent; + const content = e.currentTarget.value; if (!content) return; taskActions.updateContent(task.id, content); } function handleKeypress( - e: KeyboardEvent & { currentTarget: HTMLParagraphElement }, + e: KeyboardEvent & { currentTarget: HTMLTextAreaElement }, ) { if (e.key === "Enter") { e.currentTarget.blur(); @@ -44,26 +51,29 @@ isDraggingStore.set(false); } - function handleDblClick(e: MouseEvent) { - const target = e.target as HTMLParagraphElement | null; - if (!target) { - return; - } + let textAreaEl: HTMLTextAreaElement | undefined; + function handleDblClick(e: MouseEvent) { isEditing = true; - target.focus(); - function onClickOutside(clickEvent: MouseEvent) { - if (!target.contains(clickEvent.targetNode)) { - isEditing = false; - window.removeEventListener("click", onClickOutside); - } - } + setTimeout(() => { + textAreaEl?.focus(); + }, 100); + } - window.addEventListener("click", onClickOutside); + $: mdContent = mdConverted.makeHtml(task.content); + + $: { + if (textAreaEl) { + textAreaEl.style.height = `0px`; + textAreaEl.style.height = `${textAreaEl.scrollHeight}px`; + } } - $: editableContentProps = isEditing ? { contenteditable: true } : {}; + function onInput(e: Event & { currentTarget: HTMLTextAreaElement }) { + e.currentTarget.style.height = `0px`; + e.currentTarget.style.height = `${e.currentTarget.scrollHeight}px`; + }

-
- -

- {task.content} -

+ +
+ {#if isEditing} +