@nlabs/lex 1.49.4 → 1.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.swcrc +35 -0
- package/README.md +43 -59
- package/__mocks__/chalk.js +19 -17
- package/config.json +32 -8
- package/examples/lex.config.js +110 -10
- package/index.cjs +1 -5
- package/lex.config.js +34 -7
- package/lib/Button.stories.js +99 -0
- package/lib/LexConfig.d.ts +60 -22
- package/lib/LexConfig.js +285 -244
- package/lib/commands/ai/ai.js +287 -288
- package/lib/commands/ai/index.js +8 -7
- package/lib/commands/build/build.d.ts +2 -2
- package/lib/commands/build/build.js +349 -458
- package/lib/commands/clean/clean.js +45 -33
- package/lib/commands/compile/compile.js +214 -227
- package/lib/commands/config/config.js +46 -42
- package/lib/commands/copy/copy.js +36 -35
- package/lib/commands/create/create.js +200 -121
- package/lib/commands/dev/dev.d.ts +2 -0
- package/lib/commands/dev/dev.js +259 -263
- package/lib/commands/init/init.js +108 -88
- package/lib/commands/link/link.js +18 -14
- package/lib/commands/lint/lint.js +735 -742
- package/lib/commands/migrate/migrate.js +49 -36
- package/lib/commands/publish/publish.js +116 -96
- package/lib/commands/serverless/serverless.js +611 -585
- package/lib/commands/storybook/storybook.js +242 -238
- package/lib/commands/test/test.d.ts +1 -1
- package/lib/commands/test/test.js +382 -394
- package/lib/commands/update/update.js +141 -120
- package/lib/commands/upgrade/upgrade.js +51 -44
- package/lib/commands/versions/versions.d.ts +1 -1
- package/lib/commands/versions/versions.js +36 -38
- package/lib/create/changelog.js +136 -125
- package/lib/index.js +40 -38
- package/lib/lex.js +95 -68
- package/lib/storybook/index.js +6 -1
- package/lib/test-react/index.js +7 -84
- package/lib/types.d.ts +1 -1
- package/lib/types.js +7 -1
- package/lib/utils/aiService.js +240 -227
- package/lib/utils/app.js +274 -273
- package/lib/utils/deepMerge.js +37 -23
- package/lib/utils/file.js +218 -215
- package/lib/utils/log.js +29 -27
- package/lib/utils/reactShim.js +7 -85
- package/lib/utils/translations.js +91 -65
- package/package.json +63 -64
- package/templates/typescript/DataLayer.js.txt +218 -0
- package/templates/typescript/DataLayer.test.js.txt +268 -0
- package/templates/typescript/DataLayer.test.ts.txt +269 -0
- package/templates/typescript/DataLayer.ts.txt +227 -0
- package/webpack.config.js +53 -26
- package/lib/commands/lint/autofix.d.ts +0 -2
|
@@ -1,83 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-Present, Nitrogen Labs, Inc.
|
|
3
|
+
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
+
*/ import { execa } from 'execa';
|
|
5
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
|
|
6
|
+
import { dirname, resolve as pathResolve, extname } from 'path';
|
|
7
|
+
import { LexConfig } from '../../LexConfig.js';
|
|
8
|
+
import { createSpinner } from '../../utils/app.js';
|
|
9
|
+
import { resolveBinaryPath } from '../../utils/file.js';
|
|
10
|
+
import { log } from '../../utils/log.js';
|
|
8
11
|
let currentFilename;
|
|
9
12
|
let currentDirname;
|
|
10
13
|
try {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} catch
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
currentFilename = eval('require("url").fileURLToPath(import.meta.url)');
|
|
15
|
+
currentDirname = dirname(currentFilename);
|
|
16
|
+
} catch {
|
|
17
|
+
currentFilename = process.cwd();
|
|
18
|
+
currentDirname = process.cwd();
|
|
16
19
|
}
|
|
17
|
-
const createDefaultESLintConfig = (useTypescript, cwd)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const createDefaultESLintConfig = (useTypescript, cwd)=>{
|
|
21
|
+
// Use a temporary file path instead of creating in the project directory
|
|
22
|
+
const configPath = pathResolve(cwd, '.lex-temp-default-eslint.cjs');
|
|
23
|
+
const originalConfig = null;
|
|
24
|
+
// Create a temporary CommonJS module that requires Lex's ESLint config
|
|
25
|
+
const configContent = `// Temporary ESLint config generated by Lex
|
|
21
26
|
const lexConfig = require('@nlabs/lex/eslint.config.mjs');
|
|
22
27
|
|
|
23
28
|
module.exports = lexConfig;`;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
writeFileSync(configPath, configContent, 'utf8');
|
|
30
|
+
return {
|
|
31
|
+
configPath,
|
|
32
|
+
originalConfig
|
|
33
|
+
};
|
|
29
34
|
};
|
|
30
|
-
const detectTypeScript = (cwd)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const detectTypeScript = (cwd)=>existsSync(pathResolve(cwd, 'tsconfig.json'));
|
|
36
|
+
/**
|
|
37
|
+
* Ensure package.json has type: module for ESM support
|
|
38
|
+
*/ const ensureModuleType = (cwd)=>{
|
|
39
|
+
const packageJsonPath = pathResolve(cwd, 'package.json');
|
|
40
|
+
if (existsSync(packageJsonPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const packageJsonContent = readFileSync(packageJsonPath, 'utf8');
|
|
43
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
44
|
+
// If type is not set to module, warn instead of auto-modifying
|
|
45
|
+
if (packageJson.type !== 'module') {
|
|
46
|
+
log('Warning: package.json should have "type": "module" for ESM support. Please add this manually.', 'warn', false);
|
|
47
|
+
}
|
|
48
|
+
} catch (_error) {
|
|
49
|
+
// Ignore errors
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const installDependencies = async (cwd, useTypescript, quiet) => {
|
|
45
|
-
if (useTypescript) {
|
|
46
|
-
log("Using TypeScript ESLint from Lex...", "info", quiet);
|
|
47
|
-
} else {
|
|
48
|
-
log("Using ESLint from Lex...", "info", quiet);
|
|
49
|
-
}
|
|
50
52
|
};
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const hasProjectConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs);
|
|
57
|
-
const hasLexConfigEslint = LexConfig.config.eslint && Object.keys(LexConfig.config.eslint).length > 0;
|
|
58
|
-
const possiblePaths = [
|
|
59
|
-
pathResolve(currentDirname, "../../../../eslint.config.mjs"),
|
|
60
|
-
pathResolve(currentDirname, "../../../../eslint.config.ts"),
|
|
61
|
-
pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.mjs"),
|
|
62
|
-
pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.ts")
|
|
63
|
-
];
|
|
64
|
-
let lexConfigPath = "";
|
|
65
|
-
for (const path of possiblePaths) {
|
|
66
|
-
if (existsSync(path)) {
|
|
67
|
-
lexConfigPath = path;
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
53
|
+
const installDependencies = async (cwd, useTypescript, quiet)=>{
|
|
54
|
+
if (useTypescript) {
|
|
55
|
+
log('Using TypeScript ESLint from Lex...', 'info', quiet);
|
|
56
|
+
} else {
|
|
57
|
+
log('Using ESLint from Lex...', 'info', quiet);
|
|
70
58
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
59
|
+
};
|
|
60
|
+
const runEslintWithLex = async (cwd, quiet, cliName, fix, debug, useTypescript, captureOutput)=>{
|
|
61
|
+
const spinner = createSpinner(quiet);
|
|
62
|
+
try {
|
|
63
|
+
const projectConfigPath = pathResolve(cwd, 'eslint.config.mjs');
|
|
64
|
+
const projectConfigPathTs = pathResolve(cwd, 'eslint.config.ts');
|
|
65
|
+
const hasProjectConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs);
|
|
66
|
+
const hasLexConfigEslint = LexConfig.config.eslint && Object.keys(LexConfig.config.eslint).length > 0;
|
|
67
|
+
const possiblePaths = [
|
|
68
|
+
pathResolve(currentDirname, '../../../../eslint.config.mjs'),
|
|
69
|
+
pathResolve(currentDirname, '../../../../eslint.config.ts'),
|
|
70
|
+
pathResolve(process.env.LEX_HOME || '/usr/local/lib/node_modules/@nlabs/lex', 'eslint.config.mjs'),
|
|
71
|
+
pathResolve(process.env.LEX_HOME || '/usr/local/lib/node_modules/@nlabs/lex', 'eslint.config.ts')
|
|
72
|
+
];
|
|
73
|
+
let lexConfigPath = '';
|
|
74
|
+
for (const path of possiblePaths){
|
|
75
|
+
if (existsSync(path)) {
|
|
76
|
+
lexConfigPath = path;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
let configPath = '';
|
|
81
|
+
let tempConfigPath = '';
|
|
82
|
+
// Priority:
|
|
83
|
+
// 1. Project eslint.config files
|
|
84
|
+
// 2. ESLint config in lex.config.* file
|
|
85
|
+
// 3. Lex's default eslint.config.mjs
|
|
86
|
+
// 4. Create a temporary config file
|
|
87
|
+
if (hasProjectConfig) {
|
|
88
|
+
configPath = existsSync(projectConfigPathTs) ? projectConfigPathTs : projectConfigPath;
|
|
89
|
+
if (debug) {
|
|
90
|
+
log(`Using project ESLint config file: ${configPath}`, 'info', quiet);
|
|
91
|
+
}
|
|
92
|
+
} else if (hasLexConfigEslint) {
|
|
93
|
+
// When using lex.config.eslint, create a temporary JS config file (not JSON)
|
|
94
|
+
// to avoid ESM JSON import issues
|
|
95
|
+
tempConfigPath = pathResolve(cwd, '.lex-temp-eslint.cjs');
|
|
96
|
+
// Create a CommonJS module that extends Lex's eslint config
|
|
97
|
+
const configContent = `// Temporary ESLint config generated by Lex
|
|
81
98
|
const lexConfig = require('@nlabs/lex/eslint.config.mjs');
|
|
82
99
|
const userConfig = ${JSON.stringify(LexConfig.config.eslint, null, 2)};
|
|
83
100
|
|
|
@@ -85,195 +102,212 @@ const userConfig = ${JSON.stringify(LexConfig.config.eslint, null, 2)};
|
|
|
85
102
|
module.exports = {
|
|
86
103
|
...lexConfig
|
|
87
104
|
};`;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
writeFileSync(tempConfigPath, configContent, 'utf8');
|
|
106
|
+
configPath = tempConfigPath;
|
|
107
|
+
if (debug) {
|
|
108
|
+
log(`Using ESLint config from lex.config.* file via temp file: ${tempConfigPath}`, 'info', quiet);
|
|
109
|
+
}
|
|
110
|
+
} else if (lexConfigPath && existsSync(lexConfigPath)) {
|
|
111
|
+
configPath = lexConfigPath;
|
|
112
|
+
if (debug) {
|
|
113
|
+
log(`Using Lex ESLint config file: ${configPath}`, 'info', quiet);
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
// Create a temporary default config file if no other config is found
|
|
117
|
+
tempConfigPath = pathResolve(cwd, '.lex-temp-default-eslint.cjs');
|
|
118
|
+
// Create a basic ESLint config
|
|
119
|
+
const configContent = `// Temporary default ESLint config generated by Lex
|
|
101
120
|
const lexConfig = require('@nlabs/lex/eslint.config.mjs');
|
|
102
121
|
|
|
103
122
|
module.exports = lexConfig;`;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
const eslintBinary = resolveBinaryPath("eslint", "eslint");
|
|
113
|
-
if (!eslintBinary) {
|
|
114
|
-
log(`
|
|
115
|
-
${cliName} Error: ESLint binary not found in Lex's node_modules`, "error", quiet);
|
|
116
|
-
log("Please reinstall Lex or check your installation.", "info", quiet);
|
|
117
|
-
return 1;
|
|
118
|
-
}
|
|
119
|
-
const baseEslintArgs = [
|
|
120
|
-
...fix ? ["--fix"] : [],
|
|
121
|
-
...debug ? ["--debug"] : [],
|
|
122
|
-
"--no-error-on-unmatched-pattern",
|
|
123
|
-
"--no-warn-ignored"
|
|
124
|
-
];
|
|
125
|
-
const configArgs = configPath ? ["--config", configPath] : [];
|
|
126
|
-
const jsResult = await execa(eslintBinary, [
|
|
127
|
-
"src/**/*.{js,jsx}",
|
|
128
|
-
...configArgs,
|
|
129
|
-
...baseEslintArgs
|
|
130
|
-
], {
|
|
131
|
-
cwd,
|
|
132
|
-
reject: false,
|
|
133
|
-
shell: true,
|
|
134
|
-
stdio: "pipe"
|
|
135
|
-
});
|
|
136
|
-
if (jsResult.stdout) {
|
|
137
|
-
console.log(jsResult.stdout);
|
|
138
|
-
if (captureOutput) {
|
|
139
|
-
captureOutput(jsResult.stdout);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (jsResult.stderr) {
|
|
143
|
-
console.error(jsResult.stderr);
|
|
144
|
-
if (captureOutput) {
|
|
145
|
-
captureOutput(jsResult.stderr);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
let tsResult = { exitCode: 0, stderr: "", stdout: "" };
|
|
149
|
-
if (useTypescript) {
|
|
150
|
-
tsResult = await execa(eslintBinary, [
|
|
151
|
-
"src/**/*.{ts,tsx}",
|
|
152
|
-
...configArgs,
|
|
153
|
-
...baseEslintArgs
|
|
154
|
-
], {
|
|
155
|
-
cwd,
|
|
156
|
-
reject: false,
|
|
157
|
-
shell: true,
|
|
158
|
-
stdio: "pipe"
|
|
159
|
-
});
|
|
160
|
-
if (tsResult.stdout) {
|
|
161
|
-
console.log(tsResult.stdout);
|
|
162
|
-
}
|
|
163
|
-
if (tsResult.stderr) {
|
|
164
|
-
console.error(tsResult.stderr);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (tempConfigPath && existsSync(tempConfigPath)) {
|
|
168
|
-
try {
|
|
169
|
-
unlinkSync(tempConfigPath);
|
|
170
|
-
if (debug) {
|
|
171
|
-
log(`Removed temporary ESLint config at ${tempConfigPath}`, "info", quiet);
|
|
123
|
+
writeFileSync(tempConfigPath, configContent, 'utf8');
|
|
124
|
+
configPath = tempConfigPath;
|
|
125
|
+
if (debug) {
|
|
126
|
+
log(`Created temporary default ESLint config at: ${tempConfigPath}`, 'info', quiet);
|
|
127
|
+
} else {
|
|
128
|
+
log('No ESLint configuration found. Using Lex default configuration.', 'info', quiet);
|
|
129
|
+
}
|
|
172
130
|
}
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
|
|
131
|
+
const eslintBinary = resolveBinaryPath('eslint', 'eslint');
|
|
132
|
+
if (!eslintBinary) {
|
|
133
|
+
log(`\n${cliName} Error: ESLint binary not found in Lex's node_modules`, 'error', quiet);
|
|
134
|
+
log('Please reinstall Lex or check your installation.', 'info', quiet);
|
|
135
|
+
return 1;
|
|
176
136
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
137
|
+
// Base ESLint arguments
|
|
138
|
+
const baseEslintArgs = [
|
|
139
|
+
...fix ? [
|
|
140
|
+
'--fix'
|
|
141
|
+
] : [],
|
|
142
|
+
...debug ? [
|
|
143
|
+
'--debug'
|
|
144
|
+
] : [],
|
|
145
|
+
'--no-error-on-unmatched-pattern',
|
|
146
|
+
'--no-warn-ignored'
|
|
147
|
+
];
|
|
148
|
+
// Add config path
|
|
149
|
+
const configArgs = configPath ? [
|
|
150
|
+
'--config',
|
|
151
|
+
configPath
|
|
152
|
+
] : [];
|
|
153
|
+
const jsResult = await execa(eslintBinary, [
|
|
154
|
+
'src/**/*.{js,jsx}',
|
|
155
|
+
...configArgs,
|
|
156
|
+
...baseEslintArgs
|
|
157
|
+
], {
|
|
158
|
+
cwd,
|
|
159
|
+
reject: false,
|
|
160
|
+
shell: true,
|
|
161
|
+
stdio: 'pipe'
|
|
162
|
+
});
|
|
163
|
+
if (jsResult.stdout) {
|
|
164
|
+
// eslint-disable-next-line no-console
|
|
165
|
+
console.log(jsResult.stdout);
|
|
166
|
+
if (captureOutput) {
|
|
167
|
+
captureOutput(jsResult.stdout);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (jsResult.stderr) {
|
|
171
|
+
// eslint-disable-next-line no-console
|
|
172
|
+
console.error(jsResult.stderr);
|
|
173
|
+
if (captureOutput) {
|
|
174
|
+
captureOutput(jsResult.stderr);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
let tsResult = {
|
|
178
|
+
exitCode: 0,
|
|
179
|
+
stderr: '',
|
|
180
|
+
stdout: ''
|
|
181
|
+
};
|
|
182
|
+
if (useTypescript) {
|
|
183
|
+
tsResult = await execa(eslintBinary, [
|
|
184
|
+
'src/**/*.{ts,tsx}',
|
|
185
|
+
...configArgs,
|
|
186
|
+
...baseEslintArgs
|
|
187
|
+
], {
|
|
188
|
+
cwd,
|
|
189
|
+
reject: false,
|
|
190
|
+
shell: true,
|
|
191
|
+
stdio: 'pipe'
|
|
192
|
+
});
|
|
193
|
+
if (tsResult.stdout) {
|
|
194
|
+
// eslint-disable-next-line no-console
|
|
195
|
+
console.log(tsResult.stdout);
|
|
196
|
+
}
|
|
197
|
+
if (tsResult.stderr) {
|
|
198
|
+
// eslint-disable-next-line no-console
|
|
199
|
+
console.error(tsResult.stderr);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Clean up temp file if created
|
|
203
|
+
if (tempConfigPath && existsSync(tempConfigPath)) {
|
|
204
|
+
try {
|
|
205
|
+
unlinkSync(tempConfigPath);
|
|
206
|
+
if (debug) {
|
|
207
|
+
log(`Removed temporary ESLint config at ${tempConfigPath}`, 'info', quiet);
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
// Ignore errors when cleaning up
|
|
211
|
+
if (debug) {
|
|
212
|
+
log(`Failed to remove temporary ESLint config: ${error.message}`, 'warn', quiet);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const eslintNotFound = jsResult.stderr?.includes('command not found') || jsResult.stderr?.includes('eslint: command not found');
|
|
217
|
+
if (eslintNotFound) {
|
|
218
|
+
spinner.fail('ESLint not found!');
|
|
219
|
+
log(`\n${cliName} Error: Lex's ESLint binary not found. Please reinstall Lex or check your installation.`, 'error', quiet);
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
if (jsResult.exitCode === 0 && tsResult.exitCode === 0) {
|
|
223
|
+
spinner.succeed('Linting completed!');
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
const noFilesFound = (jsResult.stderr?.includes('No such file or directory') || jsResult.stdout?.includes('No such file or directory')) && (!useTypescript || tsResult.stderr?.includes('No such file or directory') || tsResult.stdout?.includes('No such file or directory'));
|
|
227
|
+
if (noFilesFound) {
|
|
228
|
+
spinner.succeed('No files found to lint');
|
|
229
|
+
return 0;
|
|
230
|
+
}
|
|
231
|
+
spinner.fail('Linting failed!');
|
|
232
|
+
log(`\n${cliName} Error: ESLint found issues in your code.`, 'error', quiet);
|
|
233
|
+
return 1;
|
|
234
|
+
} catch (error) {
|
|
235
|
+
spinner.fail('Linting failed!');
|
|
236
|
+
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
|
|
237
|
+
return 1;
|
|
194
238
|
}
|
|
195
|
-
spinner.fail("Linting failed!");
|
|
196
|
-
log(`
|
|
197
|
-
${cliName} Error: ESLint found issues in your code.`, "error", quiet);
|
|
198
|
-
return 1;
|
|
199
|
-
} catch (error) {
|
|
200
|
-
spinner.fail("Linting failed!");
|
|
201
|
-
log(`
|
|
202
|
-
${cliName} Error: ${error.message}`, "error", quiet);
|
|
203
|
-
return 1;
|
|
204
|
-
}
|
|
205
239
|
};
|
|
206
|
-
const applyAIFix = async (cwd, errors, quiet)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
240
|
+
const applyAIFix = async (cwd, errors, quiet)=>{
|
|
241
|
+
const spinner = createSpinner(quiet);
|
|
242
|
+
spinner.start('Using AI to fix remaining lint issues...');
|
|
243
|
+
try {
|
|
244
|
+
const fileErrorMap = new Map();
|
|
245
|
+
const lines = errors.split('\n');
|
|
246
|
+
let currentFile = '';
|
|
247
|
+
for (const line of lines){
|
|
248
|
+
if (line.match(/^(\/|[A-Z]:\\).*?\.(js|jsx|ts|tsx)$/)) {
|
|
249
|
+
currentFile = line.trim();
|
|
250
|
+
if (!fileErrorMap.has(currentFile)) {
|
|
251
|
+
fileErrorMap.set(currentFile, []);
|
|
252
|
+
}
|
|
253
|
+
} else if (currentFile && line.trim() && line.match(/\s+\d+:\d+\s+(error|warning)\s+/)) {
|
|
254
|
+
const errorArray = fileErrorMap.get(currentFile);
|
|
255
|
+
if (errorArray) {
|
|
256
|
+
errorArray.push(line.trim());
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (fileErrorMap.size === 0) {
|
|
261
|
+
log('Using alternative error parsing strategy', 'info', quiet);
|
|
262
|
+
const sections = errors.split('\n\n');
|
|
263
|
+
for (const section of sections){
|
|
264
|
+
if (section.trim() === '') {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const lines = section.split('\n');
|
|
268
|
+
const filePath = lines[0].trim();
|
|
269
|
+
if (filePath.match(/\.(js|jsx|ts|tsx)$/)) {
|
|
270
|
+
fileErrorMap.set(filePath, []);
|
|
271
|
+
for(let i = 1; i < lines.length; i++){
|
|
272
|
+
if (lines[i].trim() !== '') {
|
|
273
|
+
fileErrorMap.get(filePath)?.push(lines[i].trim());
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (fileErrorMap.size === 0) {
|
|
280
|
+
log('Using direct file path extraction', 'info', quiet);
|
|
281
|
+
const filePathRegex = /(?:\/|[A-Z]:\\)(?:[^:\n]+\/)*[^:\n]+\.(js|jsx|ts|tsx)/g;
|
|
282
|
+
const filePaths = errors.match(filePathRegex) || [];
|
|
283
|
+
for (const filePath of filePaths){
|
|
284
|
+
if (!fileErrorMap.has(filePath) && existsSync(filePath)) {
|
|
285
|
+
fileErrorMap.set(filePath, []);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const knownFiles = [
|
|
289
|
+
pathResolve(cwd, 'src/create/changelog.ts'),
|
|
290
|
+
pathResolve(cwd, 'src/utils/aiService.ts'),
|
|
291
|
+
pathResolve(cwd, 'src/utils/app.ts'),
|
|
292
|
+
pathResolve(cwd, 'src/utils/reactShim.ts'),
|
|
293
|
+
pathResolve(cwd, 'src/commands/lint/autofix.js')
|
|
294
|
+
];
|
|
295
|
+
for (const file of knownFiles){
|
|
296
|
+
if (existsSync(file) && !fileErrorMap.has(file)) {
|
|
297
|
+
fileErrorMap.set(file, []);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
for (const filePath of fileErrorMap.keys()){
|
|
302
|
+
if (!existsSync(filePath)) {
|
|
303
|
+
log(`File not found: ${filePath}`, 'warn', quiet);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
log(`Processing file: ${filePath}`, 'info', quiet);
|
|
307
|
+
const isCursorIDE = LexConfig.config.ai?.provider === 'cursor' || process.env.CURSOR_IDE === 'true';
|
|
308
|
+
if (isCursorIDE) {
|
|
309
|
+
try {
|
|
310
|
+
const prompt = `Fix all ESLint errors in this file. Focus on:
|
|
277
311
|
1. Fixing naming conventions
|
|
278
312
|
2. Fixing sort-keys issues
|
|
279
313
|
3. Replacing console.log with log utility
|
|
@@ -346,41 +380,47 @@ import {app, events, images, locations, messages, posts, tags, users, websocket}
|
|
|
346
380
|
const config = {baseUrl: 'https://api.example.com', apiKey: 'value', timeout: 5000};
|
|
347
381
|
|
|
348
382
|
Fix ONLY the specific ESLint errors. Return the properly formatted code.`;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
383
|
+
try {
|
|
384
|
+
const promptFile = pathResolve(cwd, '.cursor_prompt_temp.txt');
|
|
385
|
+
writeFileSync(promptFile, prompt, 'utf8');
|
|
386
|
+
// Use Cursor CLI to fix the file
|
|
387
|
+
await execa('cursor', [
|
|
388
|
+
'edit',
|
|
389
|
+
'--file',
|
|
390
|
+
filePath,
|
|
391
|
+
'--prompt-file',
|
|
392
|
+
promptFile
|
|
393
|
+
], {
|
|
394
|
+
cwd,
|
|
395
|
+
reject: false,
|
|
396
|
+
stdio: 'pipe'
|
|
397
|
+
});
|
|
398
|
+
try {
|
|
399
|
+
unlinkSync(promptFile);
|
|
400
|
+
} catch (_error) {}
|
|
401
|
+
log(`Applied Cursor AI fixes to ${filePath}`, 'info', quiet);
|
|
402
|
+
} catch {
|
|
403
|
+
const wasModified = await applyDirectFixes(filePath, quiet);
|
|
404
|
+
if (wasModified) {
|
|
405
|
+
log(`Applied direct fixes to ${filePath}`, 'info', quiet);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
} catch (error) {
|
|
409
|
+
log(`Error using Cursor AI: ${error.message}`, 'error', quiet);
|
|
410
|
+
await applyDirectFixes(filePath, quiet);
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
const wasModified = await applyDirectFixes(filePath, quiet);
|
|
414
|
+
if (wasModified) {
|
|
415
|
+
log(`Applied direct fixes to ${filePath}`, 'info', quiet);
|
|
416
|
+
}
|
|
417
|
+
const fileErrors = fileErrorMap.get(filePath) || [];
|
|
418
|
+
if (fileErrors.length > 0) {
|
|
419
|
+
try {
|
|
420
|
+
const { callAIService } = await import('../../utils/aiService.js');
|
|
421
|
+
const fileContent = readFileSync(filePath, 'utf8');
|
|
422
|
+
const prompt = `Fix the following ESLint errors in this code:
|
|
423
|
+
${fileErrors.join('\n')}
|
|
384
424
|
|
|
385
425
|
Here's the code:
|
|
386
426
|
\`\`\`
|
|
@@ -476,448 +516,405 @@ const config = {baseUrl: 'https://api.example.com', apiKey: 'value', timeout: 50
|
|
|
476
516
|
|
|
477
517
|
Fix ONLY the specific ESLint errors listed above. Review the entire file for compliance with all ESLint rules.
|
|
478
518
|
Return only the properly formatted fixed code without any explanations.`;
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
519
|
+
const fixedContent = await callAIService(prompt, quiet);
|
|
520
|
+
if (fixedContent && fixedContent !== fileContent) {
|
|
521
|
+
writeFileSync(filePath, fixedContent, 'utf8');
|
|
522
|
+
log(`Applied AI fixes to ${filePath}`, 'info', quiet);
|
|
523
|
+
}
|
|
524
|
+
} catch (error) {
|
|
525
|
+
log(`Error applying AI fixes to ${filePath}: ${error.message}`, 'error', quiet);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
483
528
|
}
|
|
484
|
-
} catch (error) {
|
|
485
|
-
log(`Error applying AI fixes to ${filePath}: ${error.message}`, "error", quiet);
|
|
486
|
-
}
|
|
487
529
|
}
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
console.error(error);
|
|
530
|
+
spinner.succeed('AI fixes applied successfully!');
|
|
531
|
+
} catch (error) {
|
|
532
|
+
spinner.fail('Failed to apply AI fixes');
|
|
533
|
+
log(`Error: ${error.message}`, 'error', quiet);
|
|
534
|
+
if (!quiet) {
|
|
535
|
+
console.error(error);
|
|
536
|
+
}
|
|
496
537
|
}
|
|
497
|
-
}
|
|
498
538
|
};
|
|
499
|
-
const applyDirectFixes = async (filePath, quiet)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
539
|
+
const applyDirectFixes = async (filePath, quiet)=>{
|
|
540
|
+
let wasModified = false;
|
|
541
|
+
try {
|
|
542
|
+
const fileContent = readFileSync(filePath, 'utf8');
|
|
543
|
+
let newContent = fileContent;
|
|
544
|
+
if (filePath.includes('aiService.ts')) {
|
|
545
|
+
log('Fixing issues in aiService.ts', 'info', quiet);
|
|
546
|
+
newContent = newContent.replace(/'Content-Type': 'application\/json',\s*'Authorization': `Bearer/g, '\'Authorization\': `Bearer\', \'Content-Type\': \'application/json\'');
|
|
547
|
+
newContent = newContent.replace(/headers: {([^}]*)},\s*method: 'POST'/g, 'method: \'POST\',\n headers: {$1}');
|
|
548
|
+
newContent = newContent.replace(/{role: 'system', content:/g, '{content:, role: \'system\',');
|
|
549
|
+
newContent = newContent.replace(/{role: 'user', content:/g, '{content:, role: \'user\',');
|
|
550
|
+
newContent = newContent.replace(/\(([^)]*?)_([a-zA-Z0-9]+)(\s*:[^)]*)\)/g, '($1$2$3)');
|
|
551
|
+
newContent = newContent.replace(/console\.log\(/g, 'log(');
|
|
552
|
+
if (!newContent.includes('import {log}') && newContent.includes('log(')) {
|
|
553
|
+
newContent = newContent.replace(/import {([^}]*)} from '(.*)';/, 'import {$1} from \'$2\';\nimport {log} from \'./log.js\';');
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (filePath.includes('reactShim.ts')) {
|
|
557
|
+
log('Fixing naming-convention issues in reactShim.ts', 'info', quiet);
|
|
558
|
+
newContent = newContent.replace('import * as React from', 'import * as react from');
|
|
559
|
+
newContent = newContent.replace(/React\./g, 'react.');
|
|
560
|
+
}
|
|
561
|
+
if (filePath.includes('changelog.ts')) {
|
|
562
|
+
log('Fixing issues in changelog.ts', 'info', quiet);
|
|
563
|
+
newContent = newContent.replace(/(\w+)\+\+/g, '$1 += 1');
|
|
564
|
+
newContent = newContent.replace(/\\\$/g, '$');
|
|
565
|
+
newContent = newContent.replace(/\\\./g, '.');
|
|
566
|
+
newContent = newContent.replace(/\\\*/g, '*');
|
|
567
|
+
newContent = newContent.replace(/\\:/g, ':');
|
|
568
|
+
}
|
|
569
|
+
if (filePath.includes('app.ts')) {
|
|
570
|
+
log('Fixing issues in app.ts', 'info', quiet);
|
|
571
|
+
newContent = newContent.replace(/console\.log\(/g, 'log(');
|
|
572
|
+
if (!newContent.includes('import {log}') && newContent.includes('log(')) {
|
|
573
|
+
newContent = newContent.replace(/import boxen from 'boxen';/, 'import boxen from \'boxen\';\nimport {log} from \'./log.js\';');
|
|
574
|
+
}
|
|
575
|
+
newContent = newContent.replace(/\\\//g, '/');
|
|
576
|
+
}
|
|
577
|
+
if (filePath.includes('autofix.js')) {
|
|
578
|
+
log('Fixing issues in autofix.js', 'info', quiet);
|
|
579
|
+
newContent = newContent.replace(/import {([^}]*)} from 'path';[\s\n]*import {([^}]*)} from 'path';/, 'import {$1, $2} from \'path\';');
|
|
580
|
+
newContent = newContent.replace(/__filename/g, 'currentFilename');
|
|
581
|
+
newContent = newContent.replace(/__dirname/g, 'currentDirname');
|
|
582
|
+
newContent = newContent.replace(/const prefix = type === 'error' \? '❌ ' : type === 'success' \? '✅ ' : 'ℹ️ ';/, 'let prefix = \'ℹ️ \';\nif(type === \'error\') {\n prefix = \'❌ \';\n} else if(type === \'success\') {\n prefix = \'✅ \';\n}');
|
|
583
|
+
newContent = newContent.replace(/async function runEslintFix\(\)/g, 'const runEslintFix = async ()');
|
|
584
|
+
newContent = newContent.replace(/async function getFilesWithErrors\(\)/g, 'const getFilesWithErrors = async ()');
|
|
585
|
+
newContent = newContent.replace(/async function isCursorAvailable\(\)/g, 'const isCursorAvailable = async ()');
|
|
586
|
+
newContent = newContent.replace(/async function fixFileWithCursorAI\(filePath\)/g, 'const fixFileWithCursorAI = async (filePath)');
|
|
587
|
+
newContent = newContent.replace(/async function main\(\)/g, 'const main = async ()');
|
|
588
|
+
newContent = newContent.replace(/import {existsSync, readFileSync, writeFileSync}/g, 'import {writeFileSync}');
|
|
589
|
+
newContent = newContent.replace(/console\.log\(`\${prefix} \${message}`\);/g, 'process.stdout.write(`${prefix} ${message}\\n`);');
|
|
590
|
+
newContent = newContent.replace(/} catch\(error\) {[\s\n]*\/\/ Ignore cleanup errors/g, '} catch(_) {\n // Ignore cleanup errors');
|
|
591
|
+
newContent = newContent.replace(/} catch\(error\) {[\s\n]*log\(/g, '} catch(err) {\n log(');
|
|
592
|
+
newContent = newContent.replace(/} catch\(error\) {[\s\n]*return false;/g, '} catch(_) {\n return false;');
|
|
593
|
+
newContent = newContent.replace(/for\(const filePath of filesWithErrors\) {[\s\n]*const success = await fixFileWithCursorAI\(filePath\);/g, 'const fixResults = await Promise.all(filesWithErrors.map(filePath => fixFileWithCursorAI(filePath)));\nfor(const success of fixResults) {');
|
|
594
|
+
newContent = newContent.replace(/fixedCount\+\+;/g, 'fixedCount += 1;');
|
|
595
|
+
}
|
|
596
|
+
if (newContent !== fileContent) {
|
|
597
|
+
writeFileSync(filePath, newContent, 'utf8');
|
|
598
|
+
log(`Fixed issues in ${filePath}`, 'info', quiet);
|
|
599
|
+
wasModified = true;
|
|
600
|
+
}
|
|
601
|
+
return wasModified;
|
|
602
|
+
} catch (error) {
|
|
603
|
+
log(`Error applying direct fixes to ${filePath}: ${error.message}`, 'error', quiet);
|
|
604
|
+
return false;
|
|
549
605
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
606
|
+
};
|
|
607
|
+
const loadAIConfig = async (cwd, quiet, debug = false)=>{
|
|
608
|
+
const configFormats = [
|
|
609
|
+
'js',
|
|
610
|
+
'mjs',
|
|
611
|
+
'cjs',
|
|
612
|
+
'ts',
|
|
613
|
+
'json'
|
|
614
|
+
];
|
|
615
|
+
const configBaseName = 'lex.config';
|
|
616
|
+
let lexConfigPath = '';
|
|
617
|
+
for (const format of configFormats){
|
|
618
|
+
const potentialPath = pathResolve(cwd, `./${configBaseName}.${format}`);
|
|
619
|
+
if (existsSync(potentialPath)) {
|
|
620
|
+
lexConfigPath = potentialPath;
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
560
623
|
}
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
);
|
|
623
|
-
newContent = newContent.replace(
|
|
624
|
-
/fixedCount\+\+;/g,
|
|
625
|
-
"fixedCount += 1;"
|
|
626
|
-
);
|
|
624
|
+
if (lexConfigPath) {
|
|
625
|
+
try {
|
|
626
|
+
// For MJS files, we need to use dynamic import with URL for compatibility
|
|
627
|
+
const format = extname(lexConfigPath).slice(1);
|
|
628
|
+
let importPath = lexConfigPath;
|
|
629
|
+
// Use URL protocol for ESM imports
|
|
630
|
+
if (format === 'mjs') {
|
|
631
|
+
try {
|
|
632
|
+
const url = new URL(`file://${lexConfigPath}`);
|
|
633
|
+
importPath = url.href;
|
|
634
|
+
if (debug) {
|
|
635
|
+
log(`Using URL format for MJS import: ${importPath}`, 'info', quiet);
|
|
636
|
+
}
|
|
637
|
+
} catch (urlError) {
|
|
638
|
+
log(`Error creating URL for MJS import: ${urlError.message}`, 'warn', debug || !quiet);
|
|
639
|
+
importPath = `file://${lexConfigPath}`;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (debug) {
|
|
643
|
+
log(`Trying to import config from ${importPath} (format: ${format})`, 'info', quiet);
|
|
644
|
+
}
|
|
645
|
+
let lexConfig;
|
|
646
|
+
try {
|
|
647
|
+
lexConfig = await import(importPath);
|
|
648
|
+
} catch (importError) {
|
|
649
|
+
if (importError.message.includes('not defined in ES module scope')) {
|
|
650
|
+
log(`ES Module syntax error in ${lexConfigPath}. Make sure you're using 'export' instead of 'module.exports'.`, 'error', quiet);
|
|
651
|
+
if (debug) {
|
|
652
|
+
console.error(importError);
|
|
653
|
+
}
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
throw importError;
|
|
657
|
+
}
|
|
658
|
+
// Handle both ESM (default export) and CommonJS (module.exports)
|
|
659
|
+
let configData = null;
|
|
660
|
+
if (lexConfig.default) {
|
|
661
|
+
configData = lexConfig.default;
|
|
662
|
+
if (debug) {
|
|
663
|
+
log(`Found default export in ${lexConfigPath}`, 'info', quiet);
|
|
664
|
+
}
|
|
665
|
+
} else {
|
|
666
|
+
// For CommonJS or other module systems
|
|
667
|
+
configData = lexConfig;
|
|
668
|
+
if (debug) {
|
|
669
|
+
log(`Using direct export in ${lexConfigPath}`, 'info', quiet);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (configData && configData.ai) {
|
|
673
|
+
log(`Found AI configuration in ${pathResolve(cwd, lexConfigPath)}, applying settings...`, 'info', quiet);
|
|
674
|
+
LexConfig.config.ai = {
|
|
675
|
+
...LexConfig.config.ai,
|
|
676
|
+
...configData.ai
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
} catch (error) {
|
|
680
|
+
log(`Error loading AI configuration from ${lexConfigPath}: ${error.message}`, 'warn', quiet);
|
|
681
|
+
if (debug) {
|
|
682
|
+
console.error(error);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
627
685
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
686
|
+
};
|
|
687
|
+
/**
|
|
688
|
+
* Load ESLint configuration from lex.config.* files
|
|
689
|
+
*/ const loadESLintConfig = async (cwd, quiet, debug)=>{
|
|
690
|
+
// Check if LexConfig already has ESLint configuration loaded
|
|
691
|
+
if (LexConfig.config.eslint && Object.keys(LexConfig.config.eslint).length > 0) {
|
|
692
|
+
log('Found ESLint configuration in lex.config.* file', 'info', debug || !quiet);
|
|
693
|
+
return true;
|
|
694
|
+
}
|
|
695
|
+
// Try to load from lex.config.* files if not already loaded
|
|
696
|
+
const configFormats = [
|
|
697
|
+
'js',
|
|
698
|
+
'mjs',
|
|
699
|
+
'cjs',
|
|
700
|
+
'ts',
|
|
701
|
+
'json'
|
|
702
|
+
];
|
|
703
|
+
const configBaseName = 'lex.config';
|
|
704
|
+
for (const format of configFormats){
|
|
705
|
+
const potentialPath = pathResolve(cwd, `./${configBaseName}.${format}`);
|
|
706
|
+
if (existsSync(potentialPath)) {
|
|
707
|
+
try {
|
|
708
|
+
// For MJS files, we need to use dynamic import with URL for compatibility
|
|
709
|
+
const fileFormat = extname(potentialPath).slice(1);
|
|
710
|
+
let importPath = potentialPath;
|
|
711
|
+
// Use URL protocol for ESM imports
|
|
712
|
+
if (fileFormat === 'mjs') {
|
|
713
|
+
try {
|
|
714
|
+
const url = new URL(`file://${potentialPath}`);
|
|
715
|
+
importPath = url.href;
|
|
716
|
+
if (debug) {
|
|
717
|
+
log(`Using URL format for MJS import: ${importPath}`, 'info', quiet);
|
|
718
|
+
}
|
|
719
|
+
} catch (urlError) {
|
|
720
|
+
log(`Error creating URL for MJS import: ${urlError.message}`, 'warn', debug || !quiet);
|
|
721
|
+
importPath = `file://${potentialPath}`;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (debug) {
|
|
725
|
+
log(`Trying to import config from ${importPath} (format: ${fileFormat})`, 'info', quiet);
|
|
726
|
+
}
|
|
727
|
+
let lexConfig;
|
|
728
|
+
try {
|
|
729
|
+
lexConfig = await import(importPath);
|
|
730
|
+
} catch (importError) {
|
|
731
|
+
if (importError.message.includes('not defined in ES module scope')) {
|
|
732
|
+
log(`ES Module syntax error in ${potentialPath}. Make sure you're using 'export' instead of 'module.exports'.`, 'error', quiet);
|
|
733
|
+
if (debug) {
|
|
734
|
+
console.error(importError);
|
|
735
|
+
}
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
throw importError;
|
|
739
|
+
}
|
|
740
|
+
// Handle both ESM (default export) and CommonJS (module.exports)
|
|
741
|
+
let configData = null;
|
|
742
|
+
if (lexConfig.default) {
|
|
743
|
+
configData = lexConfig.default;
|
|
744
|
+
if (debug) {
|
|
745
|
+
log(`Found default export in ${potentialPath}`, 'info', quiet);
|
|
746
|
+
}
|
|
747
|
+
} else {
|
|
748
|
+
// For CommonJS or other module systems
|
|
749
|
+
configData = lexConfig;
|
|
750
|
+
if (debug) {
|
|
751
|
+
log(`Using direct export in ${potentialPath}`, 'info', quiet);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
if (configData && configData.eslint && Object.keys(configData.eslint).length > 0) {
|
|
755
|
+
log(`Found ESLint configuration in ${pathResolve(cwd, potentialPath)}, applying settings...`, 'info', debug || !quiet);
|
|
756
|
+
LexConfig.config.eslint = {
|
|
757
|
+
...LexConfig.config.eslint,
|
|
758
|
+
...configData.eslint
|
|
759
|
+
};
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
} catch (error) {
|
|
763
|
+
log(`Error loading ESLint configuration from ${potentialPath}: ${error.message}`, 'warn', quiet);
|
|
764
|
+
if (debug) {
|
|
765
|
+
console.error(error);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
632
769
|
}
|
|
633
|
-
return wasModified;
|
|
634
|
-
} catch (error) {
|
|
635
|
-
log(`Error applying direct fixes to ${filePath}: ${error.message}`, "error", quiet);
|
|
636
770
|
return false;
|
|
637
|
-
}
|
|
638
771
|
};
|
|
639
|
-
const
|
|
640
|
-
const configFormats = ["js", "mjs", "cjs", "ts", "json"];
|
|
641
|
-
const configBaseName = "lex.config";
|
|
642
|
-
let lexConfigPath = "";
|
|
643
|
-
for (const format of configFormats) {
|
|
644
|
-
const potentialPath = pathResolve(cwd, `./${configBaseName}.${format}`);
|
|
645
|
-
if (existsSync(potentialPath)) {
|
|
646
|
-
lexConfigPath = potentialPath;
|
|
647
|
-
break;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
if (lexConfigPath) {
|
|
772
|
+
const removeFileComments = (filePath, quiet)=>{
|
|
651
773
|
try {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
if (debug) {
|
|
686
|
-
log(`Found default export in ${lexConfigPath}`, "info", quiet);
|
|
687
|
-
}
|
|
688
|
-
} else {
|
|
689
|
-
configData = lexConfig;
|
|
690
|
-
if (debug) {
|
|
691
|
-
log(`Using direct export in ${lexConfigPath}`, "info", quiet);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
if (configData && configData.ai) {
|
|
695
|
-
log(`Found AI configuration in ${pathResolve(cwd, lexConfigPath)}, applying settings...`, "info", quiet);
|
|
696
|
-
LexConfig.config.ai = { ...LexConfig.config.ai, ...configData.ai };
|
|
697
|
-
}
|
|
774
|
+
const fileContent = readFileSync(filePath, 'utf8');
|
|
775
|
+
if (fileContent.length > 1000000) {
|
|
776
|
+
log(`Skipping comment removal for large file: ${filePath}`, 'info', quiet);
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
// Use regex to match different types of comments
|
|
780
|
+
// Preserves:
|
|
781
|
+
// 1. Copyright notices (/* Copyright ... */)
|
|
782
|
+
// 2. TODO comments (// TODO: ...)
|
|
783
|
+
// 3. License headers (/* ... License ... */)
|
|
784
|
+
// Handle multi-line comments first - preserve copyright/license notices
|
|
785
|
+
let newContent = fileContent.replace(/\/\*[\s\S]*?\*\//g, (match)=>{
|
|
786
|
+
if (match.includes('Copyright') || match.includes('LICENSE') || match.includes('License') || match.includes('license')) {
|
|
787
|
+
return match;
|
|
788
|
+
}
|
|
789
|
+
return '';
|
|
790
|
+
});
|
|
791
|
+
// Handle single-line comments - preserve TODOs
|
|
792
|
+
newContent = newContent.replace(/\/\/.*$/gm, (match)=>{
|
|
793
|
+
if (match.includes('TODO') || match.includes('FIXME')) {
|
|
794
|
+
return match;
|
|
795
|
+
}
|
|
796
|
+
return '';
|
|
797
|
+
});
|
|
798
|
+
// Clean up any multiple blank lines created by comment removal
|
|
799
|
+
newContent = newContent.replace(/\n\s*\n\s*\n/g, '\n\n');
|
|
800
|
+
// If the file was modified, save it
|
|
801
|
+
if (newContent !== fileContent) {
|
|
802
|
+
writeFileSync(filePath, newContent, 'utf8');
|
|
803
|
+
log(`Removed comments from ${filePath}`, 'info', quiet);
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
return false;
|
|
698
807
|
} catch (error) {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
console.error(error);
|
|
702
|
-
}
|
|
808
|
+
log(`Error removing comments from ${filePath}: ${error.message}`, 'error', quiet);
|
|
809
|
+
return false;
|
|
703
810
|
}
|
|
704
|
-
}
|
|
705
811
|
};
|
|
706
|
-
const
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
812
|
+
export const lint = async (cmd, callback = process.exit)=>{
|
|
813
|
+
const { cliName = 'Lex', fix = false, debug = false, quiet = false, config = null, removeComments = false, 'remove-comments': removeCommentsFlag = false } = cmd;
|
|
814
|
+
const shouldRemoveComments = removeComments || removeCommentsFlag;
|
|
815
|
+
log(`${cliName} linting...`, 'info', quiet);
|
|
816
|
+
const cwd = process.cwd();
|
|
817
|
+
const spinner = createSpinner(quiet);
|
|
818
|
+
await loadAIConfig(cwd, quiet, debug);
|
|
819
|
+
let tempConfigPath = null;
|
|
820
|
+
try {
|
|
821
|
+
const useTypescript = detectTypeScript(cwd);
|
|
822
|
+
log(`TypeScript ${useTypescript ? 'detected' : 'not detected'} from tsconfig.json`, 'info', quiet);
|
|
823
|
+
if (useTypescript) {
|
|
824
|
+
LexConfig.checkLintTypescriptConfig();
|
|
825
|
+
}
|
|
826
|
+
ensureModuleType(cwd);
|
|
827
|
+
await installDependencies(cwd, useTypescript, quiet);
|
|
828
|
+
const projectConfigPath = pathResolve(cwd, 'eslint.config.mjs');
|
|
829
|
+
const projectConfigPathTs = pathResolve(cwd, 'eslint.config.ts');
|
|
830
|
+
const hasEslintConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs) || existsSync(pathResolve(cwd, '.eslintrc.js')) || existsSync(pathResolve(cwd, '.eslintrc.json')) || existsSync(pathResolve(cwd, '.eslintrc.yml')) || existsSync(pathResolve(cwd, '.eslintrc.yaml')) || existsSync(pathResolve(cwd, '.eslintrc'));
|
|
831
|
+
const hasLexEslintConfig = await loadESLintConfig(cwd, quiet, debug);
|
|
832
|
+
if (hasLexEslintConfig) {
|
|
833
|
+
log('Using ESLint configuration from lex.config.* file', 'info', quiet);
|
|
834
|
+
}
|
|
835
|
+
if (existsSync(pathResolve(cwd, '.eslintrc.json'))) {
|
|
836
|
+
unlinkSync(pathResolve(cwd, '.eslintrc.json'));
|
|
837
|
+
}
|
|
838
|
+
let lexConfigPath = '';
|
|
839
|
+
let shouldCreateTempConfig = false;
|
|
840
|
+
if (!hasEslintConfig && !hasLexEslintConfig) {
|
|
841
|
+
const possiblePaths = [
|
|
842
|
+
pathResolve(currentDirname, '../../../../eslint.config.ts'),
|
|
843
|
+
pathResolve(currentDirname, '../../../../eslint.config.jms'),
|
|
844
|
+
pathResolve(process.env.LEX_HOME || './node_modules/@nlabs/lex', 'eslint.config.ts'),
|
|
845
|
+
pathResolve(process.env.LEX_HOME || './node_modules/@nlabs/lex', 'eslint.config.mjs')
|
|
846
|
+
];
|
|
847
|
+
for (const path of possiblePaths){
|
|
848
|
+
if (existsSync(path)) {
|
|
849
|
+
lexConfigPath = path;
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
723
853
|
if (debug) {
|
|
724
|
-
|
|
854
|
+
log(`Current directory: ${currentDirname}`, 'info', quiet);
|
|
855
|
+
log(`Project config path: ${projectConfigPath}`, 'info', quiet);
|
|
856
|
+
log(`Project config exists: ${hasEslintConfig}`, 'info', quiet);
|
|
857
|
+
log(`Found Lex config: ${lexConfigPath}`, 'info', quiet);
|
|
858
|
+
log(`Lex config exists: ${!!lexConfigPath && existsSync(lexConfigPath)}`, 'info', quiet);
|
|
859
|
+
}
|
|
860
|
+
if (lexConfigPath && existsSync(lexConfigPath)) {
|
|
861
|
+
log('No ESLint configuration found in project. Using Lex\'s default configuration.', 'info', quiet);
|
|
862
|
+
} else {
|
|
863
|
+
shouldCreateTempConfig = true;
|
|
725
864
|
}
|
|
726
|
-
} catch (urlError) {
|
|
727
|
-
log(`Error creating URL for MJS import: ${urlError.message}`, "warn", debug || !quiet);
|
|
728
|
-
importPath = `file://${potentialPath}`;
|
|
729
|
-
}
|
|
730
865
|
}
|
|
731
|
-
if (
|
|
732
|
-
|
|
866
|
+
if (config) {
|
|
867
|
+
const userConfigPath = pathResolve(cwd, config);
|
|
868
|
+
if (existsSync(userConfigPath)) {
|
|
869
|
+
log(`Using specified ESLint configuration: ${config}`, 'info', quiet);
|
|
870
|
+
shouldCreateTempConfig = false;
|
|
871
|
+
} else {
|
|
872
|
+
log(`Specified ESLint configuration not found: ${config}. Using Lex's default configuration.`, 'warn', quiet);
|
|
873
|
+
}
|
|
733
874
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
if (fileContent.length > 1e6) {
|
|
778
|
-
log(`Skipping comment removal for large file: ${filePath}`, "info", quiet);
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
|
-
let newContent = fileContent.replace(
|
|
782
|
-
/\/\*[\s\S]*?\*\//g,
|
|
783
|
-
(match) => {
|
|
784
|
-
if (match.includes("Copyright") || match.includes("LICENSE") || match.includes("License") || match.includes("license")) {
|
|
785
|
-
return match;
|
|
786
|
-
}
|
|
787
|
-
return "";
|
|
788
|
-
}
|
|
789
|
-
);
|
|
790
|
-
newContent = newContent.replace(
|
|
791
|
-
/\/\/.*$/gm,
|
|
792
|
-
(match) => {
|
|
793
|
-
if (match.includes("TODO") || match.includes("FIXME")) {
|
|
794
|
-
return match;
|
|
795
|
-
}
|
|
796
|
-
return "";
|
|
797
|
-
}
|
|
798
|
-
);
|
|
799
|
-
newContent = newContent.replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
800
|
-
if (newContent !== fileContent) {
|
|
801
|
-
writeFileSync(filePath, newContent, "utf8");
|
|
802
|
-
log(`Removed comments from ${filePath}`, "info", quiet);
|
|
803
|
-
return true;
|
|
804
|
-
}
|
|
805
|
-
return false;
|
|
806
|
-
} catch (error) {
|
|
807
|
-
log(`Error removing comments from ${filePath}: ${error.message}`, "error", quiet);
|
|
808
|
-
return false;
|
|
809
|
-
}
|
|
810
|
-
};
|
|
811
|
-
const lint = async (cmd, callback = process.exit) => {
|
|
812
|
-
const {
|
|
813
|
-
cliName = "Lex",
|
|
814
|
-
fix = false,
|
|
815
|
-
debug = false,
|
|
816
|
-
quiet = false,
|
|
817
|
-
config = null,
|
|
818
|
-
removeComments = false,
|
|
819
|
-
"remove-comments": removeCommentsFlag = false
|
|
820
|
-
} = cmd;
|
|
821
|
-
const shouldRemoveComments = removeComments || removeCommentsFlag;
|
|
822
|
-
log(`${cliName} linting...`, "info", quiet);
|
|
823
|
-
const cwd = process.cwd();
|
|
824
|
-
const spinner = createSpinner(quiet);
|
|
825
|
-
await loadAIConfig(cwd, quiet, debug);
|
|
826
|
-
let tempConfigPath = null;
|
|
827
|
-
try {
|
|
828
|
-
const useTypescript = detectTypeScript(cwd);
|
|
829
|
-
log(`TypeScript ${useTypescript ? "detected" : "not detected"} from tsconfig.json`, "info", quiet);
|
|
830
|
-
if (useTypescript) {
|
|
831
|
-
LexConfig.checkLintTypescriptConfig();
|
|
832
|
-
}
|
|
833
|
-
ensureModuleType(cwd);
|
|
834
|
-
await installDependencies(cwd, useTypescript, quiet);
|
|
835
|
-
const projectConfigPath = pathResolve(cwd, "eslint.config.mjs");
|
|
836
|
-
const projectConfigPathTs = pathResolve(cwd, "eslint.config.ts");
|
|
837
|
-
const hasEslintConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs) || existsSync(pathResolve(cwd, ".eslintrc.js")) || existsSync(pathResolve(cwd, ".eslintrc.json")) || existsSync(pathResolve(cwd, ".eslintrc.yml")) || existsSync(pathResolve(cwd, ".eslintrc.yaml")) || existsSync(pathResolve(cwd, ".eslintrc"));
|
|
838
|
-
const hasLexEslintConfig = await loadESLintConfig(cwd, quiet, debug);
|
|
839
|
-
if (hasLexEslintConfig) {
|
|
840
|
-
log("Using ESLint configuration from lex.config.* file", "info", quiet);
|
|
841
|
-
}
|
|
842
|
-
if (existsSync(pathResolve(cwd, ".eslintrc.json"))) {
|
|
843
|
-
unlinkSync(pathResolve(cwd, ".eslintrc.json"));
|
|
844
|
-
}
|
|
845
|
-
let lexConfigPath = "";
|
|
846
|
-
let shouldCreateTempConfig = false;
|
|
847
|
-
if (!hasEslintConfig && !hasLexEslintConfig) {
|
|
848
|
-
const possiblePaths = [
|
|
849
|
-
pathResolve(currentDirname, "../../../../eslint.config.ts"),
|
|
850
|
-
pathResolve(currentDirname, "../../../../eslint.config.jms"),
|
|
851
|
-
pathResolve(process.env.LEX_HOME || "./node_modules/@nlabs/lex", "eslint.config.ts"),
|
|
852
|
-
pathResolve(process.env.LEX_HOME || "./node_modules/@nlabs/lex", "eslint.config.mjs")
|
|
853
|
-
];
|
|
854
|
-
for (const path of possiblePaths) {
|
|
855
|
-
if (existsSync(path)) {
|
|
856
|
-
lexConfigPath = path;
|
|
857
|
-
break;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
if (debug) {
|
|
861
|
-
log(`Current directory: ${currentDirname}`, "info", quiet);
|
|
862
|
-
log(`Project config path: ${projectConfigPath}`, "info", quiet);
|
|
863
|
-
log(`Project config exists: ${hasEslintConfig}`, "info", quiet);
|
|
864
|
-
log(`Found Lex config: ${lexConfigPath}`, "info", quiet);
|
|
865
|
-
log(`Lex config exists: ${!!lexConfigPath && existsSync(lexConfigPath)}`, "info", quiet);
|
|
866
|
-
}
|
|
867
|
-
if (lexConfigPath && existsSync(lexConfigPath)) {
|
|
868
|
-
log("No ESLint configuration found in project. Using Lex's default configuration.", "info", quiet);
|
|
869
|
-
} else {
|
|
870
|
-
shouldCreateTempConfig = true;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
if (config) {
|
|
874
|
-
const userConfigPath = pathResolve(cwd, config);
|
|
875
|
-
if (existsSync(userConfigPath)) {
|
|
876
|
-
log(`Using specified ESLint configuration: ${config}`, "info", quiet);
|
|
877
|
-
shouldCreateTempConfig = false;
|
|
878
|
-
} else {
|
|
879
|
-
log(`Specified ESLint configuration not found: ${config}. Using Lex's default configuration.`, "warn", quiet);
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
if (shouldCreateTempConfig) {
|
|
883
|
-
log("No ESLint configuration found. Creating a temporary configuration...", "info", quiet);
|
|
884
|
-
const configResult = createDefaultESLintConfig(useTypescript, cwd);
|
|
885
|
-
tempConfigPath = configResult.configPath;
|
|
886
|
-
}
|
|
887
|
-
let eslintOutput = "";
|
|
888
|
-
const captureOutput = (output) => {
|
|
889
|
-
eslintOutput += `${output}
|
|
890
|
-
`;
|
|
891
|
-
};
|
|
892
|
-
const result = await runEslintWithLex(cwd, quiet, cliName, true, debug, useTypescript, captureOutput);
|
|
893
|
-
if (shouldRemoveComments) {
|
|
894
|
-
spinner.start("Removing comments from files...");
|
|
895
|
-
const glob = await import("glob");
|
|
896
|
-
const files = glob.sync("{src,lib}/**/*.{js,jsx,ts,tsx}", {
|
|
897
|
-
cwd,
|
|
898
|
-
ignore: ["**/node_modules/**", "**/lib/**", "**/dist/**", "**/build/**"]
|
|
899
|
-
});
|
|
900
|
-
let processedCount = 0;
|
|
901
|
-
for (const file of files) {
|
|
902
|
-
const filePath = pathResolve(cwd, file);
|
|
903
|
-
if (removeFileComments(filePath, quiet)) {
|
|
904
|
-
processedCount++;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
spinner.succeed(`Removed comments from ${processedCount} files`);
|
|
908
|
-
}
|
|
909
|
-
if (result !== 0 && fix) {
|
|
910
|
-
const aiConfigured = LexConfig.config.ai?.provider && LexConfig.config.ai.provider !== "none";
|
|
911
|
-
if (aiConfigured) {
|
|
912
|
-
log("Applying AI fixes to remaining issues...", "info", quiet);
|
|
913
|
-
await applyAIFix(cwd, eslintOutput, quiet);
|
|
914
|
-
const afterFixResult = await runEslintWithLex(cwd, quiet, cliName, false, debug, useTypescript);
|
|
915
|
-
callback(afterFixResult);
|
|
916
|
-
return afterFixResult;
|
|
917
|
-
}
|
|
918
|
-
log("ESLint could not fix all issues automatically.", "warn", quiet);
|
|
919
|
-
log("To enable AI-powered fixes, add AI configuration to your lex.config file:", "info", quiet);
|
|
920
|
-
log(`
|
|
875
|
+
if (shouldCreateTempConfig) {
|
|
876
|
+
log('No ESLint configuration found. Creating a temporary configuration...', 'info', quiet);
|
|
877
|
+
const configResult = createDefaultESLintConfig(useTypescript, cwd);
|
|
878
|
+
tempConfigPath = configResult.configPath;
|
|
879
|
+
}
|
|
880
|
+
let eslintOutput = '';
|
|
881
|
+
const captureOutput = (output)=>{
|
|
882
|
+
eslintOutput += `${output}\n`;
|
|
883
|
+
};
|
|
884
|
+
const result = await runEslintWithLex(cwd, quiet, cliName, true, debug, useTypescript, captureOutput);
|
|
885
|
+
if (shouldRemoveComments) {
|
|
886
|
+
spinner.start('Removing comments from files...');
|
|
887
|
+
const glob = await import('glob');
|
|
888
|
+
const files = glob.sync('{src,lib}/**/*.{js,jsx,ts,tsx}', {
|
|
889
|
+
cwd,
|
|
890
|
+
ignore: [
|
|
891
|
+
'**/node_modules/**',
|
|
892
|
+
'**/lib/**',
|
|
893
|
+
'**/dist/**',
|
|
894
|
+
'**/build/**'
|
|
895
|
+
]
|
|
896
|
+
});
|
|
897
|
+
let processedCount = 0;
|
|
898
|
+
for (const file of files){
|
|
899
|
+
const filePath = pathResolve(cwd, file);
|
|
900
|
+
if (removeFileComments(filePath, quiet)) {
|
|
901
|
+
processedCount++;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
spinner.succeed(`Removed comments from ${processedCount} files`);
|
|
905
|
+
}
|
|
906
|
+
if (result !== 0 && fix) {
|
|
907
|
+
const aiConfigured = LexConfig.config.ai?.provider && LexConfig.config.ai.provider !== 'none';
|
|
908
|
+
if (aiConfigured) {
|
|
909
|
+
log('Applying AI fixes to remaining issues...', 'info', quiet);
|
|
910
|
+
await applyAIFix(cwd, eslintOutput, quiet);
|
|
911
|
+
const afterFixResult = await runEslintWithLex(cwd, quiet, cliName, false, debug, useTypescript);
|
|
912
|
+
callback(afterFixResult);
|
|
913
|
+
return afterFixResult;
|
|
914
|
+
}
|
|
915
|
+
log('ESLint could not fix all issues automatically.', 'warn', quiet);
|
|
916
|
+
log('To enable AI-powered fixes, add AI configuration to your lex.config file:', 'info', quiet);
|
|
917
|
+
log(`
|
|
921
918
|
// In lex.config.js (or lex.config.mjs, lex.config.cjs, etc.)
|
|
922
919
|
export default {
|
|
923
920
|
// Your existing config
|
|
@@ -925,38 +922,34 @@ export default {
|
|
|
925
922
|
provider: 'cursor' // or 'openai', 'anthropic', etc.
|
|
926
923
|
// Additional provider-specific settings
|
|
927
924
|
}
|
|
928
|
-
};`,
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
925
|
+
};`, 'info', quiet);
|
|
926
|
+
}
|
|
927
|
+
callback(result);
|
|
928
|
+
return result;
|
|
929
|
+
} catch (error) {
|
|
930
|
+
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
|
|
931
|
+
if (spinner) {
|
|
932
|
+
spinner.fail('Linting failed!');
|
|
933
|
+
}
|
|
934
|
+
callback(1);
|
|
935
|
+
return 1;
|
|
936
|
+
} finally{
|
|
937
|
+
const tempFilePaths = [
|
|
938
|
+
tempConfigPath,
|
|
939
|
+
pathResolve(cwd, '.lex-temp-eslint.cjs'),
|
|
940
|
+
pathResolve(cwd, '.lex-temp-default-eslint.cjs')
|
|
941
|
+
];
|
|
942
|
+
for (const filePath of tempFilePaths){
|
|
943
|
+
if (filePath && existsSync(filePath)) {
|
|
944
|
+
try {
|
|
945
|
+
unlinkSync(filePath);
|
|
946
|
+
if (debug) {
|
|
947
|
+
log(`Cleaned up temporary ESLint config at ${filePath}`, 'info', quiet);
|
|
948
|
+
}
|
|
949
|
+
} catch {}
|
|
950
|
+
}
|
|
954
951
|
}
|
|
955
|
-
}
|
|
956
952
|
}
|
|
957
|
-
}
|
|
958
953
|
};
|
|
959
|
-
|
|
960
|
-
lint
|
|
961
|
-
};
|
|
962
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjItUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhlY2F9IGZyb20gJ2V4ZWNhJztcbmltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB1bmxpbmtTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmUsIGV4dG5hbWV9IGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7cmVzb2x2ZUJpbmFyeVBhdGh9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcyc7XG5cbmxldCBjdXJyZW50RmlsZW5hbWU6IHN0cmluZztcbmxldCBjdXJyZW50RGlybmFtZTogc3RyaW5nO1xuXG50cnkge1xuICBjdXJyZW50RmlsZW5hbWUgPSBldmFsKCdyZXF1aXJlKFwidXJsXCIpLmZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKScpO1xuICBjdXJyZW50RGlybmFtZSA9IGRpcm5hbWUoY3VycmVudEZpbGVuYW1lKTtcbn0gY2F0Y2gge1xuICBjdXJyZW50RmlsZW5hbWUgPSBwcm9jZXNzLmN3ZCgpO1xuICBjdXJyZW50RGlybmFtZSA9IHByb2Nlc3MuY3dkKCk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGludE9wdGlvbnMge1xuICByZWFkb25seSBjYWNoZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNhY2hlRmlsZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY2FjaGVMb2NhdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgY2xpTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY29sb3I/OiBib29sZWFuO1xuICByZWFkb25seSBjb25maWc/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlYnVnPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZW52Pzogc3RyaW5nO1xuICByZWFkb25seSBlbnZJbmZvPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZXh0Pzogc3RyaW5nO1xuICByZWFkb25seSBmaXg/OiBib29sZWFuO1xuICByZWFkb25seSBmaXhEcnlSdW4/OiBib29sZWFuO1xuICByZWFkb25seSBmaXhUeXBlPzogc3RyaW5nO1xuICByZWFkb25seSBmb3JtYXQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGdsb2JhbD86IHN0cmluZztcbiAgcmVhZG9ubHkgaWdub3JlUGF0aD86IHN0cmluZztcbiAgcmVhZG9ubHkgaWdub3JlUGF0dGVybj86IHN0cmluZztcbiAgcmVhZG9ubHkgaW5pdD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG1heFdhcm5pbmdzPzogc3RyaW5nO1xuICByZWFkb25seSBub0NvbG9yPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9Fc2xpbnRyYz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG5vSWdub3JlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9JbmxpbmVDb25maWc/OiBib29sZWFuO1xuICByZWFkb25seSBvdXRwdXRGaWxlPzogc3RyaW5nO1xuICByZWFkb25seSBwYXJzZXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnNlck9wdGlvbnM/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBsdWdpbj86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJpbnRDb25maWc/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgcmVtb3ZlQ29tbWVudHM/OiBib29sZWFuO1xuICByZWFkb25seSByZXBvcnRVbnVzZWREaXNhYmxlRGlyZWN0aXZlcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJlc29sdmVQbHVnaW5zUmVsYXRpdmVUbz86IHN0cmluZztcbiAgcmVhZG9ubHkgcnVsZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcnVsZXNkaXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0ZGluPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3RkaW5GaWxlbmFtZT86IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgTGludENhbGxiYWNrID0gdHlwZW9mIHByb2Nlc3MuZXhpdDtcblxuaW50ZXJmYWNlIENvbmZpZ1Jlc3VsdCB7XG4gIGNvbmZpZ1BhdGg6IHN0cmluZztcbiAgb3JpZ2luYWxDb25maWc6IHN0cmluZyB8IG51bGw7XG59XG5cbmNvbnN0IGNyZWF0ZURlZmF1bHRFU0xpbnRDb25maWcgPSAodXNlVHlwZXNjcmlwdDogYm9vbGVhbiwgY3dkOiBzdHJpbmcpOiBDb25maWdSZXN1bHQgPT4ge1xuICAvLyBVc2UgYSB0ZW1wb3JhcnkgZmlsZSBwYXRoIGluc3RlYWQgb2YgY3JlYXRpbmcgaW4gdGhlIHByb2plY3QgZGlyZWN0b3J5XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICcubGV4LXRlbXAtZGVmYXVsdC1lc2xpbnQuY2pzJyk7XG4gIGNvbnN0IG9yaWdpbmFsQ29uZmlnID0gbnVsbDtcblxuICAvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgQ29tbW9uSlMgbW9kdWxlIHRoYXQgcmVxdWlyZXMgTGV4J3MgRVNMaW50IGNvbmZpZ1xuICBjb25zdCBjb25maWdDb250ZW50ID0gYC8vIFRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGdlbmVyYXRlZCBieSBMZXhcbmNvbnN0IGxleENvbmZpZyA9IHJlcXVpcmUoJ0BubGFicy9sZXgvZXNsaW50LmNvbmZpZy5tanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBsZXhDb25maWc7YDtcblxuICB3cml0ZUZpbGVTeW5jKGNvbmZpZ1BhdGgsIGNvbmZpZ0NvbnRlbnQsICd1dGY4Jyk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb25maWdQYXRoLFxuICAgIG9yaWdpbmFsQ29uZmlnXG4gIH07XG59O1xuXG5jb25zdCBkZXRlY3RUeXBlU2NyaXB0ID0gKGN3ZDogc3RyaW5nKTogYm9vbGVhbiA9PiBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmpzb24nKSk7XG5cbi8qKlxuICogRW5zdXJlIHBhY2thZ2UuanNvbiBoYXMgdHlwZTogbW9kdWxlIGZvciBFU00gc3VwcG9ydFxuICovXG5jb25zdCBlbnN1cmVNb2R1bGVUeXBlID0gKGN3ZDogc3RyaW5nKTogdm9pZCA9PiB7XG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3BhY2thZ2UuanNvbicpO1xuXG4gIGlmKGV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYWNrYWdlSnNvbkNvbnRlbnQgPSByZWFkRmlsZVN5bmMocGFja2FnZUpzb25QYXRoLCAndXRmOCcpO1xuICAgICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKHBhY2thZ2VKc29uQ29udGVudCk7XG5cbiAgICAgIC8vIElmIHR5cGUgaXMgbm90IHNldCB0byBtb2R1bGUsIHdhcm4gaW5zdGVhZCBvZiBhdXRvLW1vZGlmeWluZ1xuICAgICAgaWYocGFja2FnZUpzb24udHlwZSAhPT0gJ21vZHVsZScpIHtcbiAgICAgICAgbG9nKCdXYXJuaW5nOiBwYWNrYWdlLmpzb24gc2hvdWxkIGhhdmUgXCJ0eXBlXCI6IFwibW9kdWxlXCIgZm9yIEVTTSBzdXBwb3J0LiBQbGVhc2UgYWRkIHRoaXMgbWFudWFsbHkuJywgJ3dhcm4nLCBmYWxzZSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoX2Vycm9yKSB7XG4gICAgICAvLyBJZ25vcmUgZXJyb3JzXG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBpbnN0YWxsRGVwZW5kZW5jaWVzID0gYXN5bmMgKGN3ZDogc3RyaW5nLCB1c2VUeXBlc2NyaXB0OiBib29sZWFuLCBxdWlldDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZih1c2VUeXBlc2NyaXB0KSB7XG4gICAgbG9nKCdVc2luZyBUeXBlU2NyaXB0IEVTTGludCBmcm9tIExleC4uLicsICdpbmZvJywgcXVpZXQpO1xuICB9IGVsc2Uge1xuICAgIGxvZygnVXNpbmcgRVNMaW50IGZyb20gTGV4Li4uJywgJ2luZm8nLCBxdWlldCk7XG4gIH1cbn07XG5cbmNvbnN0IHJ1bkVzbGludFdpdGhMZXggPSBhc3luYyAoXG4gIGN3ZDogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhbixcbiAgY2xpTmFtZTogc3RyaW5nLFxuICBmaXg6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuLFxuICB1c2VUeXBlc2NyaXB0OiBib29sZWFuLFxuICBjYXB0dXJlT3V0cHV0PzogKG91dHB1dDogc3RyaW5nKSA9PiB2b2lkXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJ2VzbGludC5jb25maWcubWpzJyk7XG4gICAgY29uc3QgcHJvamVjdENvbmZpZ1BhdGhUcyA9IHBhdGhSZXNvbHZlKGN3ZCwgJ2VzbGludC5jb25maWcudHMnKTtcbiAgICBjb25zdCBoYXNQcm9qZWN0Q29uZmlnID0gZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnUGF0aCkgfHwgZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnUGF0aFRzKTtcbiAgICBjb25zdCBoYXNMZXhDb25maWdFc2xpbnQgPSBMZXhDb25maWcuY29uZmlnLmVzbGludCAmJiBPYmplY3Qua2V5cyhMZXhDb25maWcuY29uZmlnLmVzbGludCkubGVuZ3RoID4gMDtcblxuICAgIGNvbnN0IHBvc3NpYmxlUGF0aHMgPSBbXG4gICAgICBwYXRoUmVzb2x2ZShjdXJyZW50RGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcubWpzJyksXG4gICAgICBwYXRoUmVzb2x2ZShjdXJyZW50RGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcudHMnKSxcbiAgICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuZW52LkxFWF9IT01FIHx8ICcvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLm1qcycpLFxuICAgICAgcGF0aFJlc29sdmUocHJvY2Vzcy5lbnYuTEVYX0hPTUUgfHwgJy91c3IvbG9jYWwvbGliL25vZGVfbW9kdWxlcy9AbmxhYnMvbGV4JywgJ2VzbGludC5jb25maWcudHMnKVxuICAgIF07XG5cbiAgICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuXG4gICAgZm9yKGNvbnN0IHBhdGggb2YgcG9zc2libGVQYXRocykge1xuICAgICAgaWYoZXhpc3RzU3luYyhwYXRoKSkge1xuICAgICAgICBsZXhDb25maWdQYXRoID0gcGF0aDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGNvbmZpZ1BhdGggPSAnJztcbiAgICBsZXQgdGVtcENvbmZpZ1BhdGggPSAnJztcblxuICAgIC8vIFByaW9yaXR5OlxuICAgIC8vIDEuIFByb2plY3QgZXNsaW50LmNvbmZpZyBmaWxlc1xuICAgIC8vIDIuIEVTTGludCBjb25maWcgaW4gbGV4LmNvbmZpZy4qIGZpbGVcbiAgICAvLyAzLiBMZXgncyBkZWZhdWx0IGVzbGludC5jb25maWcubWpzXG4gICAgLy8gNC4gQ3JlYXRlIGEgdGVtcG9yYXJ5IGNvbmZpZyBmaWxlXG4gICAgaWYoaGFzUHJvamVjdENvbmZpZykge1xuICAgICAgY29uZmlnUGF0aCA9IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGhUcykgPyBwcm9qZWN0Q29uZmlnUGF0aFRzIDogcHJvamVjdENvbmZpZ1BhdGg7XG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYFVzaW5nIHByb2plY3QgRVNMaW50IGNvbmZpZyBmaWxlOiAke2NvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKGhhc0xleENvbmZpZ0VzbGludCkge1xuICAgICAgLy8gV2hlbiB1c2luZyBsZXguY29uZmlnLmVzbGludCwgY3JlYXRlIGEgdGVtcG9yYXJ5IEpTIGNvbmZpZyBmaWxlIChub3QgSlNPTilcbiAgICAgIC8vIHRvIGF2b2lkIEVTTSBKU09OIGltcG9ydCBpc3N1ZXNcbiAgICAgIHRlbXBDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCAnLmxleC10ZW1wLWVzbGludC5janMnKTtcblxuICAgICAgLy8gQ3JlYXRlIGEgQ29tbW9uSlMgbW9kdWxlIHRoYXQgZXh0ZW5kcyBMZXgncyBlc2xpbnQgY29uZmlnXG4gICAgICBjb25zdCBjb25maWdDb250ZW50ID0gYC8vIFRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGdlbmVyYXRlZCBieSBMZXhcbmNvbnN0IGxleENvbmZpZyA9IHJlcXVpcmUoJ0BubGFicy9sZXgvZXNsaW50LmNvbmZpZy5tanMnKTtcbmNvbnN0IHVzZXJDb25maWcgPSAke0pTT04uc3RyaW5naWZ5KExleENvbmZpZy5jb25maWcuZXNsaW50LCBudWxsLCAyKX07XG5cbi8vIE1lcmdlIExleCdzIGNvbmZpZyB3aXRoIHVzZXIgY29uZmlnXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgLi4ubGV4Q29uZmlnXG59O2A7XG5cbiAgICAgIHdyaXRlRmlsZVN5bmModGVtcENvbmZpZ1BhdGgsIGNvbmZpZ0NvbnRlbnQsICd1dGY4Jyk7XG4gICAgICBjb25maWdQYXRoID0gdGVtcENvbmZpZ1BhdGg7XG5cbiAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgIGxvZyhgVXNpbmcgRVNMaW50IGNvbmZpZyBmcm9tIGxleC5jb25maWcuKiBmaWxlIHZpYSB0ZW1wIGZpbGU6ICR7dGVtcENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKGxleENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyhsZXhDb25maWdQYXRoKSkge1xuICAgICAgY29uZmlnUGF0aCA9IGxleENvbmZpZ1BhdGg7XG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYFVzaW5nIExleCBFU0xpbnQgY29uZmlnIGZpbGU6ICR7Y29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ3JlYXRlIGEgdGVtcG9yYXJ5IGRlZmF1bHQgY29uZmlnIGZpbGUgaWYgbm8gb3RoZXIgY29uZmlnIGlzIGZvdW5kXG4gICAgICB0ZW1wQ29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJy5sZXgtdGVtcC1kZWZhdWx0LWVzbGludC5janMnKTtcblxuICAgICAgLy8gQ3JlYXRlIGEgYmFzaWMgRVNMaW50IGNvbmZpZ1xuICAgICAgY29uc3QgY29uZmlnQ29udGVudCA9IGAvLyBUZW1wb3JhcnkgZGVmYXVsdCBFU0xpbnQgY29uZmlnIGdlbmVyYXRlZCBieSBMZXhcbmNvbnN0IGxleENvbmZpZyA9IHJlcXVpcmUoJ0BubGFicy9sZXgvZXNsaW50LmNvbmZpZy5tanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBsZXhDb25maWc7YDtcblxuICAgICAgd3JpdGVGaWxlU3luYyh0ZW1wQ29uZmlnUGF0aCwgY29uZmlnQ29udGVudCwgJ3V0ZjgnKTtcbiAgICAgIGNvbmZpZ1BhdGggPSB0ZW1wQ29uZmlnUGF0aDtcblxuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBDcmVhdGVkIHRlbXBvcmFyeSBkZWZhdWx0IEVTTGludCBjb25maWcgYXQ6ICR7dGVtcENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2coJ05vIEVTTGludCBjb25maWd1cmF0aW9uIGZvdW5kLiBVc2luZyBMZXggZGVmYXVsdCBjb25maWd1cmF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGVzbGludEJpbmFyeSA9IHJlc29sdmVCaW5hcnlQYXRoKCdlc2xpbnQnLCAnZXNsaW50Jyk7XG5cbiAgICBpZighZXNsaW50QmluYXJ5KSB7XG4gICAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6IEVTTGludCBiaW5hcnkgbm90IGZvdW5kIGluIExleCdzIG5vZGVfbW9kdWxlc2AsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIGxvZygnUGxlYXNlIHJlaW5zdGFsbCBMZXggb3IgY2hlY2sgeW91ciBpbnN0YWxsYXRpb24uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICAvLyBCYXNlIEVTTGludCBhcmd1bWVudHNcbiAgICBjb25zdCBiYXNlRXNsaW50QXJncyA9IFtcbiAgICAgIC4uLihmaXggPyBbJy0tZml4J10gOiBbXSksXG4gICAgICAuLi4oZGVidWcgPyBbJy0tZGVidWcnXSA6IFtdKSxcbiAgICAgICctLW5vLWVycm9yLW9uLXVubWF0Y2hlZC1wYXR0ZXJuJyxcbiAgICAgICctLW5vLXdhcm4taWdub3JlZCdcbiAgICBdO1xuXG4gICAgLy8gQWRkIGNvbmZpZyBwYXRoXG4gICAgY29uc3QgY29uZmlnQXJncyA9IGNvbmZpZ1BhdGggPyBbJy0tY29uZmlnJywgY29uZmlnUGF0aF0gOiBbXTtcblxuICAgIGNvbnN0IGpzUmVzdWx0ID0gYXdhaXQgZXhlY2EoZXNsaW50QmluYXJ5LCBbXG4gICAgICAnc3JjLyoqLyoue2pzLGpzeH0nLFxuICAgICAgLi4uY29uZmlnQXJncyxcbiAgICAgIC4uLmJhc2VFc2xpbnRBcmdzXG4gICAgXSwge1xuICAgICAgY3dkLFxuICAgICAgcmVqZWN0OiBmYWxzZSxcbiAgICAgIHNoZWxsOiB0cnVlLFxuICAgICAgc3RkaW86ICdwaXBlJ1xuICAgIH0pO1xuXG4gICAgaWYoanNSZXN1bHQuc3Rkb3V0KSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5sb2coanNSZXN1bHQuc3Rkb3V0KTtcbiAgICAgIGlmKGNhcHR1cmVPdXRwdXQpIHtcbiAgICAgICAgY2FwdHVyZU91dHB1dChqc1Jlc3VsdC5zdGRvdXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGpzUmVzdWx0LnN0ZGVycikge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUuZXJyb3IoanNSZXN1bHQuc3RkZXJyKTtcbiAgICAgIGlmKGNhcHR1cmVPdXRwdXQpIHtcbiAgICAgICAgY2FwdHVyZU91dHB1dChqc1Jlc3VsdC5zdGRlcnIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCB0c1Jlc3VsdDogYW55ID0ge2V4aXRDb2RlOiAwLCBzdGRlcnI6ICcnLCBzdGRvdXQ6ICcnfTtcbiAgICBpZih1c2VUeXBlc2NyaXB0KSB7XG4gICAgICB0c1Jlc3VsdCA9IGF3YWl0IGV4ZWNhKGVzbGludEJpbmFyeSwgW1xuICAgICAgICAnc3JjLyoqLyoue3RzLHRzeH0nLFxuICAgICAgICAuLi5jb25maWdBcmdzLFxuICAgICAgICAuLi5iYXNlRXNsaW50QXJnc1xuICAgICAgXSwge1xuICAgICAgICBjd2QsXG4gICAgICAgIHJlamVjdDogZmFsc2UsXG4gICAgICAgIHNoZWxsOiB0cnVlLFxuICAgICAgICBzdGRpbzogJ3BpcGUnXG4gICAgICB9KTtcblxuICAgICAgaWYodHNSZXN1bHQuc3Rkb3V0KSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUubG9nKHRzUmVzdWx0LnN0ZG91dCk7XG4gICAgICB9XG5cbiAgICAgIGlmKHRzUmVzdWx0LnN0ZGVycikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLmVycm9yKHRzUmVzdWx0LnN0ZGVycik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXAgdGVtcCBmaWxlIGlmIGNyZWF0ZWRcbiAgICBpZih0ZW1wQ29uZmlnUGF0aCAmJiBleGlzdHNTeW5jKHRlbXBDb25maWdQYXRoKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdW5saW5rU3luYyh0ZW1wQ29uZmlnUGF0aCk7XG4gICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgbG9nKGBSZW1vdmVkIHRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGF0ICR7dGVtcENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIElnbm9yZSBlcnJvcnMgd2hlbiBjbGVhbmluZyB1cFxuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgRmFpbGVkIHRvIHJlbW92ZSB0ZW1wb3JhcnkgRVNMaW50IGNvbmZpZzogJHtlcnJvci5tZXNzYWdlfWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZXNsaW50Tm90Rm91bmQgPSBqc1Jlc3VsdC5zdGRlcnI/LmluY2x1ZGVzKCdjb21tYW5kIG5vdCBmb3VuZCcpIHx8IGpzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ2VzbGludDogY29tbWFuZCBub3QgZm91bmQnKTtcbiAgICBpZihlc2xpbnROb3RGb3VuZCkge1xuICAgICAgc3Bpbm5lci5mYWlsKCdFU0xpbnQgbm90IGZvdW5kIScpO1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBMZXgncyBFU0xpbnQgYmluYXJ5IG5vdCBmb3VuZC4gUGxlYXNlIHJlaW5zdGFsbCBMZXggb3IgY2hlY2sgeW91ciBpbnN0YWxsYXRpb24uYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgaWYoanNSZXN1bHQuZXhpdENvZGUgPT09IDAgJiYgdHNSZXN1bHQuZXhpdENvZGUgPT09IDApIHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnTGludGluZyBjb21wbGV0ZWQhJyk7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBjb25zdCBub0ZpbGVzRm91bmQgPVxuICAgICAgKGpzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSB8fCBqc1Jlc3VsdC5zdGRvdXQ/LmluY2x1ZGVzKCdObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5JykpICYmXG4gICAgICAoIXVzZVR5cGVzY3JpcHQgfHwgdHNSZXN1bHQuc3RkZXJyPy5pbmNsdWRlcygnTm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeScpIHx8IHRzUmVzdWx0LnN0ZG91dD8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSk7XG5cbiAgICBpZihub0ZpbGVzRm91bmQpIHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnTm8gZmlsZXMgZm91bmQgdG8gbGludCcpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHNwaW5uZXIuZmFpbCgnTGludGluZyBmYWlsZWQhJyk7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFU0xpbnQgZm91bmQgaXNzdWVzIGluIHlvdXIgY29kZS5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIDE7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdMaW50aW5nIGZhaWxlZCEnKTtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIDE7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGx5QUlGaXggPSBhc3luYyAoXG4gIGN3ZDogc3RyaW5nLFxuICBlcnJvcnM6IHN0cmluZyxcbiAgcXVpZXQ6IGJvb2xlYW5cbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG4gIHNwaW5uZXIuc3RhcnQoJ1VzaW5nIEFJIHRvIGZpeCByZW1haW5pbmcgbGludCBpc3N1ZXMuLi4nKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGZpbGVFcnJvck1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBjb25zdCBsaW5lcyA9IGVycm9ycy5zcGxpdCgnXFxuJyk7XG4gICAgbGV0IGN1cnJlbnRGaWxlID0gJyc7XG5cbiAgICBmb3IoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgaWYobGluZS5tYXRjaCgvXihcXC98W0EtWl06XFxcXCkuKj9cXC4oanN8anN4fHRzfHRzeCkkLykpIHtcbiAgICAgICAgY3VycmVudEZpbGUgPSBsaW5lLnRyaW0oKTtcbiAgICAgICAgaWYoIWZpbGVFcnJvck1hcC5oYXMoY3VycmVudEZpbGUpKSB7XG4gICAgICAgICAgZmlsZUVycm9yTWFwLnNldChjdXJyZW50RmlsZSwgW10pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoY3VycmVudEZpbGUgJiYgbGluZS50cmltKCkgJiYgbGluZS5tYXRjaCgvXFxzK1xcZCs6XFxkK1xccysoZXJyb3J8d2FybmluZylcXHMrLykpIHtcbiAgICAgICAgY29uc3QgZXJyb3JBcnJheSA9IGZpbGVFcnJvck1hcC5nZXQoY3VycmVudEZpbGUpO1xuICAgICAgICBpZihlcnJvckFycmF5KSB7XG4gICAgICAgICAgZXJyb3JBcnJheS5wdXNoKGxpbmUudHJpbSgpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVFcnJvck1hcC5zaXplID09PSAwKSB7XG4gICAgICBsb2coJ1VzaW5nIGFsdGVybmF0aXZlIGVycm9yIHBhcnNpbmcgc3RyYXRlZ3knLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgY29uc3Qgc2VjdGlvbnMgPSBlcnJvcnMuc3BsaXQoJ1xcblxcbicpO1xuXG4gICAgICBmb3IoY29uc3Qgc2VjdGlvbiBvZiBzZWN0aW9ucykge1xuICAgICAgICBpZihzZWN0aW9uLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxpbmVzID0gc2VjdGlvbi5zcGxpdCgnXFxuJyk7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gbGluZXNbMF0udHJpbSgpO1xuXG4gICAgICAgIGlmKGZpbGVQYXRoLm1hdGNoKC9cXC4oanN8anN4fHRzfHRzeCkkLykpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGVQYXRoLCBbXSk7XG5cbiAgICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGxpbmVzW2ldLnRyaW0oKSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgZmlsZUVycm9yTWFwLmdldChmaWxlUGF0aCk/LnB1c2gobGluZXNbaV0udHJpbSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihmaWxlRXJyb3JNYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgbG9nKCdVc2luZyBkaXJlY3QgZmlsZSBwYXRoIGV4dHJhY3Rpb24nLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgY29uc3QgZmlsZVBhdGhSZWdleCA9IC8oPzpcXC98W0EtWl06XFxcXCkoPzpbXjpcXG5dK1xcLykqW146XFxuXStcXC4oanN8anN4fHRzfHRzeCkvZztcbiAgICAgIGNvbnN0IGZpbGVQYXRocyA9IGVycm9ycy5tYXRjaChmaWxlUGF0aFJlZ2V4KSB8fCBbXTtcblxuICAgICAgZm9yKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVQYXRocykge1xuICAgICAgICBpZighZmlsZUVycm9yTWFwLmhhcyhmaWxlUGF0aCkgJiYgZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGVQYXRoLCBbXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qga25vd25GaWxlcyA9IFtcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL2NyZWF0ZS9jaGFuZ2Vsb2cudHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL3V0aWxzL2FpU2VydmljZS50cycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShjd2QsICdzcmMvdXRpbHMvYXBwLnRzJyksXG4gICAgICAgIHBhdGhSZXNvbHZlKGN3ZCwgJ3NyYy91dGlscy9yZWFjdFNoaW0udHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL2NvbW1hbmRzL2xpbnQvYXV0b2ZpeC5qcycpXG4gICAgICBdO1xuXG4gICAgICBmb3IoY29uc3QgZmlsZSBvZiBrbm93bkZpbGVzKSB7XG4gICAgICAgIGlmKGV4aXN0c1N5bmMoZmlsZSkgJiYgIWZpbGVFcnJvck1hcC5oYXMoZmlsZSkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGUsIFtdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvcihjb25zdCBmaWxlUGF0aCBvZiBmaWxlRXJyb3JNYXAua2V5cygpKSB7XG4gICAgICBpZighZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgbG9nKGBGaWxlIG5vdCBmb3VuZDogJHtmaWxlUGF0aH1gLCAnd2FybicsIHF1aWV0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGxvZyhgUHJvY2Vzc2luZyBmaWxlOiAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBjb25zdCBpc0N1cnNvcklERSA9IExleENvbmZpZy5jb25maWcuYWk/LnByb3ZpZGVyID09PSAnY3Vyc29yJyB8fCBwcm9jZXNzLmVudi5DVVJTT1JfSURFID09PSAndHJ1ZSc7XG5cbiAgICAgIGlmKGlzQ3Vyc29ySURFKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcHJvbXB0ID0gYEZpeCBhbGwgRVNMaW50IGVycm9ycyBpbiB0aGlzIGZpbGUuIEZvY3VzIG9uOlxuMS4gRml4aW5nIG5hbWluZyBjb252ZW50aW9uc1xuMi4gRml4aW5nIHNvcnQta2V5cyBpc3N1ZXNcbjMuIFJlcGxhY2luZyBjb25zb2xlLmxvZyB3aXRoIGxvZyB1dGlsaXR5XG40LiBGaXhpbmcgbm8tcGx1c3BsdXMgaXNzdWVzXG41LiBGaXhpbmcgdW5uZWNlc3NhcnkgZXNjYXBlIGNoYXJhY3RlcnNcbjYuIEZpeGluZyBvdGhlciBFU0xpbnQgZXJyb3JzXG5cbkNSSVRJQ0FMIFJFUVVJUkVNRU5UUzpcbi0gT05MWSBmaXggdGhlIHNwZWNpZmljIGxpbmVzIHdpdGggRVNMaW50IGVycm9yc1xuLSBETyBOT1QgbW9kaWZ5IGFueSBvdGhlciBsaW5lcyBvZiBjb2RlXG4tIERPIE5PVCByZW1vdmUgbGluZSBicmVha3MgdW5sZXNzIHRoZXkgYXJlIHNwZWNpZmljYWxseSBjYXVzaW5nIEVTTGludCBlcnJvcnNcbi0gRE8gTk9UIGNvbmRlbnNlIG11bHRpLWxpbmUgc3RydWN0dXJlcyB0byBzaW5nbGUgbGluZXNcbi0gUFJFU0VSVkUgYWxsIGV4aXN0aW5nIGxpbmUgYnJlYWtzIGFuZCBmb3JtYXR0aW5nIHRoYXQgaXMgbm90IGNhdXNpbmcgZXJyb3JzXG5cblNQRUNJRklDIEZPUk1BVFRJTkcgUlVMRVM6XG4tIE1haW50YWluIHByb3BlciBpbmRlbnRhdGlvbiAoMiBzcGFjZXMpXG4tIEtlZXAgbGluZSBicmVha3MgYmV0d2VlbiBjbGFzcy9pbnRlcmZhY2UgZGVjbGFyYXRpb24gYW5kIHRoZWlyIG1lbWJlcnNcbi0gS2VlcCBsaW5lIGJyZWFrcyBiZXR3ZWVuIG1ldGhvZHNcbi0gRW5zdXJlIHRoZXJlIGlzIGEgbGluZSBicmVhayBhZnRlciBvcGVuaW5nIGJyYWNlcyBmb3IgY2xhc3NlcywgaW50ZXJmYWNlcywgYW5kIG1ldGhvZHNcbi0gRE8gTk9UIHBsYWNlIGNsYXNzL2ludGVyZmFjZSBwcm9wZXJ0aWVzIG9yIG1ldGhvZHMgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgb3BlbmluZyBicmFjZVxuLSBQcmVzZXJ2ZSBlbXB0eSBsaW5lcyBiZXR3ZWVuIGxvZ2ljYWwgY29kZSBibG9ja3Ncbi0gUFJFU0VSVkUgbXVsdGktbGluZSBpbXBvcnRzIC0gZG8gbm90IGNvbmRlbnNlIHRoZW0gdG8gc2luZ2xlIGxpbmVzXG4tIFBSRVNFUlZFIG11bHRpLWxpbmUgb2JqZWN0L2FycmF5IGRlY2xhcmF0aW9ucyAtIGRvIG5vdCBjb25kZW5zZSB0aGVtIHRvIHNpbmdsZSBsaW5lc1xuXG5TT1JULUtFWVMgUlVMRSAoSElHSEVTVCBQUklPUklUWSk6XG4tIEFsbCBvYmplY3QgbGl0ZXJhbCBrZXlzIE1VU1QgYmUgc29ydGVkIGFscGhhYmV0aWNhbGx5IGluIGFzY2VuZGluZyBvcmRlclxuLSBUaGlzIGFwcGxpZXMgdG8gQUxMIG9iamVjdHMgaW4gdGhlIGZpbGUsIG5vdCBqdXN0IHRob3NlIHdpdGggZXhwbGljaXQgc29ydC1rZXlzIGVycm9yc1xuLSBFeGFtcGxlOiB7YjogMiwgYTogMSwgYzogM30gc2hvdWxkIGJlY29tZSB7YTogMSwgYjogMiwgYzogM31cbi0gUHJlc2VydmUgdGhlIG9yaWdpbmFsIGZvcm1hdHRpbmcgYW5kIGxpbmUgYnJlYWtzIHdoZW4gc29ydGluZ1xuXG5FeGFtcGxlIG9mIENPUlJFQ1QgZm9ybWF0dGluZyAoRE8gTk9UIENIQU5HRSk6XG5leHBvcnQgY2xhc3MgVXNlckNvbnN0YW50cyB7XG4gIHN0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7XG4gIHRoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7XG59XG5cbmltcG9ydCB7XG4gIGFwcCxcbiAgZXZlbnRzLFxuICBpbWFnZXMsXG4gIGxvY2F0aW9ucyxcbiAgbWVzc2FnZXMsXG4gIHBvc3RzLFxuICB0YWdzLFxuICB1c2VycyxcbiAgd2Vic29ja2V0XG59IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge1xuICBhcGlLZXk6ICd2YWx1ZScsXG4gIGJhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gIHRpbWVvdXQ6IDUwMDBcbn07XG5cbkV4YW1wbGUgb2YgSU5DT1JSRUNUIGZvcm1hdHRpbmcgKEZJWCBUSElTKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtzdGF0aWMgcmVhZG9ubHkgQUREX0lURU1fRVJST1I6IHN0cmluZyA9ICdVU0VSX0FERF9JVEVNX0VSUk9SJztcbiAgc3RhdGljIHJlYWRvbmx5IE9USEVSX0NPTlNUQU5UOiBzdHJpbmcgPSAnT1RIRVJfQ09OU1RBTlQnO1xufVxuXG5jb25zdHJ1Y3RvcihmbHV4OiBGbHV4RnJhbWV3b3JrLCBDdXN0b21BZGFwdGVyOiB0eXBlb2YgRXZlbnQgPSBFdmVudCkge3RoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7fVxuXG5pbXBvcnQge2FwcCwgZXZlbnRzLCBpbWFnZXMsIGxvY2F0aW9ucywgbWVzc2FnZXMsIHBvc3RzLCB0YWdzLCB1c2Vycywgd2Vic29ja2V0fSBmcm9tICcuL3N0b3Jlcyc7XG5cbmNvbnN0IGNvbmZpZyA9IHtiYXNlVXJsOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLCBhcGlLZXk6ICd2YWx1ZScsIHRpbWVvdXQ6IDUwMDB9O1xuXG5GaXggT05MWSB0aGUgc3BlY2lmaWMgRVNMaW50IGVycm9ycy4gUmV0dXJuIHRoZSBwcm9wZXJseSBmb3JtYXR0ZWQgY29kZS5gO1xuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHByb21wdEZpbGUgPSBwYXRoUmVzb2x2ZShjd2QsICcuY3Vyc29yX3Byb21wdF90ZW1wLnR4dCcpO1xuICAgICAgICAgICAgd3JpdGVGaWxlU3luYyhwcm9tcHRGaWxlLCBwcm9tcHQsICd1dGY4Jyk7XG5cbiAgICAgICAgICAgIC8vIFVzZSBDdXJzb3IgQ0xJIHRvIGZpeCB0aGUgZmlsZVxuICAgICAgICAgICAgYXdhaXQgZXhlY2EoJ2N1cnNvcicsIFsnZWRpdCcsICctLWZpbGUnLCBmaWxlUGF0aCwgJy0tcHJvbXB0LWZpbGUnLCBwcm9tcHRGaWxlXSwge1xuICAgICAgICAgICAgICBjd2QsXG4gICAgICAgICAgICAgIHJlamVjdDogZmFsc2UsXG4gICAgICAgICAgICAgIHN0ZGlvOiAncGlwZSdcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICB1bmxpbmtTeW5jKHByb21wdEZpbGUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoX2Vycm9yKSB7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxvZyhgQXBwbGllZCBDdXJzb3IgQUkgZml4ZXMgdG8gJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIGNvbnN0IHdhc01vZGlmaWVkID0gYXdhaXQgYXBwbHlEaXJlY3RGaXhlcyhmaWxlUGF0aCwgcXVpZXQpO1xuICAgICAgICAgICAgaWYod2FzTW9kaWZpZWQpIHtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBsb2coYEVycm9yIHVzaW5nIEN1cnNvciBBSTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICBhd2FpdCBhcHBseURpcmVjdEZpeGVzKGZpbGVQYXRoLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHdhc01vZGlmaWVkID0gYXdhaXQgYXBwbHlEaXJlY3RGaXhlcyhmaWxlUGF0aCwgcXVpZXQpO1xuICAgICAgICBpZih3YXNNb2RpZmllZCkge1xuICAgICAgICAgIGxvZyhgQXBwbGllZCBkaXJlY3QgZml4ZXMgdG8gJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZpbGVFcnJvcnMgPSBmaWxlRXJyb3JNYXAuZ2V0KGZpbGVQYXRoKSB8fCBbXTtcbiAgICAgICAgaWYoZmlsZUVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHtjYWxsQUlTZXJ2aWNlfSA9IGF3YWl0IGltcG9ydCgnLi4vLi4vdXRpbHMvYWlTZXJ2aWNlLmpzJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbGVDb250ZW50ID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuXG4gICAgICAgICAgICBjb25zdCBwcm9tcHQgPSBgRml4IHRoZSBmb2xsb3dpbmcgRVNMaW50IGVycm9ycyBpbiB0aGlzIGNvZGU6XG4ke2ZpbGVFcnJvcnMuam9pbignXFxuJyl9XG5cbkhlcmUncyB0aGUgY29kZTpcblxcYFxcYFxcYFxuJHtmaWxlQ29udGVudH1cblxcYFxcYFxcYFxuXG5DUklUSUNBTCBSRVFVSVJFTUVOVFM6XG4tIE9OTFkgZml4IHRoZSBzcGVjaWZpYyBsaW5lcyB3aXRoIEVTTGludCBlcnJvcnNcbi0gRE8gTk9UIG1vZGlmeSBhbnkgb3RoZXIgbGluZXMgb2YgY29kZVxuLSBETyBOT1QgcmVtb3ZlIGxpbmUgYnJlYWtzIHVubGVzcyB0aGV5IGFyZSBzcGVjaWZpY2FsbHkgY2F1c2luZyBFU0xpbnQgZXJyb3JzXG4tIERPIE5PVCBjb25kZW5zZSBtdWx0aS1saW5lIHN0cnVjdHVyZXMgdG8gc2luZ2xlIGxpbmVzXG4tIFBSRVNFUlZFIGFsbCBleGlzdGluZyBsaW5lIGJyZWFrcyBhbmQgZm9ybWF0dGluZyB0aGF0IGlzIG5vdCBjYXVzaW5nIGVycm9yc1xuXG5TUEVDSUZJQyBGT1JNQVRUSU5HIFJVTEVTOlxuLSBNYWludGFpbiBwcm9wZXIgaW5kZW50YXRpb24gKDIgc3BhY2VzKVxuLSBLZWVwIGxpbmUgYnJlYWtzIGJldHdlZW4gY2xhc3MvaW50ZXJmYWNlIGRlY2xhcmF0aW9uIGFuZCB0aGVpciBtZW1iZXJzXG4tIEtlZXAgbGluZSBicmVha3MgYmV0d2VlbiBtZXRob2RzXG4tIEVuc3VyZSB0aGVyZSBpcyBhIGxpbmUgYnJlYWsgYWZ0ZXIgb3BlbmluZyBicmFjZXMgZm9yIGNsYXNzZXMsIGludGVyZmFjZXMsIGFuZCBtZXRob2RzXG4tIERPIE5PVCBwbGFjZSBjbGFzcy9pbnRlcmZhY2UgcHJvcGVydGllcyBvciBtZXRob2RzIG9uIHRoZSBzYW1lIGxpbmUgYXMgdGhlIG9wZW5pbmcgYnJhY2Vcbi0gUHJlc2VydmUgZW1wdHkgbGluZXMgYmV0d2VlbiBsb2dpY2FsIGNvZGUgYmxvY2tzXG4tIFBSRVNFUlZFIG11bHRpLWxpbmUgaW1wb3J0cyAtIGRvIG5vdCBjb25kZW5zZSB0aGVtIHRvIHNpbmdsZSBsaW5lc1xuLSBQUkVTRVJWRSBtdWx0aS1saW5lIG9iamVjdC9hcnJheSBkZWNsYXJhdGlvbnMgLSBkbyBub3QgY29uZGVuc2UgdGhlbSB0byBzaW5nbGUgbGluZXNcblxuU09SVC1LRVlTIFJVTEUgKEhJR0hFU1QgUFJJT1JJVFkpOlxuLSBBbGwgb2JqZWN0IGxpdGVyYWwga2V5cyBNVVNUIGJlIHNvcnRlZCBhbHBoYWJldGljYWxseSBpbiBhc2NlbmRpbmcgb3JkZXJcbi0gVGhpcyBhcHBsaWVzIHRvIEFMTCBvYmplY3RzIGluIHRoZSBmaWxlLCBub3QganVzdCB0aG9zZSB3aXRoIGV4cGxpY2l0IHNvcnQta2V5cyBlcnJvcnNcbi0gRXhhbXBsZToge2I6IDIsIGE6IDEsIGM6IDN9IHNob3VsZCBiZWNvbWUge2E6IDEsIGI6IDIsIGM6IDN9XG4tIFByZXNlcnZlIHRoZSBvcmlnaW5hbCBmb3JtYXR0aW5nIGFuZCBsaW5lIGJyZWFrcyB3aGVuIHNvcnRpbmdcblxuV0hBVCBUTyBGSVg6XG4xLiBTb3J0aW5nIGFsbCBvYmplY3Qga2V5cyBhbHBoYWJldGljYWxseSAoc29ydC1rZXlzIHJ1bGUpIC0gQUxMIG9iamVjdHMgbXVzdCBoYXZlIHNvcnRlZCBrZXlzXG4yLiBGaXhpbmcgbmFtaW5nIGNvbnZlbnRpb25zIC0gT05MWSBmb3IgdmFyaWFibGVzL2Z1bmN0aW9ucyB3aXRoIG5hbWluZyBlcnJvcnNcbjMuIFJlcGxhY2luZyBjb25zb2xlLmxvZyB3aXRoIGxvZyB1dGlsaXR5IC0gT05MWSBmb3IgY29uc29sZS5sb2cgc3RhdGVtZW50c1xuNC4gRml4aW5nIG5vLXBsdXNwbHVzIGlzc3VlcyAtIE9OTFkgZm9yICsrLy0tIG9wZXJhdG9yc1xuNS4gRml4aW5nIHVubmVjZXNzYXJ5IGVzY2FwZSBjaGFyYWN0ZXJzIC0gT05MWSBmb3IgZXNjYXBlZCBjaGFyYWN0ZXJzIHRoYXQgZG9uJ3QgbmVlZCBlc2NhcGluZ1xuNi4gUHJvcGVyIGluZGVudGF0aW9uIGFuZCBzcGFjaW5nIC0gT05MWSB3aGVyZSBzcGVjaWZpY2FsbHkgcmVxdWlyZWQgYnkgZXJyb3JzXG43LiBTdHJpbmcgcXVvdGVzIGNvbnNpc3RlbmN5ICh1c2Ugc2luZ2xlIHF1b3RlcykgLSBPTkxZIGZvciBzdHJpbmcgbGl0ZXJhbHMgd2l0aCBxdW90ZSBlcnJvcnNcbjguIEltcG9ydCBvcmRlciBhbmQgc3BhY2luZyAtIE9OTFkgZm9yIGltcG9ydHMgd2l0aCBvcmRlci9zcGFjaW5nIGVycm9yc1xuOS4gRnVuY3Rpb24gcGFyYW1ldGVyIGZvcm1hdHRpbmcgLSBPTkxZIGZvciBmdW5jdGlvbnMgd2l0aCBwYXJhbWV0ZXIgZXJyb3JzXG4xMC4gVmFyaWFibGUgbmFtaW5nIGNvbnZlbnRpb25zIC0gT05MWSBmb3IgdmFyaWFibGVzIHdpdGggbmFtaW5nIGVycm9yc1xuMTEuIE5vIHVudXNlZCB2YXJpYWJsZXMgb3IgaW1wb3J0cyAtIE9OTFkgZm9yIHVudXNlZCB2YXJpYWJsZXMvaW1wb3J0c1xuMTIuIEF2b2lkaW5nIG5lc3RlZCB0ZXJuYXJpZXMgLSBPTkxZIGZvciBuZXN0ZWQgdGVybmFyeSBleHByZXNzaW9uc1xuMTMuIEFueSBvdGhlciBFU0xpbnQgZXJyb3JzIC0gT05MWSBmb3IgdGhlIHNwZWNpZmljIGVycm9ycyBsaXN0ZWQgYWJvdmVcblxuV0hBVCBOT1QgVE8gRklYOlxuLSBEbyBub3QgY2hhbmdlIHByb3Blcmx5IGZvcm1hdHRlZCBtdWx0aS1saW5lIHN0cnVjdHVyZXNcbi0gRG8gbm90IHJlbW92ZSBsaW5lIGJyZWFrcyB0aGF0IGFyZSBub3QgY2F1c2luZyBlcnJvcnNcbi0gRG8gbm90IGNoYW5nZSBpbmRlbnRhdGlvbiB0aGF0IGlzIGFscmVhZHkgY29ycmVjdFxuLSBEbyBub3QgbW9kaWZ5IHNwYWNpbmcgdGhhdCBpcyBhbHJlYWR5IGNvcnJlY3Rcbi0gRG8gbm90IGNvbmRlbnNlIHJlYWRhYmxlIG11bHRpLWxpbmUgY29kZSB0byBzaW5nbGUgbGluZXNcbi0gRG8gbm90IG1vZGlmeSBjb2RlIHRoYXQgaXMgbm90IG1lbnRpb25lZCBpbiB0aGUgRVNMaW50IGVycm9yc1xuXG5FeGFtcGxlIG9mIENPUlJFQ1QgZm9ybWF0dGluZyAoRE8gTk9UIENIQU5HRSk6XG5leHBvcnQgY2xhc3MgVXNlckNvbnN0YW50cyB7XG4gIHN0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7XG4gIHRoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7XG59XG5cbmltcG9ydCB7XG4gIGFwcCxcbiAgZXZlbnRzLFxuICBpbWFnZXMsXG4gIGxvY2F0aW9ucyxcbiAgbWVzc2FnZXMsXG4gIHBvc3RzLFxuICB0YWdzLFxuICB1c2VycyxcbiAgd2Vic29ja2V0XG59IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge1xuICBhcGlLZXk6ICd2YWx1ZScsXG4gIGJhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gIHRpbWVvdXQ6IDUwMDBcbn07XG5cbkV4YW1wbGUgb2YgSU5DT1JSRUNUIGZvcm1hdHRpbmcgKEZJWCBUSElTKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtzdGF0aWMgcmVhZG9ubHkgQUREX0lURU1fRVJST1I6IHN0cmluZyA9ICdVU0VSX0FERF9JVEVNX0VSUk9SJztcbiAgc3RhdGljIHJlYWRvbmx5IE9USEVSX0NPTlNUQU5UOiBzdHJpbmcgPSAnT1RIRVJfQ09OU1RBTlQnO1xufVxuXG5jb25zdHJ1Y3RvcihmbHV4OiBGbHV4RnJhbWV3b3JrLCBDdXN0b21BZGFwdGVyOiB0eXBlb2YgRXZlbnQgPSBFdmVudCkge3RoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7fVxuXG5pbXBvcnQge2FwcCwgZXZlbnRzLCBpbWFnZXMsIGxvY2F0aW9ucywgbWVzc2FnZXMsIHBvc3RzLCB0YWdzLCB1c2Vycywgd2Vic29ja2V0fSBmcm9tICcuL3N0b3Jlcyc7XG5cbmNvbnN0IGNvbmZpZyA9IHtiYXNlVXJsOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLCBhcGlLZXk6ICd2YWx1ZScsIHRpbWVvdXQ6IDUwMDB9O1xuXG5GaXggT05MWSB0aGUgc3BlY2lmaWMgRVNMaW50IGVycm9ycyBsaXN0ZWQgYWJvdmUuIFJldmlldyB0aGUgZW50aXJlIGZpbGUgZm9yIGNvbXBsaWFuY2Ugd2l0aCBhbGwgRVNMaW50IHJ1bGVzLlxuUmV0dXJuIG9ubHkgdGhlIHByb3Blcmx5IGZvcm1hdHRlZCBmaXhlZCBjb2RlIHdpdGhvdXQgYW55IGV4cGxhbmF0aW9ucy5gO1xuXG4gICAgICAgICAgICBjb25zdCBmaXhlZENvbnRlbnQgPSBhd2FpdCBjYWxsQUlTZXJ2aWNlKHByb21wdCwgcXVpZXQpO1xuXG4gICAgICAgICAgICBpZihmaXhlZENvbnRlbnQgJiYgZml4ZWRDb250ZW50ICE9PSBmaWxlQ29udGVudCkge1xuICAgICAgICAgICAgICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBmaXhlZENvbnRlbnQsICd1dGY4Jyk7XG4gICAgICAgICAgICAgIGxvZyhgQXBwbGllZCBBSSBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBsb2coYEVycm9yIGFwcGx5aW5nIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9OiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHNwaW5uZXIuc3VjY2VlZCgnQUkgZml4ZXMgYXBwbGllZCBzdWNjZXNzZnVsbHkhJyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gYXBwbHkgQUkgZml4ZXMnKTtcbiAgICBsb2coYEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBhcHBseURpcmVjdEZpeGVzID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIGxldCB3YXNNb2RpZmllZCA9IGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG4gICAgbGV0IG5ld0NvbnRlbnQgPSBmaWxlQ29udGVudDtcblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdhaVNlcnZpY2UudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGFpU2VydmljZS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvblxcL2pzb24nLFxccyonQXV0aG9yaXphdGlvbic6IGBCZWFyZXIvZyxcbiAgICAgICAgJ1xcJ0F1dGhvcml6YXRpb25cXCc6IGBCZWFyZXJcXCcsIFxcJ0NvbnRlbnQtVHlwZVxcJzogXFwnYXBwbGljYXRpb24vanNvblxcJydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9oZWFkZXJzOiB7KFtefV0qKX0sXFxzKm1ldGhvZDogJ1BPU1QnL2csXG4gICAgICAgICdtZXRob2Q6IFxcJ1BPU1RcXCcsXFxuICAgICAgaGVhZGVyczogeyQxfSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC97cm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3N5c3RlbVxcJywnXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL3tyb2xlOiAndXNlcicsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3VzZXJcXCcsJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL1xcKChbXildKj8pXyhbYS16QS1aMC05XSspKFxccyo6W14pXSopXFwpL2csXG4gICAgICAgICcoJDEkMiQzKSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL2NvbnNvbGVcXC5sb2dcXCgvZywgJ2xvZygnKTtcblxuICAgICAgaWYoIW5ld0NvbnRlbnQuaW5jbHVkZXMoJ2ltcG9ydCB7bG9nfScpICYmIG5ld0NvbnRlbnQuaW5jbHVkZXMoJ2xvZygnKSkge1xuICAgICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAgIC9pbXBvcnQgeyhbXn1dKil9IGZyb20gJyguKiknOy8sXG4gICAgICAgICAgJ2ltcG9ydCB7JDF9IGZyb20gXFwnJDJcXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdyZWFjdFNoaW0udHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgbmFtaW5nLWNvbnZlbnRpb24gaXNzdWVzIGluIHJlYWN0U2hpbS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAnaW1wb3J0ICogYXMgUmVhY3QgZnJvbScsXG4gICAgICAgICdpbXBvcnQgKiBhcyByZWFjdCBmcm9tJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvUmVhY3RcXC4vZywgJ3JlYWN0LicpO1xuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdjaGFuZ2Vsb2cudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGNoYW5nZWxvZy50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC8oXFx3KylcXCtcXCsvZywgJyQxICs9IDEnKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcJC9nLCAnJCcpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcLi9nLCAnLicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcKi9nLCAnKicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXDovZywgJzonKTtcbiAgICB9XG5cbiAgICBpZihmaWxlUGF0aC5pbmNsdWRlcygnYXBwLnRzJykpIHtcbiAgICAgIGxvZygnRml4aW5nIGlzc3VlcyBpbiBhcHAudHMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvY29uc29sZVxcLmxvZ1xcKC9nLCAnbG9nKCcpO1xuXG4gICAgICBpZighbmV3Q29udGVudC5pbmNsdWRlcygnaW1wb3J0IHtsb2d9JykgJiYgbmV3Q29udGVudC5pbmNsdWRlcygnbG9nKCcpKSB7XG4gICAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgICAgL2ltcG9ydCBib3hlbiBmcm9tICdib3hlbic7LyxcbiAgICAgICAgICAnaW1wb3J0IGJveGVuIGZyb20gXFwnYm94ZW5cXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC9cXFxcXFwvL2csICcvJyk7XG4gICAgfVxuXG4gICAgaWYoZmlsZVBhdGguaW5jbHVkZXMoJ2F1dG9maXguanMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGF1dG9maXguanMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2ltcG9ydCB7KFtefV0qKX0gZnJvbSAncGF0aCc7W1xcc1xcbl0qaW1wb3J0IHsoW159XSopfSBmcm9tICdwYXRoJzsvLFxuICAgICAgICAnaW1wb3J0IHskMSwgJDJ9IGZyb20gXFwncGF0aFxcJzsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvX19maWxlbmFtZS9nLFxuICAgICAgICAnY3VycmVudEZpbGVuYW1lJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9fX2Rpcm5hbWUvZyxcbiAgICAgICAgJ2N1cnJlbnREaXJuYW1lJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnN0IHByZWZpeCA9IHR5cGUgPT09ICdlcnJvcicgXFw/ICdcdTI3NEMgJyA6IHR5cGUgPT09ICdzdWNjZXNzJyBcXD8gJ1x1MjcwNSAnIDogJ1x1MjEzOVx1RkUwRiAnOy8sXG4gICAgICAgICdsZXQgcHJlZml4ID0gXFwnXHUyMTM5XHVGRTBGIFxcJztcXG5pZih0eXBlID09PSBcXCdlcnJvclxcJykge1xcbiAgcHJlZml4ID0gXFwnXHUyNzRDIFxcJztcXG59IGVsc2UgaWYodHlwZSA9PT0gXFwnc3VjY2Vzc1xcJykge1xcbiAgcHJlZml4ID0gXFwnXHUyNzA1IFxcJztcXG59J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIHJ1bkVzbGludEZpeFxcKFxcKS9nLFxuICAgICAgICAnY29uc3QgcnVuRXNsaW50Rml4ID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGdldEZpbGVzV2l0aEVycm9yc1xcKFxcKS9nLFxuICAgICAgICAnY29uc3QgZ2V0RmlsZXNXaXRoRXJyb3JzID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGlzQ3Vyc29yQXZhaWxhYmxlXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBpc0N1cnNvckF2YWlsYWJsZSA9IGFzeW5jICgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCkvZyxcbiAgICAgICAgJ2NvbnN0IGZpeEZpbGVXaXRoQ3Vyc29yQUkgPSBhc3luYyAoZmlsZVBhdGgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBtYWluXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBtYWluID0gYXN5bmMgKCknXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvaW1wb3J0IHtleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmN9L2csXG4gICAgICAgICdpbXBvcnQge3dyaXRlRmlsZVN5bmN9J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnNvbGVcXC5sb2dcXChgXFwke3ByZWZpeH0gXFwke21lc3NhZ2V9YFxcKTsvZyxcbiAgICAgICAgJ3Byb2Nlc3Muc3Rkb3V0LndyaXRlKGAke3ByZWZpeH0gJHttZXNzYWdlfVxcXFxuYCk7J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL30gY2F0Y2hcXChlcnJvclxcKSB7W1xcc1xcbl0qXFwvXFwvIElnbm9yZSBjbGVhbnVwIGVycm9ycy9nLFxuICAgICAgICAnfSBjYXRjaChfKSB7XFxuICAgICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC99IGNhdGNoXFwoZXJyb3JcXCkge1tcXHNcXG5dKmxvZ1xcKC9nLFxuICAgICAgICAnfSBjYXRjaChlcnIpIHtcXG4gICAgbG9nKCdcbiAgICAgICk7XG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvfSBjYXRjaFxcKGVycm9yXFwpIHtbXFxzXFxuXSpyZXR1cm4gZmFsc2U7L2csXG4gICAgICAgICd9IGNhdGNoKF8pIHtcXG4gICAgcmV0dXJuIGZhbHNlOydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9mb3JcXChjb25zdCBmaWxlUGF0aCBvZiBmaWxlc1dpdGhFcnJvcnNcXCkge1tcXHNcXG5dKmNvbnN0IHN1Y2Nlc3MgPSBhd2FpdCBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCk7L2csXG4gICAgICAgICdjb25zdCBmaXhSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoZmlsZXNXaXRoRXJyb3JzLm1hcChmaWxlUGF0aCA9PiBmaXhGaWxlV2l0aEN1cnNvckFJKGZpbGVQYXRoKSkpO1xcbmZvcihjb25zdCBzdWNjZXNzIG9mIGZpeFJlc3VsdHMpIHsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvZml4ZWRDb3VudFxcK1xcKzsvZyxcbiAgICAgICAgJ2ZpeGVkQ291bnQgKz0gMTsnXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmKG5ld0NvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBuZXdDb250ZW50LCAndXRmOCcpO1xuICAgICAgbG9nKGBGaXhlZCBpc3N1ZXMgaW4gJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIHdhc01vZGlmaWVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gd2FzTW9kaWZpZWQ7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nKGBFcnJvciBhcHBseWluZyBkaXJlY3QgZml4ZXMgdG8gJHtmaWxlUGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5jb25zdCBsb2FkQUlDb25maWcgPSBhc3luYyAoY3dkOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuLCBkZWJ1ZzogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IGNvbmZpZ0Zvcm1hdHMgPSBbJ2pzJywgJ21qcycsICdjanMnLCAndHMnLCAnanNvbiddO1xuICBjb25zdCBjb25maWdCYXNlTmFtZSA9ICdsZXguY29uZmlnJztcbiAgbGV0IGxleENvbmZpZ1BhdGggPSAnJztcblxuICBmb3IoY29uc3QgZm9ybWF0IG9mIGNvbmZpZ0Zvcm1hdHMpIHtcbiAgICBjb25zdCBwb3RlbnRpYWxQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBgLi8ke2NvbmZpZ0Jhc2VOYW1lfS4ke2Zvcm1hdH1gKTtcbiAgICBpZihleGlzdHNTeW5jKHBvdGVudGlhbFBhdGgpKSB7XG4gICAgICBsZXhDb25maWdQYXRoID0gcG90ZW50aWFsUGF0aDtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGlmKGxleENvbmZpZ1BhdGgpIHtcbiAgICB0cnkge1xuICAgICAgLy8gRm9yIE1KUyBmaWxlcywgd2UgbmVlZCB0byB1c2UgZHluYW1pYyBpbXBvcnQgd2l0aCBVUkwgZm9yIGNvbXBhdGliaWxpdHlcbiAgICAgIGNvbnN0IGZvcm1hdCA9IGV4dG5hbWUobGV4Q29uZmlnUGF0aCkuc2xpY2UoMSk7XG4gICAgICBsZXQgaW1wb3J0UGF0aCA9IGxleENvbmZpZ1BhdGg7XG5cbiAgICAgIC8vIFVzZSBVUkwgcHJvdG9jb2wgZm9yIEVTTSBpbXBvcnRzXG4gICAgICBpZihmb3JtYXQgPT09ICdtanMnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgdXJsID0gbmV3IFVSTChgZmlsZTovLyR7bGV4Q29uZmlnUGF0aH1gKTtcbiAgICAgICAgICBpbXBvcnRQYXRoID0gdXJsLmhyZWY7XG4gICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgIGxvZyhgVXNpbmcgVVJMIGZvcm1hdCBmb3IgTUpTIGltcG9ydDogJHtpbXBvcnRQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAodXJsRXJyb3IpIHtcbiAgICAgICAgICBsb2coYEVycm9yIGNyZWF0aW5nIFVSTCBmb3IgTUpTIGltcG9ydDogJHt1cmxFcnJvci5tZXNzYWdlfWAsICd3YXJuJywgZGVidWcgfHwgIXF1aWV0KTtcbiAgICAgICAgICBpbXBvcnRQYXRoID0gYGZpbGU6Ly8ke2xleENvbmZpZ1BhdGh9YDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYFRyeWluZyB0byBpbXBvcnQgY29uZmlnIGZyb20gJHtpbXBvcnRQYXRofSAoZm9ybWF0OiAke2Zvcm1hdH0pYCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBsZXhDb25maWc7XG4gICAgICB0cnkge1xuICAgICAgICBsZXhDb25maWcgPSBhd2FpdCBpbXBvcnQoaW1wb3J0UGF0aCk7XG4gICAgICB9IGNhdGNoIChpbXBvcnRFcnJvcikge1xuICAgICAgICBpZihpbXBvcnRFcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdub3QgZGVmaW5lZCBpbiBFUyBtb2R1bGUgc2NvcGUnKSkge1xuICAgICAgICAgIGxvZyhgRVMgTW9kdWxlIHN5bnRheCBlcnJvciBpbiAke2xleENvbmZpZ1BhdGh9LiBNYWtlIHN1cmUgeW91J3JlIHVzaW5nICdleHBvcnQnIGluc3RlYWQgb2YgJ21vZHVsZS5leHBvcnRzJy5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoaW1wb3J0RXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgaW1wb3J0RXJyb3I7XG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBib3RoIEVTTSAoZGVmYXVsdCBleHBvcnQpIGFuZCBDb21tb25KUyAobW9kdWxlLmV4cG9ydHMpXG4gICAgICBsZXQgY29uZmlnRGF0YSA9IG51bGw7XG4gICAgICBpZihsZXhDb25maWcuZGVmYXVsdCkge1xuICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnLmRlZmF1bHQ7XG4gICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgbG9nKGBGb3VuZCBkZWZhdWx0IGV4cG9ydCBpbiAke2xleENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZvciBDb21tb25KUyBvciBvdGhlciBtb2R1bGUgc3lzdGVtc1xuICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnO1xuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgVXNpbmcgZGlyZWN0IGV4cG9ydCBpbiAke2xleENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoY29uZmlnRGF0YSAmJiBjb25maWdEYXRhLmFpKSB7XG4gICAgICAgIGxvZyhgRm91bmQgQUkgY29uZmlndXJhdGlvbiBpbiAke3BhdGhSZXNvbHZlKGN3ZCwgbGV4Q29uZmlnUGF0aCl9LCBhcHBseWluZyBzZXR0aW5ncy4uLmAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBMZXhDb25maWcuY29uZmlnLmFpID0gey4uLkxleENvbmZpZy5jb25maWcuYWksIC4uLmNvbmZpZ0RhdGEuYWl9O1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2coYEVycm9yIGxvYWRpbmcgQUkgY29uZmlndXJhdGlvbiBmcm9tICR7bGV4Q29uZmlnUGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnd2FybicsIHF1aWV0KTtcbiAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBMb2FkIEVTTGludCBjb25maWd1cmF0aW9uIGZyb20gbGV4LmNvbmZpZy4qIGZpbGVzXG4gKi9cbmNvbnN0IGxvYWRFU0xpbnRDb25maWcgPSBhc3luYyAoY3dkOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuLCBkZWJ1ZzogYm9vbGVhbik6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAvLyBDaGVjayBpZiBMZXhDb25maWcgYWxyZWFkeSBoYXMgRVNMaW50IGNvbmZpZ3VyYXRpb24gbG9hZGVkXG4gIGlmKExleENvbmZpZy5jb25maWcuZXNsaW50ICYmIE9iamVjdC5rZXlzKExleENvbmZpZy5jb25maWcuZXNsaW50KS5sZW5ndGggPiAwKSB7XG4gICAgbG9nKCdGb3VuZCBFU0xpbnQgY29uZmlndXJhdGlvbiBpbiBsZXguY29uZmlnLiogZmlsZScsICdpbmZvJywgZGVidWcgfHwgIXF1aWV0KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIFRyeSB0byBsb2FkIGZyb20gbGV4LmNvbmZpZy4qIGZpbGVzIGlmIG5vdCBhbHJlYWR5IGxvYWRlZFxuICBjb25zdCBjb25maWdGb3JtYXRzID0gWydqcycsICdtanMnLCAnY2pzJywgJ3RzJywgJ2pzb24nXTtcbiAgY29uc3QgY29uZmlnQmFzZU5hbWUgPSAnbGV4LmNvbmZpZyc7XG5cbiAgZm9yKGNvbnN0IGZvcm1hdCBvZiBjb25maWdGb3JtYXRzKSB7XG4gICAgY29uc3QgcG90ZW50aWFsUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgYC4vJHtjb25maWdCYXNlTmFtZX0uJHtmb3JtYXR9YCk7XG4gICAgaWYoZXhpc3RzU3luYyhwb3RlbnRpYWxQYXRoKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRm9yIE1KUyBmaWxlcywgd2UgbmVlZCB0byB1c2UgZHluYW1pYyBpbXBvcnQgd2l0aCBVUkwgZm9yIGNvbXBhdGliaWxpdHlcbiAgICAgICAgY29uc3QgZmlsZUZvcm1hdCA9IGV4dG5hbWUocG90ZW50aWFsUGF0aCkuc2xpY2UoMSk7XG4gICAgICAgIGxldCBpbXBvcnRQYXRoID0gcG90ZW50aWFsUGF0aDtcblxuICAgICAgICAvLyBVc2UgVVJMIHByb3RvY29sIGZvciBFU00gaW1wb3J0c1xuICAgICAgICBpZihmaWxlRm9ybWF0ID09PSAnbWpzJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGBmaWxlOi8vJHtwb3RlbnRpYWxQYXRofWApO1xuICAgICAgICAgICAgaW1wb3J0UGF0aCA9IHVybC5ocmVmO1xuICAgICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgICAgbG9nKGBVc2luZyBVUkwgZm9ybWF0IGZvciBNSlMgaW1wb3J0OiAke2ltcG9ydFBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAodXJsRXJyb3IpIHtcbiAgICAgICAgICAgIGxvZyhgRXJyb3IgY3JlYXRpbmcgVVJMIGZvciBNSlMgaW1wb3J0OiAke3VybEVycm9yLm1lc3NhZ2V9YCwgJ3dhcm4nLCBkZWJ1ZyB8fCAhcXVpZXQpO1xuICAgICAgICAgICAgaW1wb3J0UGF0aCA9IGBmaWxlOi8vJHtwb3RlbnRpYWxQYXRofWA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICBsb2coYFRyeWluZyB0byBpbXBvcnQgY29uZmlnIGZyb20gJHtpbXBvcnRQYXRofSAoZm9ybWF0OiAke2ZpbGVGb3JtYXR9KWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxleENvbmZpZztcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXhDb25maWcgPSBhd2FpdCBpbXBvcnQoaW1wb3J0UGF0aCk7XG4gICAgICAgIH0gY2F0Y2ggKGltcG9ydEVycm9yKSB7XG4gICAgICAgICAgaWYoaW1wb3J0RXJyb3IubWVzc2FnZS5pbmNsdWRlcygnbm90IGRlZmluZWQgaW4gRVMgbW9kdWxlIHNjb3BlJykpIHtcbiAgICAgICAgICAgIGxvZyhgRVMgTW9kdWxlIHN5bnRheCBlcnJvciBpbiAke3BvdGVudGlhbFBhdGh9LiBNYWtlIHN1cmUgeW91J3JlIHVzaW5nICdleHBvcnQnIGluc3RlYWQgb2YgJ21vZHVsZS5leHBvcnRzJy5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGltcG9ydEVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBpbXBvcnRFcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBib3RoIEVTTSAoZGVmYXVsdCBleHBvcnQpIGFuZCBDb21tb25KUyAobW9kdWxlLmV4cG9ydHMpXG4gICAgICAgIGxldCBjb25maWdEYXRhID0gbnVsbDtcbiAgICAgICAgaWYobGV4Q29uZmlnLmRlZmF1bHQpIHtcbiAgICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnLmRlZmF1bHQ7XG4gICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgIGxvZyhgRm91bmQgZGVmYXVsdCBleHBvcnQgaW4gJHtwb3RlbnRpYWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBGb3IgQ29tbW9uSlMgb3Igb3RoZXIgbW9kdWxlIHN5c3RlbXNcbiAgICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnO1xuICAgICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgICBsb2coYFVzaW5nIGRpcmVjdCBleHBvcnQgaW4gJHtwb3RlbnRpYWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNvbmZpZ0RhdGEgJiYgY29uZmlnRGF0YS5lc2xpbnQgJiYgT2JqZWN0LmtleXMoY29uZmlnRGF0YS5lc2xpbnQpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBsb2coYEZvdW5kIEVTTGludCBjb25maWd1cmF0aW9uIGluICR7cGF0aFJlc29sdmUoY3dkLCBwb3RlbnRpYWxQYXRoKX0sIGFwcGx5aW5nIHNldHRpbmdzLi4uYCwgJ2luZm8nLCBkZWJ1ZyB8fCAhcXVpZXQpO1xuICAgICAgICAgIExleENvbmZpZy5jb25maWcuZXNsaW50ID0gey4uLkxleENvbmZpZy5jb25maWcuZXNsaW50LCAuLi5jb25maWdEYXRhLmVzbGludH07XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGxvZyhgRXJyb3IgbG9hZGluZyBFU0xpbnQgY29uZmlndXJhdGlvbiBmcm9tICR7cG90ZW50aWFsUGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnd2FybicsIHF1aWV0KTtcbiAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbmNvbnN0IHJlbW92ZUZpbGVDb21tZW50cyA9IChmaWxlUGF0aDogc3RyaW5nLCBxdWlldDogYm9vbGVhbik6IGJvb2xlYW4gPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IGZpbGVDb250ZW50ID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuXG4gICAgaWYoZmlsZUNvbnRlbnQubGVuZ3RoID4gMTAwMDAwMCkgeyAvLyAxTUIgbGltaXRcbiAgICAgIGxvZyhgU2tpcHBpbmcgY29tbWVudCByZW1vdmFsIGZvciBsYXJnZSBmaWxlOiAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBVc2UgcmVnZXggdG8gbWF0Y2ggZGlmZmVyZW50IHR5cGVzIG9mIGNvbW1lbnRzXG4gICAgLy8gUHJlc2VydmVzOlxuICAgIC8vIDEuIENvcHlyaWdodCBub3RpY2VzICgvKiBDb3B5cmlnaHQgLi4uICovKVxuICAgIC8vIDIuIFRPRE8gY29tbWVudHMgKC8vIFRPRE86IC4uLilcbiAgICAvLyAzLiBMaWNlbnNlIGhlYWRlcnMgKC8qIC4uLiBMaWNlbnNlIC4uLiAqLylcblxuICAgIC8vIEhhbmRsZSBtdWx0aS1saW5lIGNvbW1lbnRzIGZpcnN0IC0gcHJlc2VydmUgY29weXJpZ2h0L2xpY2Vuc2Ugbm90aWNlc1xuICAgIGxldCBuZXdDb250ZW50ID0gZmlsZUNvbnRlbnQucmVwbGFjZShcbiAgICAgIC9cXC9cXCpbXFxzXFxTXSo/XFwqXFwvL2csXG4gICAgICAobWF0Y2gpID0+IHtcbiAgICAgICAgaWYobWF0Y2guaW5jbHVkZXMoJ0NvcHlyaWdodCcpIHx8XG4gICAgICAgICAgbWF0Y2guaW5jbHVkZXMoJ0xJQ0VOU0UnKSB8fFxuICAgICAgICAgIG1hdGNoLmluY2x1ZGVzKCdMaWNlbnNlJykgfHxcbiAgICAgICAgICBtYXRjaC5pbmNsdWRlcygnbGljZW5zZScpKSB7XG4gICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gSGFuZGxlIHNpbmdsZS1saW5lIGNvbW1lbnRzIC0gcHJlc2VydmUgVE9ET3NcbiAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgL1xcL1xcLy4qJC9nbSxcbiAgICAgIChtYXRjaCkgPT4ge1xuICAgICAgICBpZihtYXRjaC5pbmNsdWRlcygnVE9ETycpIHx8IG1hdGNoLmluY2x1ZGVzKCdGSVhNRScpKSB7XG4gICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gQ2xlYW4gdXAgYW55IG11bHRpcGxlIGJsYW5rIGxpbmVzIGNyZWF0ZWQgYnkgY29tbWVudCByZW1vdmFsXG4gICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxuXFxzKlxcblxccypcXG4vZywgJ1xcblxcbicpO1xuXG4gICAgLy8gSWYgdGhlIGZpbGUgd2FzIG1vZGlmaWVkLCBzYXZlIGl0XG4gICAgaWYobmV3Q29udGVudCAhPT0gZmlsZUNvbnRlbnQpIHtcbiAgICAgIHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIG5ld0NvbnRlbnQsICd1dGY4Jyk7XG4gICAgICBsb2coYFJlbW92ZWQgY29tbWVudHMgZnJvbSAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZyhgRXJyb3IgcmVtb3ZpbmcgY29tbWVudHMgZnJvbSAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBsaW50ID0gYXN5bmMgKGNtZDogTGludE9wdGlvbnMgJiB7J3JlbW92ZS1jb21tZW50cyc/OiBib29sZWFufSwgY2FsbGJhY2s6IExpbnRDYWxsYmFjayA9IHByb2Nlc3MuZXhpdCk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIGNvbnN0IHtcbiAgICBjbGlOYW1lID0gJ0xleCcsXG4gICAgZml4ID0gZmFsc2UsXG4gICAgZGVidWcgPSBmYWxzZSxcbiAgICBxdWlldCA9IGZhbHNlLFxuICAgIGNvbmZpZyA9IG51bGwsXG4gICAgcmVtb3ZlQ29tbWVudHMgPSBmYWxzZSxcbiAgICAncmVtb3ZlLWNvbW1lbnRzJzogcmVtb3ZlQ29tbWVudHNGbGFnID0gZmFsc2VcbiAgfSA9IGNtZDtcblxuICBjb25zdCBzaG91bGRSZW1vdmVDb21tZW50cyA9IHJlbW92ZUNvbW1lbnRzIHx8IHJlbW92ZUNvbW1lbnRzRmxhZztcblxuICBsb2coYCR7Y2xpTmFtZX0gbGludGluZy4uLmAsICdpbmZvJywgcXVpZXQpO1xuXG4gIGNvbnN0IGN3ZCA9IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IHNwaW5uZXIgPSBjcmVhdGVTcGlubmVyKHF1aWV0KTtcblxuICBhd2FpdCBsb2FkQUlDb25maWcoY3dkLCBxdWlldCwgZGVidWcpO1xuXG4gIGxldCB0ZW1wQ29uZmlnUGF0aDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCB1c2VUeXBlc2NyaXB0ID0gZGV0ZWN0VHlwZVNjcmlwdChjd2QpO1xuICAgIGxvZyhgVHlwZVNjcmlwdCAke3VzZVR5cGVzY3JpcHQgPyAnZGV0ZWN0ZWQnIDogJ25vdCBkZXRlY3RlZCd9IGZyb20gdHNjb25maWcuanNvbmAsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgICAgTGV4Q29uZmlnLmNoZWNrTGludFR5cGVzY3JpcHRDb25maWcoKTtcbiAgICB9XG5cbiAgICBlbnN1cmVNb2R1bGVUeXBlKGN3ZCk7XG5cbiAgICBhd2FpdCBpbnN0YWxsRGVwZW5kZW5jaWVzKGN3ZCwgdXNlVHlwZXNjcmlwdCwgcXVpZXQpO1xuXG4gICAgY29uc3QgcHJvamVjdENvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLm1qcycpO1xuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoVHMgPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLnRzJyk7XG4gICAgY29uc3QgaGFzRXNsaW50Q29uZmlnID0gZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnUGF0aCkgfHxcbiAgICAgIGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGhUcykgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy5qc29uJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy55bWwnKSkgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLnlhbWwnKSkgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjJykpO1xuXG4gICAgY29uc3QgaGFzTGV4RXNsaW50Q29uZmlnID0gYXdhaXQgbG9hZEVTTGludENvbmZpZyhjd2QsIHF1aWV0LCBkZWJ1Zyk7XG5cbiAgICBpZihoYXNMZXhFc2xpbnRDb25maWcpIHtcbiAgICAgIGxvZygnVXNpbmcgRVNMaW50IGNvbmZpZ3VyYXRpb24gZnJvbSBsZXguY29uZmlnLiogZmlsZScsICdpbmZvJywgcXVpZXQpO1xuICAgIH1cblxuICAgIGlmKGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzb24nKSkpIHtcbiAgICAgIHVubGlua1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzb24nKSk7XG4gICAgfVxuXG4gICAgbGV0IGxleENvbmZpZ1BhdGggPSAnJztcbiAgICBsZXQgc2hvdWxkQ3JlYXRlVGVtcENvbmZpZyA9IGZhbHNlO1xuXG4gICAgaWYoIWhhc0VzbGludENvbmZpZyAmJiAhaGFzTGV4RXNsaW50Q29uZmlnKSB7XG4gICAgICBjb25zdCBwb3NzaWJsZVBhdGhzID0gW1xuICAgICAgICBwYXRoUmVzb2x2ZShjdXJyZW50RGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcudHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3VycmVudERpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLmptcycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmVudi5MRVhfSE9NRSB8fCAnLi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLnRzJyksXG4gICAgICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuZW52LkxFWF9IT01FIHx8ICcuL25vZGVfbW9kdWxlcy9AbmxhYnMvbGV4JywgJ2VzbGludC5jb25maWcubWpzJylcbiAgICAgIF07XG5cbiAgICAgIGZvcihjb25zdCBwYXRoIG9mIHBvc3NpYmxlUGF0aHMpIHtcbiAgICAgICAgaWYoZXhpc3RzU3luYyhwYXRoKSkge1xuICAgICAgICAgIGxleENvbmZpZ1BhdGggPSBwYXRoO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgIGxvZyhgQ3VycmVudCBkaXJlY3Rvcnk6ICR7Y3VycmVudERpcm5hbWV9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGxvZyhgUHJvamVjdCBjb25maWcgcGF0aDogJHtwcm9qZWN0Q29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBQcm9qZWN0IGNvbmZpZyBleGlzdHM6ICR7aGFzRXNsaW50Q29uZmlnfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBsb2coYEZvdW5kIExleCBjb25maWc6ICR7bGV4Q29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBMZXggY29uZmlnIGV4aXN0czogJHshIWxleENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyhsZXhDb25maWdQYXRoKX1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIH1cblxuICAgICAgaWYobGV4Q29uZmlnUGF0aCAmJiBleGlzdHNTeW5jKGxleENvbmZpZ1BhdGgpKSB7XG4gICAgICAgIGxvZygnTm8gRVNMaW50IGNvbmZpZ3VyYXRpb24gZm91bmQgaW4gcHJvamVjdC4gVXNpbmcgTGV4XFwncyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaG91bGRDcmVhdGVUZW1wQ29uZmlnID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihjb25maWcpIHtcbiAgICAgIGNvbnN0IHVzZXJDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBjb25maWcpO1xuICAgICAgaWYoZXhpc3RzU3luYyh1c2VyQ29uZmlnUGF0aCkpIHtcbiAgICAgICAgbG9nKGBVc2luZyBzcGVjaWZpZWQgRVNMaW50IGNvbmZpZ3VyYXRpb246ICR7Y29uZmlnfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBzaG91bGRDcmVhdGVUZW1wQ29uZmlnID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2coYFNwZWNpZmllZCBFU0xpbnQgY29uZmlndXJhdGlvbiBub3QgZm91bmQ6ICR7Y29uZmlnfS4gVXNpbmcgTGV4J3MgZGVmYXVsdCBjb25maWd1cmF0aW9uLmAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKHNob3VsZENyZWF0ZVRlbXBDb25maWcpIHtcbiAgICAgIGxvZygnTm8gRVNMaW50IGNvbmZpZ3VyYXRpb24gZm91bmQuIENyZWF0aW5nIGEgdGVtcG9yYXJ5IGNvbmZpZ3VyYXRpb24uLi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIGNvbnN0IGNvbmZpZ1Jlc3VsdCA9IGNyZWF0ZURlZmF1bHRFU0xpbnRDb25maWcodXNlVHlwZXNjcmlwdCwgY3dkKTtcbiAgICAgIHRlbXBDb25maWdQYXRoID0gY29uZmlnUmVzdWx0LmNvbmZpZ1BhdGg7XG4gICAgfVxuXG4gICAgbGV0IGVzbGludE91dHB1dCA9ICcnO1xuICAgIGNvbnN0IGNhcHR1cmVPdXRwdXQgPSAob3V0cHV0OiBzdHJpbmcpID0+IHtcbiAgICAgIGVzbGludE91dHB1dCArPSBgJHtvdXRwdXR9XFxuYDtcbiAgICB9O1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuRXNsaW50V2l0aExleChjd2QsIHF1aWV0LCBjbGlOYW1lLCB0cnVlLCBkZWJ1ZywgdXNlVHlwZXNjcmlwdCwgY2FwdHVyZU91dHB1dCk7XG5cbiAgICBpZihzaG91bGRSZW1vdmVDb21tZW50cykge1xuICAgICAgc3Bpbm5lci5zdGFydCgnUmVtb3ZpbmcgY29tbWVudHMgZnJvbSBmaWxlcy4uLicpO1xuXG4gICAgICBjb25zdCBnbG9iID0gYXdhaXQgaW1wb3J0KCdnbG9iJyk7XG4gICAgICBjb25zdCBmaWxlcyA9IGdsb2Iuc3luYygne3NyYyxsaWJ9LyoqLyoue2pzLGpzeCx0cyx0c3h9Jywge1xuICAgICAgICBjd2QsXG4gICAgICAgIGlnbm9yZTogWycqKi9ub2RlX21vZHVsZXMvKionLCAnKiovbGliLyoqJywgJyoqL2Rpc3QvKionLCAnKiovYnVpbGQvKionXVxuICAgICAgfSk7XG5cbiAgICAgIGxldCBwcm9jZXNzZWRDb3VudCA9IDA7XG4gICAgICBmb3IoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgZmlsZSk7XG4gICAgICAgIGlmKHJlbW92ZUZpbGVDb21tZW50cyhmaWxlUGF0aCwgcXVpZXQpKSB7XG4gICAgICAgICAgcHJvY2Vzc2VkQ291bnQrKztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBzcGlubmVyLnN1Y2NlZWQoYFJlbW92ZWQgY29tbWVudHMgZnJvbSAke3Byb2Nlc3NlZENvdW50fSBmaWxlc2ApO1xuICAgIH1cblxuICAgIGlmKHJlc3VsdCAhPT0gMCAmJiBmaXgpIHtcbiAgICAgIGNvbnN0IGFpQ29uZmlndXJlZCA9IExleENvbmZpZy5jb25maWcuYWk/LnByb3ZpZGVyICYmIExleENvbmZpZy5jb25maWcuYWkucHJvdmlkZXIgIT09ICdub25lJztcblxuICAgICAgaWYoYWlDb25maWd1cmVkKSB7XG4gICAgICAgIGxvZygnQXBwbHlpbmcgQUkgZml4ZXMgdG8gcmVtYWluaW5nIGlzc3Vlcy4uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBhd2FpdCBhcHBseUFJRml4KGN3ZCwgZXNsaW50T3V0cHV0LCBxdWlldCk7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJGaXhSZXN1bHQgPSBhd2FpdCBydW5Fc2xpbnRXaXRoTGV4KGN3ZCwgcXVpZXQsIGNsaU5hbWUsIGZhbHNlLCBkZWJ1ZywgdXNlVHlwZXNjcmlwdCk7XG5cbiAgICAgICAgY2FsbGJhY2soYWZ0ZXJGaXhSZXN1bHQpO1xuICAgICAgICByZXR1cm4gYWZ0ZXJGaXhSZXN1bHQ7XG4gICAgICB9XG4gICAgICBsb2coJ0VTTGludCBjb3VsZCBub3QgZml4IGFsbCBpc3N1ZXMgYXV0b21hdGljYWxseS4nLCAnd2FybicsIHF1aWV0KTtcbiAgICAgIGxvZygnVG8gZW5hYmxlIEFJLXBvd2VyZWQgZml4ZXMsIGFkZCBBSSBjb25maWd1cmF0aW9uIHRvIHlvdXIgbGV4LmNvbmZpZyBmaWxlOicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgbG9nKGBcbi8vIEluIGxleC5jb25maWcuanMgKG9yIGxleC5jb25maWcubWpzLCBsZXguY29uZmlnLmNqcywgZXRjLilcbmV4cG9ydCBkZWZhdWx0IHtcbiAgLy8gWW91ciBleGlzdGluZyBjb25maWdcbiAgYWk6IHtcbiAgICBwcm92aWRlcjogJ2N1cnNvcicgLy8gb3IgJ29wZW5haScsICdhbnRocm9waWMnLCBldGMuXG4gICAgLy8gQWRkaXRpb25hbCBwcm92aWRlci1zcGVjaWZpYyBzZXR0aW5nc1xuICB9XG59O2AsICdpbmZvJywgcXVpZXQpO1xuICAgIH1cblxuICAgIGNhbGxiYWNrKHJlc3VsdCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgaWYoc3Bpbm5lcikge1xuICAgICAgc3Bpbm5lci5mYWlsKCdMaW50aW5nIGZhaWxlZCEnKTtcbiAgICB9XG4gICAgY2FsbGJhY2soMSk7XG4gICAgcmV0dXJuIDE7XG4gIH0gZmluYWxseSB7XG4gICAgY29uc3QgdGVtcEZpbGVQYXRocyA9IFtcbiAgICAgIHRlbXBDb25maWdQYXRoLFxuICAgICAgcGF0aFJlc29sdmUoY3dkLCAnLmxleC10ZW1wLWVzbGludC5janMnKSxcbiAgICAgIHBhdGhSZXNvbHZlKGN3ZCwgJy5sZXgtdGVtcC1kZWZhdWx0LWVzbGludC5janMnKVxuICAgIF07XG5cbiAgICBmb3IoY29uc3QgZmlsZVBhdGggb2YgdGVtcEZpbGVQYXRocykge1xuICAgICAgaWYoZmlsZVBhdGggJiYgZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB1bmxpbmtTeW5jKGZpbGVQYXRoKTtcbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgbG9nKGBDbGVhbmVkIHVwIHRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGF0ICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufTsiXSwKICAibWFwcGluZ3MiOiAiQUFJQSxTQUFRLGFBQVk7QUFDcEIsU0FBUSxZQUFZLGNBQWMsWUFBWSxxQkFBb0I7QUFDbEUsU0FBUSxTQUFTLFdBQVcsYUFBYSxl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Q0EsUUFBUSxDQUFDLHNCQUFzQixhQUFhLGNBQWMsYUFBYTtBQUFBLE1BQ3pFLENBQUM7QUFFRCxVQUFJLGlCQUFpQjtBQUNyQixpQkFBVSxRQUFRLE9BQU87QUFDdkIsY0FBTSxXQUFXLFlBQVksS0FBSyxJQUFJO0FBQ3RDLFlBQUcsbUJBQW1CLFVBQVUsS0FBSyxHQUFHO0FBQ3RDO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFFQSxjQUFRLFFBQVEseUJBQXlCLGNBQWMsUUFBUTtBQUFBLElBQ2pFO0FBRUEsUUFBRyxXQUFXLEtBQUssS0FBSztBQUN0QixZQUFNLGVBQWUsVUFBVSxPQUFPLElBQUksWUFBWSxVQUFVLE9BQU8sR0FBRyxhQUFhO0FBRXZGLFVBQUcsY0FBYztBQUNmLFlBQUksNENBQTRDLFFBQVEsS0FBSztBQUM3RCxjQUFNLFdBQVcsS0FBSyxjQUFjLEtBQUs7QUFFekMsY0FBTSxpQkFBaUIsTUFBTSxpQkFBaUIsS0FBSyxPQUFPLFNBQVMsT0FBTyxPQUFPLGFBQWE7QUFFOUYsaUJBQVMsY0FBYztBQUN2QixlQUFPO0FBQUEsTUFDVDtBQUNBLFVBQUksa0RBQWtELFFBQVEsS0FBSztBQUNuRSxVQUFJLDZFQUE2RSxRQUFRLEtBQUs7QUFDOUYsVUFBSTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FRTCxRQUFRLEtBQUs7QUFBQSxJQUNkO0FBRUEsYUFBUyxNQUFNO0FBQ2YsV0FBTztBQUFBLEVBQ1QsU0FBUyxPQUFPO0FBQ2QsUUFBSTtBQUFBLEVBQUssT0FBTyxXQUFXLE1BQU0sT0FBTyxJQUFJLFNBQVMsS0FBSztBQUMxRCxRQUFHLFNBQVM7QUFDVixjQUFRLEtBQUssaUJBQWlCO0FBQUEsSUFDaEM7QUFDQSxhQUFTLENBQUM7QUFDVixXQUFPO0FBQUEsRUFDVCxVQUFFO0FBQ0EsVUFBTSxnQkFBZ0I7QUFBQSxNQUNwQjtBQUFBLE1BQ0EsWUFBWSxLQUFLLHNCQUFzQjtBQUFBLE1BQ3ZDLFlBQVksS0FBSyw4QkFBOEI7QUFBQSxJQUNqRDtBQUVBLGVBQVUsWUFBWSxlQUFlO0FBQ25DLFVBQUcsWUFBWSxXQUFXLFFBQVEsR0FBRztBQUNuQyxZQUFJO0FBQ0YscUJBQVcsUUFBUTtBQUNuQixjQUFHLE9BQU87QUFDUixnQkFBSSx5Q0FBeUMsUUFBUSxJQUFJLFFBQVEsS0FBSztBQUFBLFVBQ3hFO0FBQUEsUUFDRixRQUFRO0FBQUEsUUFDUjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGOyIsCiAgIm5hbWVzIjogWyJsaW5lcyJdCn0K
|
|
954
|
+
|
|
955
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9saW50L2xpbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjItUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhlY2F9IGZyb20gJ2V4ZWNhJztcbmltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB1bmxpbmtTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmUsIGV4dG5hbWV9IGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7cmVzb2x2ZUJpbmFyeVBhdGh9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcyc7XG5cbmxldCBjdXJyZW50RmlsZW5hbWU6IHN0cmluZztcbmxldCBjdXJyZW50RGlybmFtZTogc3RyaW5nO1xuXG50cnkge1xuICBjdXJyZW50RmlsZW5hbWUgPSBldmFsKCdyZXF1aXJlKFwidXJsXCIpLmZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKScpO1xuICBjdXJyZW50RGlybmFtZSA9IGRpcm5hbWUoY3VycmVudEZpbGVuYW1lKTtcbn0gY2F0Y2h7XG4gIGN1cnJlbnRGaWxlbmFtZSA9IHByb2Nlc3MuY3dkKCk7XG4gIGN1cnJlbnREaXJuYW1lID0gcHJvY2Vzcy5jd2QoKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMaW50T3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNhY2hlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY2FjaGVGaWxlPzogc3RyaW5nO1xuICByZWFkb25seSBjYWNoZUxvY2F0aW9uPzogc3RyaW5nO1xuICByZWFkb25seSBjbGlOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBjb2xvcj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgZGVidWc/OiBib29sZWFuO1xuICByZWFkb25seSBlbnY/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGVudkluZm8/OiBib29sZWFuO1xuICByZWFkb25seSBleHQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZpeD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZpeERyeVJ1bj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZpeFR5cGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZvcm1hdD86IHN0cmluZztcbiAgcmVhZG9ubHkgZ2xvYmFsPzogc3RyaW5nO1xuICByZWFkb25seSBpZ25vcmVQYXRoPzogc3RyaW5nO1xuICByZWFkb25seSBpZ25vcmVQYXR0ZXJuPzogc3RyaW5nO1xuICByZWFkb25seSBpbml0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbWF4V2FybmluZ3M/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5vQ29sb3I/OiBib29sZWFuO1xuICByZWFkb25seSBub0VzbGludHJjPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9JZ25vcmU/OiBib29sZWFuO1xuICByZWFkb25seSBub0lubGluZUNvbmZpZz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG91dHB1dEZpbGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnNlcj86IHN0cmluZztcbiAgcmVhZG9ubHkgcGFyc2VyT3B0aW9ucz86IHN0cmluZztcbiAgcmVhZG9ubHkgcGx1Z2luPzogc3RyaW5nO1xuICByZWFkb25seSBwcmludENvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xuICByZWFkb25seSByZW1vdmVDb21tZW50cz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJlcG9ydFVudXNlZERpc2FibGVEaXJlY3RpdmVzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgcmVzb2x2ZVBsdWdpbnNSZWxhdGl2ZVRvPzogc3RyaW5nO1xuICByZWFkb25seSBydWxlPzogc3RyaW5nO1xuICByZWFkb25seSBydWxlc2Rpcj86IHN0cmluZztcbiAgcmVhZG9ubHkgc3RkaW4/OiBib29sZWFuO1xuICByZWFkb25seSBzdGRpbkZpbGVuYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBMaW50Q2FsbGJhY2sgPSB0eXBlb2YgcHJvY2Vzcy5leGl0O1xuXG5pbnRlcmZhY2UgQ29uZmlnUmVzdWx0IHtcbiAgY29uZmlnUGF0aDogc3RyaW5nO1xuICBvcmlnaW5hbENvbmZpZzogc3RyaW5nIHwgbnVsbDtcbn1cblxuY29uc3QgY3JlYXRlRGVmYXVsdEVTTGludENvbmZpZyA9ICh1c2VUeXBlc2NyaXB0OiBib29sZWFuLCBjd2Q6IHN0cmluZyk6IENvbmZpZ1Jlc3VsdCA9PiB7XG4gIC8vIFVzZSBhIHRlbXBvcmFyeSBmaWxlIHBhdGggaW5zdGVhZCBvZiBjcmVhdGluZyBpbiB0aGUgcHJvamVjdCBkaXJlY3RvcnlcbiAgY29uc3QgY29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJy5sZXgtdGVtcC1kZWZhdWx0LWVzbGludC5janMnKTtcbiAgY29uc3Qgb3JpZ2luYWxDb25maWcgPSBudWxsO1xuXG4gIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBDb21tb25KUyBtb2R1bGUgdGhhdCByZXF1aXJlcyBMZXgncyBFU0xpbnQgY29uZmlnXG4gIGNvbnN0IGNvbmZpZ0NvbnRlbnQgPSBgLy8gVGVtcG9yYXJ5IEVTTGludCBjb25maWcgZ2VuZXJhdGVkIGJ5IExleFxuY29uc3QgbGV4Q29uZmlnID0gcmVxdWlyZSgnQG5sYWJzL2xleC9lc2xpbnQuY29uZmlnLm1qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGxleENvbmZpZztgO1xuXG4gIHdyaXRlRmlsZVN5bmMoY29uZmlnUGF0aCwgY29uZmlnQ29udGVudCwgJ3V0ZjgnKTtcblxuICByZXR1cm4ge1xuICAgIGNvbmZpZ1BhdGgsXG4gICAgb3JpZ2luYWxDb25maWdcbiAgfTtcbn07XG5cbmNvbnN0IGRldGVjdFR5cGVTY3JpcHQgPSAoY3dkOiBzdHJpbmcpOiBib29sZWFuID0+IGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAndHNjb25maWcuanNvbicpKTtcblxuLyoqXG4gKiBFbnN1cmUgcGFja2FnZS5qc29uIGhhcyB0eXBlOiBtb2R1bGUgZm9yIEVTTSBzdXBwb3J0XG4gKi9cbmNvbnN0IGVuc3VyZU1vZHVsZVR5cGUgPSAoY3dkOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gcGF0aFJlc29sdmUoY3dkLCAncGFja2FnZS5qc29uJyk7XG5cbiAgaWYoZXhpc3RzU3luYyhwYWNrYWdlSnNvblBhdGgpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhY2thZ2VKc29uQ29udGVudCA9IHJlYWRGaWxlU3luYyhwYWNrYWdlSnNvblBhdGgsICd1dGY4Jyk7XG4gICAgICBjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UocGFja2FnZUpzb25Db250ZW50KTtcblxuICAgICAgLy8gSWYgdHlwZSBpcyBub3Qgc2V0IHRvIG1vZHVsZSwgd2FybiBpbnN0ZWFkIG9mIGF1dG8tbW9kaWZ5aW5nXG4gICAgICBpZihwYWNrYWdlSnNvbi50eXBlICE9PSAnbW9kdWxlJykge1xuICAgICAgICBsb2coJ1dhcm5pbmc6IHBhY2thZ2UuanNvbiBzaG91bGQgaGF2ZSBcInR5cGVcIjogXCJtb2R1bGVcIiBmb3IgRVNNIHN1cHBvcnQuIFBsZWFzZSBhZGQgdGhpcyBtYW51YWxseS4nLCAnd2FybicsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgLy8gSWdub3JlIGVycm9yc1xuICAgIH1cbiAgfVxufTtcblxuY29uc3QgaW5zdGFsbERlcGVuZGVuY2llcyA9IGFzeW5jIChjd2Q6IHN0cmluZywgdXNlVHlwZXNjcmlwdDogYm9vbGVhbiwgcXVpZXQ6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgIGxvZygnVXNpbmcgVHlwZVNjcmlwdCBFU0xpbnQgZnJvbSBMZXguLi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgfSBlbHNlIHtcbiAgICBsb2coJ1VzaW5nIEVTTGludCBmcm9tIExleC4uLicsICdpbmZvJywgcXVpZXQpO1xuICB9XG59O1xuXG5jb25zdCBydW5Fc2xpbnRXaXRoTGV4ID0gYXN5bmMgKFxuICBjd2Q6IHN0cmluZyxcbiAgcXVpZXQ6IGJvb2xlYW4sXG4gIGNsaU5hbWU6IHN0cmluZyxcbiAgZml4OiBib29sZWFuLFxuICBkZWJ1ZzogYm9vbGVhbixcbiAgdXNlVHlwZXNjcmlwdDogYm9vbGVhbixcbiAgY2FwdHVyZU91dHB1dD86IChvdXRwdXQ6IHN0cmluZykgPT4gdm9pZFxuKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcbiAgY29uc3Qgc3Bpbm5lciA9IGNyZWF0ZVNwaW5uZXIocXVpZXQpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcHJvamVjdENvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLm1qcycpO1xuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoVHMgPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLnRzJyk7XG4gICAgY29uc3QgaGFzUHJvamVjdENvbmZpZyA9IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpIHx8IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGhUcyk7XG4gICAgY29uc3QgaGFzTGV4Q29uZmlnRXNsaW50ID0gTGV4Q29uZmlnLmNvbmZpZy5lc2xpbnQgJiYgT2JqZWN0LmtleXMoTGV4Q29uZmlnLmNvbmZpZy5lc2xpbnQpLmxlbmd0aCA+IDA7XG5cbiAgICBjb25zdCBwb3NzaWJsZVBhdGhzID0gW1xuICAgICAgcGF0aFJlc29sdmUoY3VycmVudERpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLm1qcycpLFxuICAgICAgcGF0aFJlc29sdmUoY3VycmVudERpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLnRzJyksXG4gICAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmVudi5MRVhfSE9NRSB8fCAnL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL0BubGFicy9sZXgnLCAnZXNsaW50LmNvbmZpZy5tanMnKSxcbiAgICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuZW52LkxFWF9IT01FIHx8ICcvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLnRzJylcbiAgICBdO1xuXG4gICAgbGV0IGxleENvbmZpZ1BhdGggPSAnJztcblxuICAgIGZvcihjb25zdCBwYXRoIG9mIHBvc3NpYmxlUGF0aHMpIHtcbiAgICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgICAgbGV4Q29uZmlnUGF0aCA9IHBhdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBjb25maWdQYXRoID0gJyc7XG4gICAgbGV0IHRlbXBDb25maWdQYXRoID0gJyc7XG5cbiAgICAvLyBQcmlvcml0eTpcbiAgICAvLyAxLiBQcm9qZWN0IGVzbGludC5jb25maWcgZmlsZXNcbiAgICAvLyAyLiBFU0xpbnQgY29uZmlnIGluIGxleC5jb25maWcuKiBmaWxlXG4gICAgLy8gMy4gTGV4J3MgZGVmYXVsdCBlc2xpbnQuY29uZmlnLm1qc1xuICAgIC8vIDQuIENyZWF0ZSBhIHRlbXBvcmFyeSBjb25maWcgZmlsZVxuICAgIGlmKGhhc1Byb2plY3RDb25maWcpIHtcbiAgICAgIGNvbmZpZ1BhdGggPSBleGlzdHNTeW5jKHByb2plY3RDb25maWdQYXRoVHMpID8gcHJvamVjdENvbmZpZ1BhdGhUcyA6IHByb2plY3RDb25maWdQYXRoO1xuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBVc2luZyBwcm9qZWN0IEVTTGludCBjb25maWcgZmlsZTogJHtjb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZihoYXNMZXhDb25maWdFc2xpbnQpIHtcbiAgICAgIC8vIFdoZW4gdXNpbmcgbGV4LmNvbmZpZy5lc2xpbnQsIGNyZWF0ZSBhIHRlbXBvcmFyeSBKUyBjb25maWcgZmlsZSAobm90IEpTT04pXG4gICAgICAvLyB0byBhdm9pZCBFU00gSlNPTiBpbXBvcnQgaXNzdWVzXG4gICAgICB0ZW1wQ29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJy5sZXgtdGVtcC1lc2xpbnQuY2pzJyk7XG5cbiAgICAgIC8vIENyZWF0ZSBhIENvbW1vbkpTIG1vZHVsZSB0aGF0IGV4dGVuZHMgTGV4J3MgZXNsaW50IGNvbmZpZ1xuICAgICAgY29uc3QgY29uZmlnQ29udGVudCA9IGAvLyBUZW1wb3JhcnkgRVNMaW50IGNvbmZpZyBnZW5lcmF0ZWQgYnkgTGV4XG5jb25zdCBsZXhDb25maWcgPSByZXF1aXJlKCdAbmxhYnMvbGV4L2VzbGludC5jb25maWcubWpzJyk7XG5jb25zdCB1c2VyQ29uZmlnID0gJHtKU09OLnN0cmluZ2lmeShMZXhDb25maWcuY29uZmlnLmVzbGludCwgbnVsbCwgMil9O1xuXG4vLyBNZXJnZSBMZXgncyBjb25maWcgd2l0aCB1c2VyIGNvbmZpZ1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIC4uLmxleENvbmZpZ1xufTtgO1xuXG4gICAgICB3cml0ZUZpbGVTeW5jKHRlbXBDb25maWdQYXRoLCBjb25maWdDb250ZW50LCAndXRmOCcpO1xuICAgICAgY29uZmlnUGF0aCA9IHRlbXBDb25maWdQYXRoO1xuXG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYFVzaW5nIEVTTGludCBjb25maWcgZnJvbSBsZXguY29uZmlnLiogZmlsZSB2aWEgdGVtcCBmaWxlOiAke3RlbXBDb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZihsZXhDb25maWdQYXRoICYmIGV4aXN0c1N5bmMobGV4Q29uZmlnUGF0aCkpIHtcbiAgICAgIGNvbmZpZ1BhdGggPSBsZXhDb25maWdQYXRoO1xuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBVc2luZyBMZXggRVNMaW50IGNvbmZpZyBmaWxlOiAke2NvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBkZWZhdWx0IGNvbmZpZyBmaWxlIGlmIG5vIG90aGVyIGNvbmZpZyBpcyBmb3VuZFxuICAgICAgdGVtcENvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICcubGV4LXRlbXAtZGVmYXVsdC1lc2xpbnQuY2pzJyk7XG5cbiAgICAgIC8vIENyZWF0ZSBhIGJhc2ljIEVTTGludCBjb25maWdcbiAgICAgIGNvbnN0IGNvbmZpZ0NvbnRlbnQgPSBgLy8gVGVtcG9yYXJ5IGRlZmF1bHQgRVNMaW50IGNvbmZpZyBnZW5lcmF0ZWQgYnkgTGV4XG5jb25zdCBsZXhDb25maWcgPSByZXF1aXJlKCdAbmxhYnMvbGV4L2VzbGludC5jb25maWcubWpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbGV4Q29uZmlnO2A7XG5cbiAgICAgIHdyaXRlRmlsZVN5bmModGVtcENvbmZpZ1BhdGgsIGNvbmZpZ0NvbnRlbnQsICd1dGY4Jyk7XG4gICAgICBjb25maWdQYXRoID0gdGVtcENvbmZpZ1BhdGg7XG5cbiAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgIGxvZyhgQ3JlYXRlZCB0ZW1wb3JhcnkgZGVmYXVsdCBFU0xpbnQgY29uZmlnIGF0OiAke3RlbXBDb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nKCdObyBFU0xpbnQgY29uZmlndXJhdGlvbiBmb3VuZC4gVXNpbmcgTGV4IGRlZmF1bHQgY29uZmlndXJhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBlc2xpbnRCaW5hcnkgPSByZXNvbHZlQmluYXJ5UGF0aCgnZXNsaW50JywgJ2VzbGludCcpO1xuXG4gICAgaWYoIWVzbGludEJpbmFyeSkge1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFU0xpbnQgYmluYXJ5IG5vdCBmb3VuZCBpbiBMZXgncyBub2RlX21vZHVsZXNgLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICBsb2coJ1BsZWFzZSByZWluc3RhbGwgTGV4IG9yIGNoZWNrIHlvdXIgaW5zdGFsbGF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgLy8gQmFzZSBFU0xpbnQgYXJndW1lbnRzXG4gICAgY29uc3QgYmFzZUVzbGludEFyZ3MgPSBbXG4gICAgICAuLi4oZml4ID8gWyctLWZpeCddIDogW10pLFxuICAgICAgLi4uKGRlYnVnID8gWyctLWRlYnVnJ10gOiBbXSksXG4gICAgICAnLS1uby1lcnJvci1vbi11bm1hdGNoZWQtcGF0dGVybicsXG4gICAgICAnLS1uby13YXJuLWlnbm9yZWQnXG4gICAgXTtcblxuICAgIC8vIEFkZCBjb25maWcgcGF0aFxuICAgIGNvbnN0IGNvbmZpZ0FyZ3MgPSBjb25maWdQYXRoID8gWyctLWNvbmZpZycsIGNvbmZpZ1BhdGhdIDogW107XG5cbiAgICBjb25zdCBqc1Jlc3VsdCA9IGF3YWl0IGV4ZWNhKGVzbGludEJpbmFyeSwgW1xuICAgICAgJ3NyYy8qKi8qLntqcyxqc3h9JyxcbiAgICAgIC4uLmNvbmZpZ0FyZ3MsXG4gICAgICAuLi5iYXNlRXNsaW50QXJnc1xuICAgIF0sIHtcbiAgICAgIGN3ZCxcbiAgICAgIHJlamVjdDogZmFsc2UsXG4gICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgIHN0ZGlvOiAncGlwZSdcbiAgICB9KTtcblxuICAgIGlmKGpzUmVzdWx0LnN0ZG91dCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUubG9nKGpzUmVzdWx0LnN0ZG91dCk7XG4gICAgICBpZihjYXB0dXJlT3V0cHV0KSB7XG4gICAgICAgIGNhcHR1cmVPdXRwdXQoanNSZXN1bHQuc3Rkb3V0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihqc1Jlc3VsdC5zdGRlcnIpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmVycm9yKGpzUmVzdWx0LnN0ZGVycik7XG4gICAgICBpZihjYXB0dXJlT3V0cHV0KSB7XG4gICAgICAgIGNhcHR1cmVPdXRwdXQoanNSZXN1bHQuc3RkZXJyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgdHNSZXN1bHQ6IGFueSA9IHtleGl0Q29kZTogMCwgc3RkZXJyOiAnJywgc3Rkb3V0OiAnJ307XG4gICAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgICAgdHNSZXN1bHQgPSBhd2FpdCBleGVjYShlc2xpbnRCaW5hcnksIFtcbiAgICAgICAgJ3NyYy8qKi8qLnt0cyx0c3h9JyxcbiAgICAgICAgLi4uY29uZmlnQXJncyxcbiAgICAgICAgLi4uYmFzZUVzbGludEFyZ3NcbiAgICAgIF0sIHtcbiAgICAgICAgY3dkLFxuICAgICAgICByZWplY3Q6IGZhbHNlLFxuICAgICAgICBzaGVsbDogdHJ1ZSxcbiAgICAgICAgc3RkaW86ICdwaXBlJ1xuICAgICAgfSk7XG5cbiAgICAgIGlmKHRzUmVzdWx0LnN0ZG91dCkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLmxvZyh0c1Jlc3VsdC5zdGRvdXQpO1xuICAgICAgfVxuXG4gICAgICBpZih0c1Jlc3VsdC5zdGRlcnIpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcih0c1Jlc3VsdC5zdGRlcnIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENsZWFuIHVwIHRlbXAgZmlsZSBpZiBjcmVhdGVkXG4gICAgaWYodGVtcENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyh0ZW1wQ29uZmlnUGF0aCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHVubGlua1N5bmModGVtcENvbmZpZ1BhdGgpO1xuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgUmVtb3ZlZCB0ZW1wb3JhcnkgRVNMaW50IGNvbmZpZyBhdCAke3RlbXBDb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIC8vIElnbm9yZSBlcnJvcnMgd2hlbiBjbGVhbmluZyB1cFxuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgRmFpbGVkIHRvIHJlbW92ZSB0ZW1wb3JhcnkgRVNMaW50IGNvbmZpZzogJHtlcnJvci5tZXNzYWdlfWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZXNsaW50Tm90Rm91bmQgPSBqc1Jlc3VsdC5zdGRlcnI/LmluY2x1ZGVzKCdjb21tYW5kIG5vdCBmb3VuZCcpIHx8IGpzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ2VzbGludDogY29tbWFuZCBub3QgZm91bmQnKTtcbiAgICBpZihlc2xpbnROb3RGb3VuZCkge1xuICAgICAgc3Bpbm5lci5mYWlsKCdFU0xpbnQgbm90IGZvdW5kIScpO1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBMZXgncyBFU0xpbnQgYmluYXJ5IG5vdCBmb3VuZC4gUGxlYXNlIHJlaW5zdGFsbCBMZXggb3IgY2hlY2sgeW91ciBpbnN0YWxsYXRpb24uYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgaWYoanNSZXN1bHQuZXhpdENvZGUgPT09IDAgJiYgdHNSZXN1bHQuZXhpdENvZGUgPT09IDApIHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnTGludGluZyBjb21wbGV0ZWQhJyk7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBjb25zdCBub0ZpbGVzRm91bmQgPVxuICAgICAgKGpzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSB8fCBqc1Jlc3VsdC5zdGRvdXQ/LmluY2x1ZGVzKCdObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5JykpICYmXG4gICAgICAoIXVzZVR5cGVzY3JpcHQgfHwgdHNSZXN1bHQuc3RkZXJyPy5pbmNsdWRlcygnTm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeScpIHx8IHRzUmVzdWx0LnN0ZG91dD8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSk7XG5cbiAgICBpZihub0ZpbGVzRm91bmQpIHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnTm8gZmlsZXMgZm91bmQgdG8gbGludCcpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHNwaW5uZXIuZmFpbCgnTGludGluZyBmYWlsZWQhJyk7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFU0xpbnQgZm91bmQgaXNzdWVzIGluIHlvdXIgY29kZS5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIDE7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBzcGlubmVyLmZhaWwoJ0xpbnRpbmcgZmFpbGVkIScpO1xuICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICByZXR1cm4gMTtcbiAgfVxufTtcblxuY29uc3QgYXBwbHlBSUZpeCA9IGFzeW5jIChcbiAgY3dkOiBzdHJpbmcsXG4gIGVycm9yczogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhblxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IHNwaW5uZXIgPSBjcmVhdGVTcGlubmVyKHF1aWV0KTtcbiAgc3Bpbm5lci5zdGFydCgnVXNpbmcgQUkgdG8gZml4IHJlbWFpbmluZyBsaW50IGlzc3Vlcy4uLicpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZUVycm9yTWFwID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpO1xuICAgIGNvbnN0IGxpbmVzID0gZXJyb3JzLnNwbGl0KCdcXG4nKTtcbiAgICBsZXQgY3VycmVudEZpbGUgPSAnJztcblxuICAgIGZvcihjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICBpZihsaW5lLm1hdGNoKC9eKFxcL3xbQS1aXTpcXFxcKS4qP1xcLihqc3xqc3h8dHN8dHN4KSQvKSkge1xuICAgICAgICBjdXJyZW50RmlsZSA9IGxpbmUudHJpbSgpO1xuICAgICAgICBpZighZmlsZUVycm9yTWFwLmhhcyhjdXJyZW50RmlsZSkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGN1cnJlbnRGaWxlLCBbXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZihjdXJyZW50RmlsZSAmJiBsaW5lLnRyaW0oKSAmJiBsaW5lLm1hdGNoKC9cXHMrXFxkKzpcXGQrXFxzKyhlcnJvcnx3YXJuaW5nKVxccysvKSkge1xuICAgICAgICBjb25zdCBlcnJvckFycmF5ID0gZmlsZUVycm9yTWFwLmdldChjdXJyZW50RmlsZSk7XG4gICAgICAgIGlmKGVycm9yQXJyYXkpIHtcbiAgICAgICAgICBlcnJvckFycmF5LnB1c2gobGluZS50cmltKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYoZmlsZUVycm9yTWFwLnNpemUgPT09IDApIHtcbiAgICAgIGxvZygnVXNpbmcgYWx0ZXJuYXRpdmUgZXJyb3IgcGFyc2luZyBzdHJhdGVneScsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBjb25zdCBzZWN0aW9ucyA9IGVycm9ycy5zcGxpdCgnXFxuXFxuJyk7XG5cbiAgICAgIGZvcihjb25zdCBzZWN0aW9uIG9mIHNlY3Rpb25zKSB7XG4gICAgICAgIGlmKHNlY3Rpb24udHJpbSgpID09PSAnJykge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGluZXMgPSBzZWN0aW9uLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBsaW5lc1swXS50cmltKCk7XG5cbiAgICAgICAgaWYoZmlsZVBhdGgubWF0Y2goL1xcLihqc3xqc3h8dHN8dHN4KSQvKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoZmlsZVBhdGgsIFtdKTtcblxuICAgICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYobGluZXNbaV0udHJpbSgpICE9PSAnJykge1xuICAgICAgICAgICAgICBmaWxlRXJyb3JNYXAuZ2V0KGZpbGVQYXRoKT8ucHVzaChsaW5lc1tpXS50cmltKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVFcnJvck1hcC5zaXplID09PSAwKSB7XG4gICAgICBsb2coJ1VzaW5nIGRpcmVjdCBmaWxlIHBhdGggZXh0cmFjdGlvbicsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBjb25zdCBmaWxlUGF0aFJlZ2V4ID0gLyg/OlxcL3xbQS1aXTpcXFxcKSg/OlteOlxcbl0rXFwvKSpbXjpcXG5dK1xcLihqc3xqc3h8dHN8dHN4KS9nO1xuICAgICAgY29uc3QgZmlsZVBhdGhzID0gZXJyb3JzLm1hdGNoKGZpbGVQYXRoUmVnZXgpIHx8IFtdO1xuXG4gICAgICBmb3IoY29uc3QgZmlsZVBhdGggb2YgZmlsZVBhdGhzKSB7XG4gICAgICAgIGlmKCFmaWxlRXJyb3JNYXAuaGFzKGZpbGVQYXRoKSAmJiBleGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoZmlsZVBhdGgsIFtdKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBrbm93bkZpbGVzID0gW1xuICAgICAgICBwYXRoUmVzb2x2ZShjd2QsICdzcmMvY3JlYXRlL2NoYW5nZWxvZy50cycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShjd2QsICdzcmMvdXRpbHMvYWlTZXJ2aWNlLnRzJyksXG4gICAgICAgIHBhdGhSZXNvbHZlKGN3ZCwgJ3NyYy91dGlscy9hcHAudHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL3V0aWxzL3JlYWN0U2hpbS50cycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShjd2QsICdzcmMvY29tbWFuZHMvbGludC9hdXRvZml4LmpzJylcbiAgICAgIF07XG5cbiAgICAgIGZvcihjb25zdCBmaWxlIG9mIGtub3duRmlsZXMpIHtcbiAgICAgICAgaWYoZXhpc3RzU3luYyhmaWxlKSAmJiAhZmlsZUVycm9yTWFwLmhhcyhmaWxlKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoZmlsZSwgW10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVFcnJvck1hcC5rZXlzKCkpIHtcbiAgICAgIGlmKCFleGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgICAgICBsb2coYEZpbGUgbm90IGZvdW5kOiAke2ZpbGVQYXRofWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgbG9nKGBQcm9jZXNzaW5nIGZpbGU6ICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgICAgIGNvbnN0IGlzQ3Vyc29ySURFID0gTGV4Q29uZmlnLmNvbmZpZy5haT8ucHJvdmlkZXIgPT09ICdjdXJzb3InIHx8IHByb2Nlc3MuZW52LkNVUlNPUl9JREUgPT09ICd0cnVlJztcblxuICAgICAgaWYoaXNDdXJzb3JJREUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwcm9tcHQgPSBgRml4IGFsbCBFU0xpbnQgZXJyb3JzIGluIHRoaXMgZmlsZS4gRm9jdXMgb246XG4xLiBGaXhpbmcgbmFtaW5nIGNvbnZlbnRpb25zXG4yLiBGaXhpbmcgc29ydC1rZXlzIGlzc3Vlc1xuMy4gUmVwbGFjaW5nIGNvbnNvbGUubG9nIHdpdGggbG9nIHV0aWxpdHlcbjQuIEZpeGluZyBuby1wbHVzcGx1cyBpc3N1ZXNcbjUuIEZpeGluZyB1bm5lY2Vzc2FyeSBlc2NhcGUgY2hhcmFjdGVyc1xuNi4gRml4aW5nIG90aGVyIEVTTGludCBlcnJvcnNcblxuQ1JJVElDQUwgUkVRVUlSRU1FTlRTOlxuLSBPTkxZIGZpeCB0aGUgc3BlY2lmaWMgbGluZXMgd2l0aCBFU0xpbnQgZXJyb3JzXG4tIERPIE5PVCBtb2RpZnkgYW55IG90aGVyIGxpbmVzIG9mIGNvZGVcbi0gRE8gTk9UIHJlbW92ZSBsaW5lIGJyZWFrcyB1bmxlc3MgdGhleSBhcmUgc3BlY2lmaWNhbGx5IGNhdXNpbmcgRVNMaW50IGVycm9yc1xuLSBETyBOT1QgY29uZGVuc2UgbXVsdGktbGluZSBzdHJ1Y3R1cmVzIHRvIHNpbmdsZSBsaW5lc1xuLSBQUkVTRVJWRSBhbGwgZXhpc3RpbmcgbGluZSBicmVha3MgYW5kIGZvcm1hdHRpbmcgdGhhdCBpcyBub3QgY2F1c2luZyBlcnJvcnNcblxuU1BFQ0lGSUMgRk9STUFUVElORyBSVUxFUzpcbi0gTWFpbnRhaW4gcHJvcGVyIGluZGVudGF0aW9uICgyIHNwYWNlcylcbi0gS2VlcCBsaW5lIGJyZWFrcyBiZXR3ZWVuIGNsYXNzL2ludGVyZmFjZSBkZWNsYXJhdGlvbiBhbmQgdGhlaXIgbWVtYmVyc1xuLSBLZWVwIGxpbmUgYnJlYWtzIGJldHdlZW4gbWV0aG9kc1xuLSBFbnN1cmUgdGhlcmUgaXMgYSBsaW5lIGJyZWFrIGFmdGVyIG9wZW5pbmcgYnJhY2VzIGZvciBjbGFzc2VzLCBpbnRlcmZhY2VzLCBhbmQgbWV0aG9kc1xuLSBETyBOT1QgcGxhY2UgY2xhc3MvaW50ZXJmYWNlIHByb3BlcnRpZXMgb3IgbWV0aG9kcyBvbiB0aGUgc2FtZSBsaW5lIGFzIHRoZSBvcGVuaW5nIGJyYWNlXG4tIFByZXNlcnZlIGVtcHR5IGxpbmVzIGJldHdlZW4gbG9naWNhbCBjb2RlIGJsb2Nrc1xuLSBQUkVTRVJWRSBtdWx0aS1saW5lIGltcG9ydHMgLSBkbyBub3QgY29uZGVuc2UgdGhlbSB0byBzaW5nbGUgbGluZXNcbi0gUFJFU0VSVkUgbXVsdGktbGluZSBvYmplY3QvYXJyYXkgZGVjbGFyYXRpb25zIC0gZG8gbm90IGNvbmRlbnNlIHRoZW0gdG8gc2luZ2xlIGxpbmVzXG5cblNPUlQtS0VZUyBSVUxFIChISUdIRVNUIFBSSU9SSVRZKTpcbi0gQWxsIG9iamVjdCBsaXRlcmFsIGtleXMgTVVTVCBiZSBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkgaW4gYXNjZW5kaW5nIG9yZGVyXG4tIFRoaXMgYXBwbGllcyB0byBBTEwgb2JqZWN0cyBpbiB0aGUgZmlsZSwgbm90IGp1c3QgdGhvc2Ugd2l0aCBleHBsaWNpdCBzb3J0LWtleXMgZXJyb3JzXG4tIEV4YW1wbGU6IHtiOiAyLCBhOiAxLCBjOiAzfSBzaG91bGQgYmVjb21lIHthOiAxLCBiOiAyLCBjOiAzfVxuLSBQcmVzZXJ2ZSB0aGUgb3JpZ2luYWwgZm9ybWF0dGluZyBhbmQgbGluZSBicmVha3Mgd2hlbiBzb3J0aW5nXG5cbkV4YW1wbGUgb2YgQ09SUkVDVCBmb3JtYXR0aW5nIChETyBOT1QgQ0hBTkdFKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtcbiAgc3RhdGljIHJlYWRvbmx5IEFERF9JVEVNX0VSUk9SOiBzdHJpbmcgPSAnVVNFUl9BRERfSVRFTV9FUlJPUic7XG4gIHN0YXRpYyByZWFkb25seSBPVEhFUl9DT05TVEFOVDogc3RyaW5nID0gJ09USEVSX0NPTlNUQU5UJztcbn1cblxuY29uc3RydWN0b3IoZmx1eDogRmx1eEZyYW1ld29yaywgQ3VzdG9tQWRhcHRlcjogdHlwZW9mIEV2ZW50ID0gRXZlbnQpIHtcbiAgdGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDtcbn1cblxuaW1wb3J0IHtcbiAgYXBwLFxuICBldmVudHMsXG4gIGltYWdlcyxcbiAgbG9jYXRpb25zLFxuICBtZXNzYWdlcyxcbiAgcG9zdHMsXG4gIHRhZ3MsXG4gIHVzZXJzLFxuICB3ZWJzb2NrZXRcbn0gZnJvbSAnLi9zdG9yZXMnO1xuXG5jb25zdCBjb25maWcgPSB7XG4gIGFwaUtleTogJ3ZhbHVlJyxcbiAgYmFzZVVybDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAgdGltZW91dDogNTAwMFxufTtcblxuRXhhbXBsZSBvZiBJTkNPUlJFQ1QgZm9ybWF0dGluZyAoRklYIFRISVMpOlxuZXhwb3J0IGNsYXNzIFVzZXJDb25zdGFudHMge3N0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7dGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDt9XG5cbmltcG9ydCB7YXBwLCBldmVudHMsIGltYWdlcywgbG9jYXRpb25zLCBtZXNzYWdlcywgcG9zdHMsIHRhZ3MsIHVzZXJzLCB3ZWJzb2NrZXR9IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge2Jhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIGFwaUtleTogJ3ZhbHVlJywgdGltZW91dDogNTAwMH07XG5cbkZpeCBPTkxZIHRoZSBzcGVjaWZpYyBFU0xpbnQgZXJyb3JzLiBSZXR1cm4gdGhlIHByb3Blcmx5IGZvcm1hdHRlZCBjb2RlLmA7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcHJvbXB0RmlsZSA9IHBhdGhSZXNvbHZlKGN3ZCwgJy5jdXJzb3JfcHJvbXB0X3RlbXAudHh0Jyk7XG4gICAgICAgICAgICB3cml0ZUZpbGVTeW5jKHByb21wdEZpbGUsIHByb21wdCwgJ3V0ZjgnKTtcblxuICAgICAgICAgICAgLy8gVXNlIEN1cnNvciBDTEkgdG8gZml4IHRoZSBmaWxlXG4gICAgICAgICAgICBhd2FpdCBleGVjYSgnY3Vyc29yJywgWydlZGl0JywgJy0tZmlsZScsIGZpbGVQYXRoLCAnLS1wcm9tcHQtZmlsZScsIHByb21wdEZpbGVdLCB7XG4gICAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgICAgcmVqZWN0OiBmYWxzZSxcbiAgICAgICAgICAgICAgc3RkaW86ICdwaXBlJ1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHVubGlua1N5bmMocHJvbXB0RmlsZSk7XG4gICAgICAgICAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsb2coYEFwcGxpZWQgQ3Vyc29yIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfSBjYXRjaHtcbiAgICAgICAgICAgIGNvbnN0IHdhc01vZGlmaWVkID0gYXdhaXQgYXBwbHlEaXJlY3RGaXhlcyhmaWxlUGF0aCwgcXVpZXQpO1xuICAgICAgICAgICAgaWYod2FzTW9kaWZpZWQpIHtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgIGxvZyhgRXJyb3IgdXNpbmcgQ3Vyc29yIEFJOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgICAgIGF3YWl0IGFwcGx5RGlyZWN0Rml4ZXMoZmlsZVBhdGgsIHF1aWV0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3Qgd2FzTW9kaWZpZWQgPSBhd2FpdCBhcHBseURpcmVjdEZpeGVzKGZpbGVQYXRoLCBxdWlldCk7XG4gICAgICAgIGlmKHdhc01vZGlmaWVkKSB7XG4gICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZUVycm9ycyA9IGZpbGVFcnJvck1hcC5nZXQoZmlsZVBhdGgpIHx8IFtdO1xuICAgICAgICBpZihmaWxlRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qge2NhbGxBSVNlcnZpY2V9ID0gYXdhaXQgaW1wb3J0KCcuLi8uLi91dGlscy9haVNlcnZpY2UuanMnKTtcblxuICAgICAgICAgICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHByb21wdCA9IGBGaXggdGhlIGZvbGxvd2luZyBFU0xpbnQgZXJyb3JzIGluIHRoaXMgY29kZTpcbiR7ZmlsZUVycm9ycy5qb2luKCdcXG4nKX1cblxuSGVyZSdzIHRoZSBjb2RlOlxuXFxgXFxgXFxgXG4ke2ZpbGVDb250ZW50fVxuXFxgXFxgXFxgXG5cbkNSSVRJQ0FMIFJFUVVJUkVNRU5UUzpcbi0gT05MWSBmaXggdGhlIHNwZWNpZmljIGxpbmVzIHdpdGggRVNMaW50IGVycm9yc1xuLSBETyBOT1QgbW9kaWZ5IGFueSBvdGhlciBsaW5lcyBvZiBjb2RlXG4tIERPIE5PVCByZW1vdmUgbGluZSBicmVha3MgdW5sZXNzIHRoZXkgYXJlIHNwZWNpZmljYWxseSBjYXVzaW5nIEVTTGludCBlcnJvcnNcbi0gRE8gTk9UIGNvbmRlbnNlIG11bHRpLWxpbmUgc3RydWN0dXJlcyB0byBzaW5nbGUgbGluZXNcbi0gUFJFU0VSVkUgYWxsIGV4aXN0aW5nIGxpbmUgYnJlYWtzIGFuZCBmb3JtYXR0aW5nIHRoYXQgaXMgbm90IGNhdXNpbmcgZXJyb3JzXG5cblNQRUNJRklDIEZPUk1BVFRJTkcgUlVMRVM6XG4tIE1haW50YWluIHByb3BlciBpbmRlbnRhdGlvbiAoMiBzcGFjZXMpXG4tIEtlZXAgbGluZSBicmVha3MgYmV0d2VlbiBjbGFzcy9pbnRlcmZhY2UgZGVjbGFyYXRpb24gYW5kIHRoZWlyIG1lbWJlcnNcbi0gS2VlcCBsaW5lIGJyZWFrcyBiZXR3ZWVuIG1ldGhvZHNcbi0gRW5zdXJlIHRoZXJlIGlzIGEgbGluZSBicmVhayBhZnRlciBvcGVuaW5nIGJyYWNlcyBmb3IgY2xhc3NlcywgaW50ZXJmYWNlcywgYW5kIG1ldGhvZHNcbi0gRE8gTk9UIHBsYWNlIGNsYXNzL2ludGVyZmFjZSBwcm9wZXJ0aWVzIG9yIG1ldGhvZHMgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgb3BlbmluZyBicmFjZVxuLSBQcmVzZXJ2ZSBlbXB0eSBsaW5lcyBiZXR3ZWVuIGxvZ2ljYWwgY29kZSBibG9ja3Ncbi0gUFJFU0VSVkUgbXVsdGktbGluZSBpbXBvcnRzIC0gZG8gbm90IGNvbmRlbnNlIHRoZW0gdG8gc2luZ2xlIGxpbmVzXG4tIFBSRVNFUlZFIG11bHRpLWxpbmUgb2JqZWN0L2FycmF5IGRlY2xhcmF0aW9ucyAtIGRvIG5vdCBjb25kZW5zZSB0aGVtIHRvIHNpbmdsZSBsaW5lc1xuXG5TT1JULUtFWVMgUlVMRSAoSElHSEVTVCBQUklPUklUWSk6XG4tIEFsbCBvYmplY3QgbGl0ZXJhbCBrZXlzIE1VU1QgYmUgc29ydGVkIGFscGhhYmV0aWNhbGx5IGluIGFzY2VuZGluZyBvcmRlclxuLSBUaGlzIGFwcGxpZXMgdG8gQUxMIG9iamVjdHMgaW4gdGhlIGZpbGUsIG5vdCBqdXN0IHRob3NlIHdpdGggZXhwbGljaXQgc29ydC1rZXlzIGVycm9yc1xuLSBFeGFtcGxlOiB7YjogMiwgYTogMSwgYzogM30gc2hvdWxkIGJlY29tZSB7YTogMSwgYjogMiwgYzogM31cbi0gUHJlc2VydmUgdGhlIG9yaWdpbmFsIGZvcm1hdHRpbmcgYW5kIGxpbmUgYnJlYWtzIHdoZW4gc29ydGluZ1xuXG5XSEFUIFRPIEZJWDpcbjEuIFNvcnRpbmcgYWxsIG9iamVjdCBrZXlzIGFscGhhYmV0aWNhbGx5IChzb3J0LWtleXMgcnVsZSkgLSBBTEwgb2JqZWN0cyBtdXN0IGhhdmUgc29ydGVkIGtleXNcbjIuIEZpeGluZyBuYW1pbmcgY29udmVudGlvbnMgLSBPTkxZIGZvciB2YXJpYWJsZXMvZnVuY3Rpb25zIHdpdGggbmFtaW5nIGVycm9yc1xuMy4gUmVwbGFjaW5nIGNvbnNvbGUubG9nIHdpdGggbG9nIHV0aWxpdHkgLSBPTkxZIGZvciBjb25zb2xlLmxvZyBzdGF0ZW1lbnRzXG40LiBGaXhpbmcgbm8tcGx1c3BsdXMgaXNzdWVzIC0gT05MWSBmb3IgKysvLS0gb3BlcmF0b3JzXG41LiBGaXhpbmcgdW5uZWNlc3NhcnkgZXNjYXBlIGNoYXJhY3RlcnMgLSBPTkxZIGZvciBlc2NhcGVkIGNoYXJhY3RlcnMgdGhhdCBkb24ndCBuZWVkIGVzY2FwaW5nXG42LiBQcm9wZXIgaW5kZW50YXRpb24gYW5kIHNwYWNpbmcgLSBPTkxZIHdoZXJlIHNwZWNpZmljYWxseSByZXF1aXJlZCBieSBlcnJvcnNcbjcuIFN0cmluZyBxdW90ZXMgY29uc2lzdGVuY3kgKHVzZSBzaW5nbGUgcXVvdGVzKSAtIE9OTFkgZm9yIHN0cmluZyBsaXRlcmFscyB3aXRoIHF1b3RlIGVycm9yc1xuOC4gSW1wb3J0IG9yZGVyIGFuZCBzcGFjaW5nIC0gT05MWSBmb3IgaW1wb3J0cyB3aXRoIG9yZGVyL3NwYWNpbmcgZXJyb3JzXG45LiBGdW5jdGlvbiBwYXJhbWV0ZXIgZm9ybWF0dGluZyAtIE9OTFkgZm9yIGZ1bmN0aW9ucyB3aXRoIHBhcmFtZXRlciBlcnJvcnNcbjEwLiBWYXJpYWJsZSBuYW1pbmcgY29udmVudGlvbnMgLSBPTkxZIGZvciB2YXJpYWJsZXMgd2l0aCBuYW1pbmcgZXJyb3JzXG4xMS4gTm8gdW51c2VkIHZhcmlhYmxlcyBvciBpbXBvcnRzIC0gT05MWSBmb3IgdW51c2VkIHZhcmlhYmxlcy9pbXBvcnRzXG4xMi4gQXZvaWRpbmcgbmVzdGVkIHRlcm5hcmllcyAtIE9OTFkgZm9yIG5lc3RlZCB0ZXJuYXJ5IGV4cHJlc3Npb25zXG4xMy4gQW55IG90aGVyIEVTTGludCBlcnJvcnMgLSBPTkxZIGZvciB0aGUgc3BlY2lmaWMgZXJyb3JzIGxpc3RlZCBhYm92ZVxuXG5XSEFUIE5PVCBUTyBGSVg6XG4tIERvIG5vdCBjaGFuZ2UgcHJvcGVybHkgZm9ybWF0dGVkIG11bHRpLWxpbmUgc3RydWN0dXJlc1xuLSBEbyBub3QgcmVtb3ZlIGxpbmUgYnJlYWtzIHRoYXQgYXJlIG5vdCBjYXVzaW5nIGVycm9yc1xuLSBEbyBub3QgY2hhbmdlIGluZGVudGF0aW9uIHRoYXQgaXMgYWxyZWFkeSBjb3JyZWN0XG4tIERvIG5vdCBtb2RpZnkgc3BhY2luZyB0aGF0IGlzIGFscmVhZHkgY29ycmVjdFxuLSBEbyBub3QgY29uZGVuc2UgcmVhZGFibGUgbXVsdGktbGluZSBjb2RlIHRvIHNpbmdsZSBsaW5lc1xuLSBEbyBub3QgbW9kaWZ5IGNvZGUgdGhhdCBpcyBub3QgbWVudGlvbmVkIGluIHRoZSBFU0xpbnQgZXJyb3JzXG5cbkV4YW1wbGUgb2YgQ09SUkVDVCBmb3JtYXR0aW5nIChETyBOT1QgQ0hBTkdFKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtcbiAgc3RhdGljIHJlYWRvbmx5IEFERF9JVEVNX0VSUk9SOiBzdHJpbmcgPSAnVVNFUl9BRERfSVRFTV9FUlJPUic7XG4gIHN0YXRpYyByZWFkb25seSBPVEhFUl9DT05TVEFOVDogc3RyaW5nID0gJ09USEVSX0NPTlNUQU5UJztcbn1cblxuY29uc3RydWN0b3IoZmx1eDogRmx1eEZyYW1ld29yaywgQ3VzdG9tQWRhcHRlcjogdHlwZW9mIEV2ZW50ID0gRXZlbnQpIHtcbiAgdGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDtcbn1cblxuaW1wb3J0IHtcbiAgYXBwLFxuICBldmVudHMsXG4gIGltYWdlcyxcbiAgbG9jYXRpb25zLFxuICBtZXNzYWdlcyxcbiAgcG9zdHMsXG4gIHRhZ3MsXG4gIHVzZXJzLFxuICB3ZWJzb2NrZXRcbn0gZnJvbSAnLi9zdG9yZXMnO1xuXG5jb25zdCBjb25maWcgPSB7XG4gIGFwaUtleTogJ3ZhbHVlJyxcbiAgYmFzZVVybDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAgdGltZW91dDogNTAwMFxufTtcblxuRXhhbXBsZSBvZiBJTkNPUlJFQ1QgZm9ybWF0dGluZyAoRklYIFRISVMpOlxuZXhwb3J0IGNsYXNzIFVzZXJDb25zdGFudHMge3N0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7dGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDt9XG5cbmltcG9ydCB7YXBwLCBldmVudHMsIGltYWdlcywgbG9jYXRpb25zLCBtZXNzYWdlcywgcG9zdHMsIHRhZ3MsIHVzZXJzLCB3ZWJzb2NrZXR9IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge2Jhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIGFwaUtleTogJ3ZhbHVlJywgdGltZW91dDogNTAwMH07XG5cbkZpeCBPTkxZIHRoZSBzcGVjaWZpYyBFU0xpbnQgZXJyb3JzIGxpc3RlZCBhYm92ZS4gUmV2aWV3IHRoZSBlbnRpcmUgZmlsZSBmb3IgY29tcGxpYW5jZSB3aXRoIGFsbCBFU0xpbnQgcnVsZXMuXG5SZXR1cm4gb25seSB0aGUgcHJvcGVybHkgZm9ybWF0dGVkIGZpeGVkIGNvZGUgd2l0aG91dCBhbnkgZXhwbGFuYXRpb25zLmA7XG5cbiAgICAgICAgICAgIGNvbnN0IGZpeGVkQ29udGVudCA9IGF3YWl0IGNhbGxBSVNlcnZpY2UocHJvbXB0LCBxdWlldCk7XG5cbiAgICAgICAgICAgIGlmKGZpeGVkQ29udGVudCAmJiBmaXhlZENvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICAgICAgICAgIHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGZpeGVkQ29udGVudCwgJ3V0ZjgnKTtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgICAgbG9nKGBFcnJvciBhcHBseWluZyBBSSBmaXhlcyB0byAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBzcGlubmVyLnN1Y2NlZWQoJ0FJIGZpeGVzIGFwcGxpZWQgc3VjY2Vzc2Z1bGx5IScpO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gYXBwbHkgQUkgZml4ZXMnKTtcbiAgICBsb2coYEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBhcHBseURpcmVjdEZpeGVzID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIGxldCB3YXNNb2RpZmllZCA9IGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG4gICAgbGV0IG5ld0NvbnRlbnQgPSBmaWxlQ29udGVudDtcblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdhaVNlcnZpY2UudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGFpU2VydmljZS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvblxcL2pzb24nLFxccyonQXV0aG9yaXphdGlvbic6IGBCZWFyZXIvZyxcbiAgICAgICAgJ1xcJ0F1dGhvcml6YXRpb25cXCc6IGBCZWFyZXJcXCcsIFxcJ0NvbnRlbnQtVHlwZVxcJzogXFwnYXBwbGljYXRpb24vanNvblxcJydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9oZWFkZXJzOiB7KFtefV0qKX0sXFxzKm1ldGhvZDogJ1BPU1QnL2csXG4gICAgICAgICdtZXRob2Q6IFxcJ1BPU1RcXCcsXFxuICAgICAgaGVhZGVyczogeyQxfSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC97cm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3N5c3RlbVxcJywnXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL3tyb2xlOiAndXNlcicsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3VzZXJcXCcsJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL1xcKChbXildKj8pXyhbYS16QS1aMC05XSspKFxccyo6W14pXSopXFwpL2csXG4gICAgICAgICcoJDEkMiQzKSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL2NvbnNvbGVcXC5sb2dcXCgvZywgJ2xvZygnKTtcblxuICAgICAgaWYoIW5ld0NvbnRlbnQuaW5jbHVkZXMoJ2ltcG9ydCB7bG9nfScpICYmIG5ld0NvbnRlbnQuaW5jbHVkZXMoJ2xvZygnKSkge1xuICAgICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAgIC9pbXBvcnQgeyhbXn1dKil9IGZyb20gJyguKiknOy8sXG4gICAgICAgICAgJ2ltcG9ydCB7JDF9IGZyb20gXFwnJDJcXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdyZWFjdFNoaW0udHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgbmFtaW5nLWNvbnZlbnRpb24gaXNzdWVzIGluIHJlYWN0U2hpbS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAnaW1wb3J0ICogYXMgUmVhY3QgZnJvbScsXG4gICAgICAgICdpbXBvcnQgKiBhcyByZWFjdCBmcm9tJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvUmVhY3RcXC4vZywgJ3JlYWN0LicpO1xuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdjaGFuZ2Vsb2cudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGNoYW5nZWxvZy50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC8oXFx3KylcXCtcXCsvZywgJyQxICs9IDEnKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcJC9nLCAnJCcpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcLi9nLCAnLicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcKi9nLCAnKicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXDovZywgJzonKTtcbiAgICB9XG5cbiAgICBpZihmaWxlUGF0aC5pbmNsdWRlcygnYXBwLnRzJykpIHtcbiAgICAgIGxvZygnRml4aW5nIGlzc3VlcyBpbiBhcHAudHMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvY29uc29sZVxcLmxvZ1xcKC9nLCAnbG9nKCcpO1xuXG4gICAgICBpZighbmV3Q29udGVudC5pbmNsdWRlcygnaW1wb3J0IHtsb2d9JykgJiYgbmV3Q29udGVudC5pbmNsdWRlcygnbG9nKCcpKSB7XG4gICAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgICAgL2ltcG9ydCBib3hlbiBmcm9tICdib3hlbic7LyxcbiAgICAgICAgICAnaW1wb3J0IGJveGVuIGZyb20gXFwnYm94ZW5cXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC9cXFxcXFwvL2csICcvJyk7XG4gICAgfVxuXG4gICAgaWYoZmlsZVBhdGguaW5jbHVkZXMoJ2F1dG9maXguanMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGF1dG9maXguanMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2ltcG9ydCB7KFtefV0qKX0gZnJvbSAncGF0aCc7W1xcc1xcbl0qaW1wb3J0IHsoW159XSopfSBmcm9tICdwYXRoJzsvLFxuICAgICAgICAnaW1wb3J0IHskMSwgJDJ9IGZyb20gXFwncGF0aFxcJzsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvX19maWxlbmFtZS9nLFxuICAgICAgICAnY3VycmVudEZpbGVuYW1lJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9fX2Rpcm5hbWUvZyxcbiAgICAgICAgJ2N1cnJlbnREaXJuYW1lJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnN0IHByZWZpeCA9IHR5cGUgPT09ICdlcnJvcicgXFw/ICfinYwgJyA6IHR5cGUgPT09ICdzdWNjZXNzJyBcXD8gJ+KchSAnIDogJ+KEue+4jyAnOy8sXG4gICAgICAgICdsZXQgcHJlZml4ID0gXFwn4oS577iPIFxcJztcXG5pZih0eXBlID09PSBcXCdlcnJvclxcJykge1xcbiAgcHJlZml4ID0gXFwn4p2MIFxcJztcXG59IGVsc2UgaWYodHlwZSA9PT0gXFwnc3VjY2Vzc1xcJykge1xcbiAgcHJlZml4ID0gXFwn4pyFIFxcJztcXG59J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIHJ1bkVzbGludEZpeFxcKFxcKS9nLFxuICAgICAgICAnY29uc3QgcnVuRXNsaW50Rml4ID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGdldEZpbGVzV2l0aEVycm9yc1xcKFxcKS9nLFxuICAgICAgICAnY29uc3QgZ2V0RmlsZXNXaXRoRXJyb3JzID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGlzQ3Vyc29yQXZhaWxhYmxlXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBpc0N1cnNvckF2YWlsYWJsZSA9IGFzeW5jICgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCkvZyxcbiAgICAgICAgJ2NvbnN0IGZpeEZpbGVXaXRoQ3Vyc29yQUkgPSBhc3luYyAoZmlsZVBhdGgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBtYWluXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBtYWluID0gYXN5bmMgKCknXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvaW1wb3J0IHtleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmN9L2csXG4gICAgICAgICdpbXBvcnQge3dyaXRlRmlsZVN5bmN9J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnNvbGVcXC5sb2dcXChgXFwke3ByZWZpeH0gXFwke21lc3NhZ2V9YFxcKTsvZyxcbiAgICAgICAgJ3Byb2Nlc3Muc3Rkb3V0LndyaXRlKGAke3ByZWZpeH0gJHttZXNzYWdlfVxcXFxuYCk7J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL30gY2F0Y2hcXChlcnJvclxcKSB7W1xcc1xcbl0qXFwvXFwvIElnbm9yZSBjbGVhbnVwIGVycm9ycy9nLFxuICAgICAgICAnfSBjYXRjaChfKSB7XFxuICAgICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC99IGNhdGNoXFwoZXJyb3JcXCkge1tcXHNcXG5dKmxvZ1xcKC9nLFxuICAgICAgICAnfSBjYXRjaChlcnIpIHtcXG4gICAgbG9nKCdcbiAgICAgICk7XG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvfSBjYXRjaFxcKGVycm9yXFwpIHtbXFxzXFxuXSpyZXR1cm4gZmFsc2U7L2csXG4gICAgICAgICd9IGNhdGNoKF8pIHtcXG4gICAgcmV0dXJuIGZhbHNlOydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9mb3JcXChjb25zdCBmaWxlUGF0aCBvZiBmaWxlc1dpdGhFcnJvcnNcXCkge1tcXHNcXG5dKmNvbnN0IHN1Y2Nlc3MgPSBhd2FpdCBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCk7L2csXG4gICAgICAgICdjb25zdCBmaXhSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoZmlsZXNXaXRoRXJyb3JzLm1hcChmaWxlUGF0aCA9PiBmaXhGaWxlV2l0aEN1cnNvckFJKGZpbGVQYXRoKSkpO1xcbmZvcihjb25zdCBzdWNjZXNzIG9mIGZpeFJlc3VsdHMpIHsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvZml4ZWRDb3VudFxcK1xcKzsvZyxcbiAgICAgICAgJ2ZpeGVkQ291bnQgKz0gMTsnXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmKG5ld0NvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBuZXdDb250ZW50LCAndXRmOCcpO1xuICAgICAgbG9nKGBGaXhlZCBpc3N1ZXMgaW4gJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIHdhc01vZGlmaWVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gd2FzTW9kaWZpZWQ7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYEVycm9yIGFwcGx5aW5nIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGxvYWRBSUNvbmZpZyA9IGFzeW5jIChjd2Q6IHN0cmluZywgcXVpZXQ6IGJvb2xlYW4sIGRlYnVnOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3QgY29uZmlnRm9ybWF0cyA9IFsnanMnLCAnbWpzJywgJ2NqcycsICd0cycsICdqc29uJ107XG4gIGNvbnN0IGNvbmZpZ0Jhc2VOYW1lID0gJ2xleC5jb25maWcnO1xuICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuXG4gIGZvcihjb25zdCBmb3JtYXQgb2YgY29uZmlnRm9ybWF0cykge1xuICAgIGNvbnN0IHBvdGVudGlhbFBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIGAuLyR7Y29uZmlnQmFzZU5hbWV9LiR7Zm9ybWF0fWApO1xuICAgIGlmKGV4aXN0c1N5bmMocG90ZW50aWFsUGF0aCkpIHtcbiAgICAgIGxleENvbmZpZ1BhdGggPSBwb3RlbnRpYWxQYXRoO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgaWYobGV4Q29uZmlnUGF0aCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBGb3IgTUpTIGZpbGVzLCB3ZSBuZWVkIHRvIHVzZSBkeW5hbWljIGltcG9ydCB3aXRoIFVSTCBmb3IgY29tcGF0aWJpbGl0eVxuICAgICAgY29uc3QgZm9ybWF0ID0gZXh0bmFtZShsZXhDb25maWdQYXRoKS5zbGljZSgxKTtcbiAgICAgIGxldCBpbXBvcnRQYXRoID0gbGV4Q29uZmlnUGF0aDtcblxuICAgICAgLy8gVXNlIFVSTCBwcm90b2NvbCBmb3IgRVNNIGltcG9ydHNcbiAgICAgIGlmKGZvcm1hdCA9PT0gJ21qcycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGBmaWxlOi8vJHtsZXhDb25maWdQYXRofWApO1xuICAgICAgICAgIGltcG9ydFBhdGggPSB1cmwuaHJlZjtcbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgbG9nKGBVc2luZyBVUkwgZm9ybWF0IGZvciBNSlMgaW1wb3J0OiAke2ltcG9ydFBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoKHVybEVycm9yKSB7XG4gICAgICAgICAgbG9nKGBFcnJvciBjcmVhdGluZyBVUkwgZm9yIE1KUyBpbXBvcnQ6ICR7dXJsRXJyb3IubWVzc2FnZX1gLCAnd2FybicsIGRlYnVnIHx8ICFxdWlldCk7XG4gICAgICAgICAgaW1wb3J0UGF0aCA9IGBmaWxlOi8vJHtsZXhDb25maWdQYXRofWA7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBUcnlpbmcgdG8gaW1wb3J0IGNvbmZpZyBmcm9tICR7aW1wb3J0UGF0aH0gKGZvcm1hdDogJHtmb3JtYXR9KWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuXG4gICAgICBsZXQgbGV4Q29uZmlnO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV4Q29uZmlnID0gYXdhaXQgaW1wb3J0KGltcG9ydFBhdGgpO1xuICAgICAgfSBjYXRjaChpbXBvcnRFcnJvcikge1xuICAgICAgICBpZihpbXBvcnRFcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdub3QgZGVmaW5lZCBpbiBFUyBtb2R1bGUgc2NvcGUnKSkge1xuICAgICAgICAgIGxvZyhgRVMgTW9kdWxlIHN5bnRheCBlcnJvciBpbiAke2xleENvbmZpZ1BhdGh9LiBNYWtlIHN1cmUgeW91J3JlIHVzaW5nICdleHBvcnQnIGluc3RlYWQgb2YgJ21vZHVsZS5leHBvcnRzJy5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoaW1wb3J0RXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgaW1wb3J0RXJyb3I7XG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBib3RoIEVTTSAoZGVmYXVsdCBleHBvcnQpIGFuZCBDb21tb25KUyAobW9kdWxlLmV4cG9ydHMpXG4gICAgICBsZXQgY29uZmlnRGF0YSA9IG51bGw7XG4gICAgICBpZihsZXhDb25maWcuZGVmYXVsdCkge1xuICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnLmRlZmF1bHQ7XG4gICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgbG9nKGBGb3VuZCBkZWZhdWx0IGV4cG9ydCBpbiAke2xleENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZvciBDb21tb25KUyBvciBvdGhlciBtb2R1bGUgc3lzdGVtc1xuICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnO1xuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgVXNpbmcgZGlyZWN0IGV4cG9ydCBpbiAke2xleENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoY29uZmlnRGF0YSAmJiBjb25maWdEYXRhLmFpKSB7XG4gICAgICAgIGxvZyhgRm91bmQgQUkgY29uZmlndXJhdGlvbiBpbiAke3BhdGhSZXNvbHZlKGN3ZCwgbGV4Q29uZmlnUGF0aCl9LCBhcHBseWluZyBzZXR0aW5ncy4uLmAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBMZXhDb25maWcuY29uZmlnLmFpID0gey4uLkxleENvbmZpZy5jb25maWcuYWksIC4uLmNvbmZpZ0RhdGEuYWl9O1xuICAgICAgfVxuICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgIGxvZyhgRXJyb3IgbG9hZGluZyBBSSBjb25maWd1cmF0aW9uIGZyb20gJHtsZXhDb25maWdQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIExvYWQgRVNMaW50IGNvbmZpZ3VyYXRpb24gZnJvbSBsZXguY29uZmlnLiogZmlsZXNcbiAqL1xuY29uc3QgbG9hZEVTTGludENvbmZpZyA9IGFzeW5jIChjd2Q6IHN0cmluZywgcXVpZXQ6IGJvb2xlYW4sIGRlYnVnOiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIC8vIENoZWNrIGlmIExleENvbmZpZyBhbHJlYWR5IGhhcyBFU0xpbnQgY29uZmlndXJhdGlvbiBsb2FkZWRcbiAgaWYoTGV4Q29uZmlnLmNvbmZpZy5lc2xpbnQgJiYgT2JqZWN0LmtleXMoTGV4Q29uZmlnLmNvbmZpZy5lc2xpbnQpLmxlbmd0aCA+IDApIHtcbiAgICBsb2coJ0ZvdW5kIEVTTGludCBjb25maWd1cmF0aW9uIGluIGxleC5jb25maWcuKiBmaWxlJywgJ2luZm8nLCBkZWJ1ZyB8fCAhcXVpZXQpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gVHJ5IHRvIGxvYWQgZnJvbSBsZXguY29uZmlnLiogZmlsZXMgaWYgbm90IGFscmVhZHkgbG9hZGVkXG4gIGNvbnN0IGNvbmZpZ0Zvcm1hdHMgPSBbJ2pzJywgJ21qcycsICdjanMnLCAndHMnLCAnanNvbiddO1xuICBjb25zdCBjb25maWdCYXNlTmFtZSA9ICdsZXguY29uZmlnJztcblxuICBmb3IoY29uc3QgZm9ybWF0IG9mIGNvbmZpZ0Zvcm1hdHMpIHtcbiAgICBjb25zdCBwb3RlbnRpYWxQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBgLi8ke2NvbmZpZ0Jhc2VOYW1lfS4ke2Zvcm1hdH1gKTtcbiAgICBpZihleGlzdHNTeW5jKHBvdGVudGlhbFBhdGgpKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBGb3IgTUpTIGZpbGVzLCB3ZSBuZWVkIHRvIHVzZSBkeW5hbWljIGltcG9ydCB3aXRoIFVSTCBmb3IgY29tcGF0aWJpbGl0eVxuICAgICAgICBjb25zdCBmaWxlRm9ybWF0ID0gZXh0bmFtZShwb3RlbnRpYWxQYXRoKS5zbGljZSgxKTtcbiAgICAgICAgbGV0IGltcG9ydFBhdGggPSBwb3RlbnRpYWxQYXRoO1xuXG4gICAgICAgIC8vIFVzZSBVUkwgcHJvdG9jb2wgZm9yIEVTTSBpbXBvcnRzXG4gICAgICAgIGlmKGZpbGVGb3JtYXQgPT09ICdtanMnKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoYGZpbGU6Ly8ke3BvdGVudGlhbFBhdGh9YCk7XG4gICAgICAgICAgICBpbXBvcnRQYXRoID0gdXJsLmhyZWY7XG4gICAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgICBsb2coYFVzaW5nIFVSTCBmb3JtYXQgZm9yIE1KUyBpbXBvcnQ6ICR7aW1wb3J0UGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoKHVybEVycm9yKSB7XG4gICAgICAgICAgICBsb2coYEVycm9yIGNyZWF0aW5nIFVSTCBmb3IgTUpTIGltcG9ydDogJHt1cmxFcnJvci5tZXNzYWdlfWAsICd3YXJuJywgZGVidWcgfHwgIXF1aWV0KTtcbiAgICAgICAgICAgIGltcG9ydFBhdGggPSBgZmlsZTovLyR7cG90ZW50aWFsUGF0aH1gO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgbG9nKGBUcnlpbmcgdG8gaW1wb3J0IGNvbmZpZyBmcm9tICR7aW1wb3J0UGF0aH0gKGZvcm1hdDogJHtmaWxlRm9ybWF0fSlgLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsZXhDb25maWc7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbGV4Q29uZmlnID0gYXdhaXQgaW1wb3J0KGltcG9ydFBhdGgpO1xuICAgICAgICB9IGNhdGNoKGltcG9ydEVycm9yKSB7XG4gICAgICAgICAgaWYoaW1wb3J0RXJyb3IubWVzc2FnZS5pbmNsdWRlcygnbm90IGRlZmluZWQgaW4gRVMgbW9kdWxlIHNjb3BlJykpIHtcbiAgICAgICAgICAgIGxvZyhgRVMgTW9kdWxlIHN5bnRheCBlcnJvciBpbiAke3BvdGVudGlhbFBhdGh9LiBNYWtlIHN1cmUgeW91J3JlIHVzaW5nICdleHBvcnQnIGluc3RlYWQgb2YgJ21vZHVsZS5leHBvcnRzJy5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGltcG9ydEVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBpbXBvcnRFcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBib3RoIEVTTSAoZGVmYXVsdCBleHBvcnQpIGFuZCBDb21tb25KUyAobW9kdWxlLmV4cG9ydHMpXG4gICAgICAgIGxldCBjb25maWdEYXRhID0gbnVsbDtcbiAgICAgICAgaWYobGV4Q29uZmlnLmRlZmF1bHQpIHtcbiAgICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnLmRlZmF1bHQ7XG4gICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgIGxvZyhgRm91bmQgZGVmYXVsdCBleHBvcnQgaW4gJHtwb3RlbnRpYWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBGb3IgQ29tbW9uSlMgb3Igb3RoZXIgbW9kdWxlIHN5c3RlbXNcbiAgICAgICAgICBjb25maWdEYXRhID0gbGV4Q29uZmlnO1xuICAgICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgICBsb2coYFVzaW5nIGRpcmVjdCBleHBvcnQgaW4gJHtwb3RlbnRpYWxQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNvbmZpZ0RhdGEgJiYgY29uZmlnRGF0YS5lc2xpbnQgJiYgT2JqZWN0LmtleXMoY29uZmlnRGF0YS5lc2xpbnQpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBsb2coYEZvdW5kIEVTTGludCBjb25maWd1cmF0aW9uIGluICR7cGF0aFJlc29sdmUoY3dkLCBwb3RlbnRpYWxQYXRoKX0sIGFwcGx5aW5nIHNldHRpbmdzLi4uYCwgJ2luZm8nLCBkZWJ1ZyB8fCAhcXVpZXQpO1xuICAgICAgICAgIExleENvbmZpZy5jb25maWcuZXNsaW50ID0gey4uLkxleENvbmZpZy5jb25maWcuZXNsaW50LCAuLi5jb25maWdEYXRhLmVzbGludH07XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgbG9nKGBFcnJvciBsb2FkaW5nIEVTTGludCBjb25maWd1cmF0aW9uIGZyb20gJHtwb3RlbnRpYWxQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuY29uc3QgcmVtb3ZlRmlsZUNvbW1lbnRzID0gKGZpbGVQYXRoOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogYm9vbGVhbiA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG5cbiAgICBpZihmaWxlQ29udGVudC5sZW5ndGggPiAxMDAwMDAwKSB7IC8vIDFNQiBsaW1pdFxuICAgICAgbG9nKGBTa2lwcGluZyBjb21tZW50IHJlbW92YWwgZm9yIGxhcmdlIGZpbGU6ICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIFVzZSByZWdleCB0byBtYXRjaCBkaWZmZXJlbnQgdHlwZXMgb2YgY29tbWVudHNcbiAgICAvLyBQcmVzZXJ2ZXM6XG4gICAgLy8gMS4gQ29weXJpZ2h0IG5vdGljZXMgKC8qIENvcHlyaWdodCAuLi4gKi8pXG4gICAgLy8gMi4gVE9ETyBjb21tZW50cyAoLy8gVE9ETzogLi4uKVxuICAgIC8vIDMuIExpY2Vuc2UgaGVhZGVycyAoLyogLi4uIExpY2Vuc2UgLi4uICovKVxuXG4gICAgLy8gSGFuZGxlIG11bHRpLWxpbmUgY29tbWVudHMgZmlyc3QgLSBwcmVzZXJ2ZSBjb3B5cmlnaHQvbGljZW5zZSBub3RpY2VzXG4gICAgbGV0IG5ld0NvbnRlbnQgPSBmaWxlQ29udGVudC5yZXBsYWNlKFxuICAgICAgL1xcL1xcKltcXHNcXFNdKj9cXCpcXC8vZyxcbiAgICAgIChtYXRjaCkgPT4ge1xuICAgICAgICBpZihtYXRjaC5pbmNsdWRlcygnQ29weXJpZ2h0JykgfHxcbiAgICAgICAgICBtYXRjaC5pbmNsdWRlcygnTElDRU5TRScpIHx8XG4gICAgICAgICAgbWF0Y2guaW5jbHVkZXMoJ0xpY2Vuc2UnKSB8fFxuICAgICAgICAgIG1hdGNoLmluY2x1ZGVzKCdsaWNlbnNlJykpIHtcbiAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBIYW5kbGUgc2luZ2xlLWxpbmUgY29tbWVudHMgLSBwcmVzZXJ2ZSBUT0RPc1xuICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAvXFwvXFwvLiokL2dtLFxuICAgICAgKG1hdGNoKSA9PiB7XG4gICAgICAgIGlmKG1hdGNoLmluY2x1ZGVzKCdUT0RPJykgfHwgbWF0Y2guaW5jbHVkZXMoJ0ZJWE1FJykpIHtcbiAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBDbGVhbiB1cCBhbnkgbXVsdGlwbGUgYmxhbmsgbGluZXMgY3JlYXRlZCBieSBjb21tZW50IHJlbW92YWxcbiAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC9cXG5cXHMqXFxuXFxzKlxcbi9nLCAnXFxuXFxuJyk7XG5cbiAgICAvLyBJZiB0aGUgZmlsZSB3YXMgbW9kaWZpZWQsIHNhdmUgaXRcbiAgICBpZihuZXdDb250ZW50ICE9PSBmaWxlQ29udGVudCkge1xuICAgICAgd3JpdGVGaWxlU3luYyhmaWxlUGF0aCwgbmV3Q29udGVudCwgJ3V0ZjgnKTtcbiAgICAgIGxvZyhgUmVtb3ZlZCBjb21tZW50cyBmcm9tICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYEVycm9yIHJlbW92aW5nIGNvbW1lbnRzIGZyb20gJHtmaWxlUGF0aH06ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbGludCA9IGFzeW5jIChjbWQ6IExpbnRPcHRpb25zICYgeydyZW1vdmUtY29tbWVudHMnPzogYm9vbGVhbn0sIGNhbGxiYWNrOiBMaW50Q2FsbGJhY2sgPSBwcm9jZXNzLmV4aXQpOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCB7XG4gICAgY2xpTmFtZSA9ICdMZXgnLFxuICAgIGZpeCA9IGZhbHNlLFxuICAgIGRlYnVnID0gZmFsc2UsXG4gICAgcXVpZXQgPSBmYWxzZSxcbiAgICBjb25maWcgPSBudWxsLFxuICAgIHJlbW92ZUNvbW1lbnRzID0gZmFsc2UsXG4gICAgJ3JlbW92ZS1jb21tZW50cyc6IHJlbW92ZUNvbW1lbnRzRmxhZyA9IGZhbHNlXG4gIH0gPSBjbWQ7XG5cbiAgY29uc3Qgc2hvdWxkUmVtb3ZlQ29tbWVudHMgPSByZW1vdmVDb21tZW50cyB8fCByZW1vdmVDb21tZW50c0ZsYWc7XG5cbiAgbG9nKGAke2NsaU5hbWV9IGxpbnRpbmcuLi5gLCAnaW5mbycsIHF1aWV0KTtcblxuICBjb25zdCBjd2QgPSBwcm9jZXNzLmN3ZCgpO1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgYXdhaXQgbG9hZEFJQ29uZmlnKGN3ZCwgcXVpZXQsIGRlYnVnKTtcblxuICBsZXQgdGVtcENvbmZpZ1BhdGg6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgdXNlVHlwZXNjcmlwdCA9IGRldGVjdFR5cGVTY3JpcHQoY3dkKTtcbiAgICBsb2coYFR5cGVTY3JpcHQgJHt1c2VUeXBlc2NyaXB0ID8gJ2RldGVjdGVkJyA6ICdub3QgZGV0ZWN0ZWQnfSBmcm9tIHRzY29uZmlnLmpzb25gLCAnaW5mbycsIHF1aWV0KTtcblxuICAgIGlmKHVzZVR5cGVzY3JpcHQpIHtcbiAgICAgIExleENvbmZpZy5jaGVja0xpbnRUeXBlc2NyaXB0Q29uZmlnKCk7XG4gICAgfVxuXG4gICAgZW5zdXJlTW9kdWxlVHlwZShjd2QpO1xuXG4gICAgYXdhaXQgaW5zdGFsbERlcGVuZGVuY2llcyhjd2QsIHVzZVR5cGVzY3JpcHQsIHF1aWV0KTtcblxuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy5tanMnKTtcbiAgICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aFRzID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy50cycpO1xuICAgIGNvbnN0IGhhc0VzbGludENvbmZpZyA9IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpIHx8XG4gICAgICBleGlzdHNTeW5jKHByb2plY3RDb25maWdQYXRoVHMpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy5qcycpKSB8fFxuICAgICAgZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMuanNvbicpKSB8fFxuICAgICAgZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMueW1sJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy55YW1sJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYycpKTtcblxuICAgIGNvbnN0IGhhc0xleEVzbGludENvbmZpZyA9IGF3YWl0IGxvYWRFU0xpbnRDb25maWcoY3dkLCBxdWlldCwgZGVidWcpO1xuXG4gICAgaWYoaGFzTGV4RXNsaW50Q29uZmlnKSB7XG4gICAgICBsb2coJ1VzaW5nIEVTTGludCBjb25maWd1cmF0aW9uIGZyb20gbGV4LmNvbmZpZy4qIGZpbGUnLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG5cbiAgICBpZihleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy5qc29uJykpKSB7XG4gICAgICB1bmxpbmtTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy5qc29uJykpO1xuICAgIH1cblxuICAgIGxldCBsZXhDb25maWdQYXRoID0gJyc7XG4gICAgbGV0IHNob3VsZENyZWF0ZVRlbXBDb25maWcgPSBmYWxzZTtcblxuICAgIGlmKCFoYXNFc2xpbnRDb25maWcgJiYgIWhhc0xleEVzbGludENvbmZpZykge1xuICAgICAgY29uc3QgcG9zc2libGVQYXRocyA9IFtcbiAgICAgICAgcGF0aFJlc29sdmUoY3VycmVudERpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLnRzJyksXG4gICAgICAgIHBhdGhSZXNvbHZlKGN1cnJlbnREaXJuYW1lLCAnLi4vLi4vLi4vLi4vZXNsaW50LmNvbmZpZy5qbXMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUocHJvY2Vzcy5lbnYuTEVYX0hPTUUgfHwgJy4vbm9kZV9tb2R1bGVzL0BubGFicy9sZXgnLCAnZXNsaW50LmNvbmZpZy50cycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmVudi5MRVhfSE9NRSB8fCAnLi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLm1qcycpXG4gICAgICBdO1xuXG4gICAgICBmb3IoY29uc3QgcGF0aCBvZiBwb3NzaWJsZVBhdGhzKSB7XG4gICAgICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgICAgICBsZXhDb25maWdQYXRoID0gcGF0aDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYEN1cnJlbnQgZGlyZWN0b3J5OiAke2N1cnJlbnREaXJuYW1lfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBsb2coYFByb2plY3QgY29uZmlnIHBhdGg6ICR7cHJvamVjdENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGxvZyhgUHJvamVjdCBjb25maWcgZXhpc3RzOiAke2hhc0VzbGludENvbmZpZ31gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBGb3VuZCBMZXggY29uZmlnOiAke2xleENvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGxvZyhgTGV4IGNvbmZpZyBleGlzdHM6ICR7ISFsZXhDb25maWdQYXRoICYmIGV4aXN0c1N5bmMobGV4Q29uZmlnUGF0aCl9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG5cbiAgICAgIGlmKGxleENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyhsZXhDb25maWdQYXRoKSkge1xuICAgICAgICBsb2coJ05vIEVTTGludCBjb25maWd1cmF0aW9uIGZvdW5kIGluIHByb2plY3QuIFVzaW5nIExleFxcJ3MgZGVmYXVsdCBjb25maWd1cmF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2hvdWxkQ3JlYXRlVGVtcENvbmZpZyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYoY29uZmlnKSB7XG4gICAgICBjb25zdCB1c2VyQ29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgY29uZmlnKTtcbiAgICAgIGlmKGV4aXN0c1N5bmModXNlckNvbmZpZ1BhdGgpKSB7XG4gICAgICAgIGxvZyhgVXNpbmcgc3BlY2lmaWVkIEVTTGludCBjb25maWd1cmF0aW9uOiAke2NvbmZpZ31gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgc2hvdWxkQ3JlYXRlVGVtcENvbmZpZyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nKGBTcGVjaWZpZWQgRVNMaW50IGNvbmZpZ3VyYXRpb24gbm90IGZvdW5kOiAke2NvbmZpZ30uIFVzaW5nIExleCdzIGRlZmF1bHQgY29uZmlndXJhdGlvbi5gLCAnd2FybicsIHF1aWV0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzaG91bGRDcmVhdGVUZW1wQ29uZmlnKSB7XG4gICAgICBsb2coJ05vIEVTTGludCBjb25maWd1cmF0aW9uIGZvdW5kLiBDcmVhdGluZyBhIHRlbXBvcmFyeSBjb25maWd1cmF0aW9uLi4uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBjb25zdCBjb25maWdSZXN1bHQgPSBjcmVhdGVEZWZhdWx0RVNMaW50Q29uZmlnKHVzZVR5cGVzY3JpcHQsIGN3ZCk7XG4gICAgICB0ZW1wQ29uZmlnUGF0aCA9IGNvbmZpZ1Jlc3VsdC5jb25maWdQYXRoO1xuICAgIH1cblxuICAgIGxldCBlc2xpbnRPdXRwdXQgPSAnJztcbiAgICBjb25zdCBjYXB0dXJlT3V0cHV0ID0gKG91dHB1dDogc3RyaW5nKSA9PiB7XG4gICAgICBlc2xpbnRPdXRwdXQgKz0gYCR7b3V0cHV0fVxcbmA7XG4gICAgfTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJ1bkVzbGludFdpdGhMZXgoY3dkLCBxdWlldCwgY2xpTmFtZSwgdHJ1ZSwgZGVidWcsIHVzZVR5cGVzY3JpcHQsIGNhcHR1cmVPdXRwdXQpO1xuXG4gICAgaWYoc2hvdWxkUmVtb3ZlQ29tbWVudHMpIHtcbiAgICAgIHNwaW5uZXIuc3RhcnQoJ1JlbW92aW5nIGNvbW1lbnRzIGZyb20gZmlsZXMuLi4nKTtcblxuICAgICAgY29uc3QgZ2xvYiA9IGF3YWl0IGltcG9ydCgnZ2xvYicpO1xuICAgICAgY29uc3QgZmlsZXMgPSBnbG9iLnN5bmMoJ3tzcmMsbGlifS8qKi8qLntqcyxqc3gsdHMsdHN4fScsIHtcbiAgICAgICAgY3dkLFxuICAgICAgICBpZ25vcmU6IFsnKiovbm9kZV9tb2R1bGVzLyoqJywgJyoqL2xpYi8qKicsICcqKi9kaXN0LyoqJywgJyoqL2J1aWxkLyoqJ11cbiAgICAgIH0pO1xuXG4gICAgICBsZXQgcHJvY2Vzc2VkQ291bnQgPSAwO1xuICAgICAgZm9yKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIGZpbGUpO1xuICAgICAgICBpZihyZW1vdmVGaWxlQ29tbWVudHMoZmlsZVBhdGgsIHF1aWV0KSkge1xuICAgICAgICAgIHByb2Nlc3NlZENvdW50Kys7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc3Bpbm5lci5zdWNjZWVkKGBSZW1vdmVkIGNvbW1lbnRzIGZyb20gJHtwcm9jZXNzZWRDb3VudH0gZmlsZXNgKTtcbiAgICB9XG5cbiAgICBpZihyZXN1bHQgIT09IDAgJiYgZml4KSB7XG4gICAgICBjb25zdCBhaUNvbmZpZ3VyZWQgPSBMZXhDb25maWcuY29uZmlnLmFpPy5wcm92aWRlciAmJiBMZXhDb25maWcuY29uZmlnLmFpLnByb3ZpZGVyICE9PSAnbm9uZSc7XG5cbiAgICAgIGlmKGFpQ29uZmlndXJlZCkge1xuICAgICAgICBsb2coJ0FwcGx5aW5nIEFJIGZpeGVzIHRvIHJlbWFpbmluZyBpc3N1ZXMuLi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgYXdhaXQgYXBwbHlBSUZpeChjd2QsIGVzbGludE91dHB1dCwgcXVpZXQpO1xuXG4gICAgICAgIGNvbnN0IGFmdGVyRml4UmVzdWx0ID0gYXdhaXQgcnVuRXNsaW50V2l0aExleChjd2QsIHF1aWV0LCBjbGlOYW1lLCBmYWxzZSwgZGVidWcsIHVzZVR5cGVzY3JpcHQpO1xuXG4gICAgICAgIGNhbGxiYWNrKGFmdGVyRml4UmVzdWx0KTtcbiAgICAgICAgcmV0dXJuIGFmdGVyRml4UmVzdWx0O1xuICAgICAgfVxuICAgICAgbG9nKCdFU0xpbnQgY291bGQgbm90IGZpeCBhbGwgaXNzdWVzIGF1dG9tYXRpY2FsbHkuJywgJ3dhcm4nLCBxdWlldCk7XG4gICAgICBsb2coJ1RvIGVuYWJsZSBBSS1wb3dlcmVkIGZpeGVzLCBhZGQgQUkgY29uZmlndXJhdGlvbiB0byB5b3VyIGxleC5jb25maWcgZmlsZTonLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIGxvZyhgXG4vLyBJbiBsZXguY29uZmlnLmpzIChvciBsZXguY29uZmlnLm1qcywgbGV4LmNvbmZpZy5janMsIGV0Yy4pXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8vIFlvdXIgZXhpc3RpbmcgY29uZmlnXG4gIGFpOiB7XG4gICAgcHJvdmlkZXI6ICdjdXJzb3InIC8vIG9yICdvcGVuYWknLCAnYW50aHJvcGljJywgZXRjLlxuICAgIC8vIEFkZGl0aW9uYWwgcHJvdmlkZXItc3BlY2lmaWMgc2V0dGluZ3NcbiAgfVxufTtgLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhyZXN1bHQpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgaWYoc3Bpbm5lcikge1xuICAgICAgc3Bpbm5lci5mYWlsKCdMaW50aW5nIGZhaWxlZCEnKTtcbiAgICB9XG4gICAgY2FsbGJhY2soMSk7XG4gICAgcmV0dXJuIDE7XG4gIH0gZmluYWxseSB7XG4gICAgY29uc3QgdGVtcEZpbGVQYXRocyA9IFtcbiAgICAgIHRlbXBDb25maWdQYXRoLFxuICAgICAgcGF0aFJlc29sdmUoY3dkLCAnLmxleC10ZW1wLWVzbGludC5janMnKSxcbiAgICAgIHBhdGhSZXNvbHZlKGN3ZCwgJy5sZXgtdGVtcC1kZWZhdWx0LWVzbGludC5janMnKVxuICAgIF07XG5cbiAgICBmb3IoY29uc3QgZmlsZVBhdGggb2YgdGVtcEZpbGVQYXRocykge1xuICAgICAgaWYoZmlsZVBhdGggJiYgZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB1bmxpbmtTeW5jKGZpbGVQYXRoKTtcbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgbG9nKGBDbGVhbmVkIHVwIHRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGF0ICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoe1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59OyJdLCJuYW1lcyI6WyJleGVjYSIsImV4aXN0c1N5bmMiLCJyZWFkRmlsZVN5bmMiLCJ1bmxpbmtTeW5jIiwid3JpdGVGaWxlU3luYyIsImRpcm5hbWUiLCJyZXNvbHZlIiwicGF0aFJlc29sdmUiLCJleHRuYW1lIiwiTGV4Q29uZmlnIiwiY3JlYXRlU3Bpbm5lciIsInJlc29sdmVCaW5hcnlQYXRoIiwibG9nIiwiY3VycmVudEZpbGVuYW1lIiwiY3VycmVudERpcm5hbWUiLCJldmFsIiwicHJvY2VzcyIsImN3ZCIsImNyZWF0ZURlZmF1bHRFU0xpbnRDb25maWciLCJ1c2VUeXBlc2NyaXB0IiwiY29uZmlnUGF0aCIsIm9yaWdpbmFsQ29uZmlnIiwiY29uZmlnQ29udGVudCIsImRldGVjdFR5cGVTY3JpcHQiLCJlbnN1cmVNb2R1bGVUeXBlIiwicGFja2FnZUpzb25QYXRoIiwicGFja2FnZUpzb25Db250ZW50IiwicGFja2FnZUpzb24iLCJKU09OIiwicGFyc2UiLCJ0eXBlIiwiX2Vycm9yIiwiaW5zdGFsbERlcGVuZGVuY2llcyIsInF1aWV0IiwicnVuRXNsaW50V2l0aExleCIsImNsaU5hbWUiLCJmaXgiLCJkZWJ1ZyIsImNhcHR1cmVPdXRwdXQiLCJzcGlubmVyIiwicHJvamVjdENvbmZpZ1BhdGgiLCJwcm9qZWN0Q29uZmlnUGF0aFRzIiwiaGFzUHJvamVjdENvbmZpZyIsImhhc0xleENvbmZpZ0VzbGludCIsImNvbmZpZyIsImVzbGludCIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJwb3NzaWJsZVBhdGhzIiwiZW52IiwiTEVYX0hPTUUiLCJsZXhDb25maWdQYXRoIiwicGF0aCIsInRlbXBDb25maWdQYXRoIiwic3RyaW5naWZ5IiwiZXNsaW50QmluYXJ5IiwiYmFzZUVzbGludEFyZ3MiLCJjb25maWdBcmdzIiwianNSZXN1bHQiLCJyZWplY3QiLCJzaGVsbCIsInN0ZGlvIiwic3Rkb3V0IiwiY29uc29sZSIsInN0ZGVyciIsImVycm9yIiwidHNSZXN1bHQiLCJleGl0Q29kZSIsIm1lc3NhZ2UiLCJlc2xpbnROb3RGb3VuZCIsImluY2x1ZGVzIiwiZmFpbCIsInN1Y2NlZWQiLCJub0ZpbGVzRm91bmQiLCJhcHBseUFJRml4IiwiZXJyb3JzIiwic3RhcnQiLCJmaWxlRXJyb3JNYXAiLCJNYXAiLCJsaW5lcyIsInNwbGl0IiwiY3VycmVudEZpbGUiLCJsaW5lIiwibWF0Y2giLCJ0cmltIiwiaGFzIiwic2V0IiwiZXJyb3JBcnJheSIsImdldCIsInB1c2giLCJzaXplIiwic2VjdGlvbnMiLCJzZWN0aW9uIiwiZmlsZVBhdGgiLCJpIiwiZmlsZVBhdGhSZWdleCIsImZpbGVQYXRocyIsImtub3duRmlsZXMiLCJmaWxlIiwiaXNDdXJzb3JJREUiLCJhaSIsInByb3ZpZGVyIiwiQ1VSU09SX0lERSIsInByb21wdCIsInByb21wdEZpbGUiLCJ3YXNNb2RpZmllZCIsImFwcGx5RGlyZWN0Rml4ZXMiLCJmaWxlRXJyb3JzIiwiY2FsbEFJU2VydmljZSIsImZpbGVDb250ZW50Iiwiam9pbiIsImZpeGVkQ29udGVudCIsIm5ld0NvbnRlbnQiLCJyZXBsYWNlIiwibG9hZEFJQ29uZmlnIiwiY29uZmlnRm9ybWF0cyIsImNvbmZpZ0Jhc2VOYW1lIiwiZm9ybWF0IiwicG90ZW50aWFsUGF0aCIsInNsaWNlIiwiaW1wb3J0UGF0aCIsInVybCIsIlVSTCIsImhyZWYiLCJ1cmxFcnJvciIsImxleENvbmZpZyIsImltcG9ydEVycm9yIiwiY29uZmlnRGF0YSIsImRlZmF1bHQiLCJsb2FkRVNMaW50Q29uZmlnIiwiZmlsZUZvcm1hdCIsInJlbW92ZUZpbGVDb21tZW50cyIsImxpbnQiLCJjbWQiLCJjYWxsYmFjayIsImV4aXQiLCJyZW1vdmVDb21tZW50cyIsInJlbW92ZUNvbW1lbnRzRmxhZyIsInNob3VsZFJlbW92ZUNvbW1lbnRzIiwiY2hlY2tMaW50VHlwZXNjcmlwdENvbmZpZyIsImhhc0VzbGludENvbmZpZyIsImhhc0xleEVzbGludENvbmZpZyIsInNob3VsZENyZWF0ZVRlbXBDb25maWciLCJ1c2VyQ29uZmlnUGF0aCIsImNvbmZpZ1Jlc3VsdCIsImVzbGludE91dHB1dCIsIm91dHB1dCIsInJlc3VsdCIsImdsb2IiLCJmaWxlcyIsInN5bmMiLCJpZ25vcmUiLCJwcm9jZXNzZWRDb3VudCIsImFpQ29uZmlndXJlZCIsImFmdGVyRml4UmVzdWx0IiwidGVtcEZpbGVQYXRocyJdLCJtYXBwaW5ncyI6IkFBQUE7OztDQUdDLEdBQ0QsU0FBUUEsS0FBSyxRQUFPLFFBQVE7QUFDNUIsU0FBUUMsVUFBVSxFQUFFQyxZQUFZLEVBQUVDLFVBQVUsRUFBRUMsYUFBYSxRQUFPLEtBQUs7QUFDdkUsU0FBUUMsT0FBTyxFQUFFQyxXQUFXQyxXQUFXLEVBQUVDLE9BQU8sUUFBTyxPQUFPO0FBRTlELFNBQVFDLFNBQVMsUUFBTyxxQkFBcUI7QUFDN0MsU0FBUUMsYUFBYSxRQUFPLHFCQUFxQjtBQUNqRCxTQUFRQyxpQkFBaUIsUUFBTyxzQkFBc0I7QUFDdEQsU0FBUUMsR0FBRyxRQUFPLHFCQUFxQjtBQUV2QyxJQUFJQztBQUNKLElBQUlDO0FBRUosSUFBSTtJQUNGRCxrQkFBa0JFLEtBQUs7SUFDdkJELGlCQUFpQlQsUUFBUVE7QUFDM0IsRUFBRSxPQUFLO0lBQ0xBLGtCQUFrQkcsUUFBUUMsR0FBRztJQUM3QkgsaUJBQWlCRSxRQUFRQyxHQUFHO0FBQzlCO0FBZ0RBLE1BQU1DLDRCQUE0QixDQUFDQyxlQUF3QkY7SUFDekQseUVBQXlFO0lBQ3pFLE1BQU1HLGFBQWFiLFlBQVlVLEtBQUs7SUFDcEMsTUFBTUksaUJBQWlCO0lBRXZCLHVFQUF1RTtJQUN2RSxNQUFNQyxnQkFBZ0IsQ0FBQzs7OzJCQUdFLENBQUM7SUFFMUJsQixjQUFjZ0IsWUFBWUUsZUFBZTtJQUV6QyxPQUFPO1FBQ0xGO1FBQ0FDO0lBQ0Y7QUFDRjtBQUVBLE1BQU1FLG1CQUFtQixDQUFDTixNQUF5QmhCLFdBQVdNLFlBQVlVLEtBQUs7QUFFL0U7O0NBRUMsR0FDRCxNQUFNTyxtQkFBbUIsQ0FBQ1A7SUFDeEIsTUFBTVEsa0JBQWtCbEIsWUFBWVUsS0FBSztJQUV6QyxJQUFHaEIsV0FBV3dCLGtCQUFrQjtRQUM5QixJQUFJO1lBQ0YsTUFBTUMscUJBQXFCeEIsYUFBYXVCLGlCQUFpQjtZQUN6RCxNQUFNRSxjQUFjQyxLQUFLQyxLQUFLLENBQUNIO1lBRS9CLCtEQUErRDtZQUMvRCxJQUFHQyxZQUFZRyxJQUFJLEtBQUssVUFBVTtnQkFDaENsQixJQUFJLGlHQUFpRyxRQUFRO1lBQy9HO1FBQ0YsRUFBRSxPQUFNbUIsUUFBUTtRQUNkLGdCQUFnQjtRQUNsQjtJQUNGO0FBQ0Y7QUFFQSxNQUFNQyxzQkFBc0IsT0FBT2YsS0FBYUUsZUFBd0JjO0lBQ3RFLElBQUdkLGVBQWU7UUFDaEJQLElBQUksdUNBQXVDLFFBQVFxQjtJQUNyRCxPQUFPO1FBQ0xyQixJQUFJLDRCQUE0QixRQUFRcUI7SUFDMUM7QUFDRjtBQUVBLE1BQU1DLG1CQUFtQixPQUN2QmpCLEtBQ0FnQixPQUNBRSxTQUNBQyxLQUNBQyxPQUNBbEIsZUFDQW1CO0lBRUEsTUFBTUMsVUFBVTdCLGNBQWN1QjtJQUU5QixJQUFJO1FBQ0YsTUFBTU8sb0JBQW9CakMsWUFBWVUsS0FBSztRQUMzQyxNQUFNd0Isc0JBQXNCbEMsWUFBWVUsS0FBSztRQUM3QyxNQUFNeUIsbUJBQW1CekMsV0FBV3VDLHNCQUFzQnZDLFdBQVd3QztRQUNyRSxNQUFNRSxxQkFBcUJsQyxVQUFVbUMsTUFBTSxDQUFDQyxNQUFNLElBQUlDLE9BQU9DLElBQUksQ0FBQ3RDLFVBQVVtQyxNQUFNLENBQUNDLE1BQU0sRUFBRUcsTUFBTSxHQUFHO1FBRXBHLE1BQU1DLGdCQUFnQjtZQUNwQjFDLFlBQVlPLGdCQUFnQjtZQUM1QlAsWUFBWU8sZ0JBQWdCO1lBQzVCUCxZQUFZUyxRQUFRa0MsR0FBRyxDQUFDQyxRQUFRLElBQUksMENBQTBDO1lBQzlFNUMsWUFBWVMsUUFBUWtDLEdBQUcsQ0FBQ0MsUUFBUSxJQUFJLDBDQUEwQztTQUMvRTtRQUVELElBQUlDLGdCQUFnQjtRQUVwQixLQUFJLE1BQU1DLFFBQVFKLGNBQWU7WUFDL0IsSUFBR2hELFdBQVdvRCxPQUFPO2dCQUNuQkQsZ0JBQWdCQztnQkFDaEI7WUFDRjtRQUNGO1FBRUEsSUFBSWpDLGFBQWE7UUFDakIsSUFBSWtDLGlCQUFpQjtRQUVyQixZQUFZO1FBQ1osaUNBQWlDO1FBQ2pDLHdDQUF3QztRQUN4QyxxQ0FBcUM7UUFDckMsb0NBQW9DO1FBQ3BDLElBQUdaLGtCQUFrQjtZQUNuQnRCLGFBQWFuQixXQUFXd0MsdUJBQXVCQSxzQkFBc0JEO1lBQ3JFLElBQUdILE9BQU87Z0JBQ1J6QixJQUFJLENBQUMsa0NBQWtDLEVBQUVRLFlBQVksRUFBRSxRQUFRYTtZQUNqRTtRQUNGLE9BQU8sSUFBR1Usb0JBQW9CO1lBQzVCLDZFQUE2RTtZQUM3RSxrQ0FBa0M7WUFDbENXLGlCQUFpQi9DLFlBQVlVLEtBQUs7WUFFbEMsNERBQTREO1lBQzVELE1BQU1LLGdCQUFnQixDQUFDOzttQkFFVixFQUFFTSxLQUFLMkIsU0FBUyxDQUFDOUMsVUFBVW1DLE1BQU0sQ0FBQ0MsTUFBTSxFQUFFLE1BQU0sR0FBRzs7Ozs7RUFLcEUsQ0FBQztZQUVHekMsY0FBY2tELGdCQUFnQmhDLGVBQWU7WUFDN0NGLGFBQWFrQztZQUViLElBQUdqQixPQUFPO2dCQUNSekIsSUFBSSxDQUFDLDBEQUEwRCxFQUFFMEMsZ0JBQWdCLEVBQUUsUUFBUXJCO1lBQzdGO1FBQ0YsT0FBTyxJQUFHbUIsaUJBQWlCbkQsV0FBV21ELGdCQUFnQjtZQUNwRGhDLGFBQWFnQztZQUNiLElBQUdmLE9BQU87Z0JBQ1J6QixJQUFJLENBQUMsOEJBQThCLEVBQUVRLFlBQVksRUFBRSxRQUFRYTtZQUM3RDtRQUNGLE9BQU87WUFDTCxxRUFBcUU7WUFDckVxQixpQkFBaUIvQyxZQUFZVSxLQUFLO1lBRWxDLCtCQUErQjtZQUMvQixNQUFNSyxnQkFBZ0IsQ0FBQzs7OzJCQUdGLENBQUM7WUFFdEJsQixjQUFja0QsZ0JBQWdCaEMsZUFBZTtZQUM3Q0YsYUFBYWtDO1lBRWIsSUFBR2pCLE9BQU87Z0JBQ1J6QixJQUFJLENBQUMsNENBQTRDLEVBQUUwQyxnQkFBZ0IsRUFBRSxRQUFRckI7WUFDL0UsT0FBTztnQkFDTHJCLElBQUksbUVBQW1FLFFBQVFxQjtZQUNqRjtRQUNGO1FBRUEsTUFBTXVCLGVBQWU3QyxrQkFBa0IsVUFBVTtRQUVqRCxJQUFHLENBQUM2QyxjQUFjO1lBQ2hCNUMsSUFBSSxDQUFDLEVBQUUsRUFBRXVCLFFBQVEscURBQXFELENBQUMsRUFBRSxTQUFTRjtZQUNsRnJCLElBQUksb0RBQW9ELFFBQVFxQjtZQUNoRSxPQUFPO1FBQ1Q7UUFFQSx3QkFBd0I7UUFDeEIsTUFBTXdCLGlCQUFpQjtlQUNqQnJCLE1BQU07Z0JBQUM7YUFBUSxHQUFHLEVBQUU7ZUFDcEJDLFFBQVE7Z0JBQUM7YUFBVSxHQUFHLEVBQUU7WUFDNUI7WUFDQTtTQUNEO1FBRUQsa0JBQWtCO1FBQ2xCLE1BQU1xQixhQUFhdEMsYUFBYTtZQUFDO1lBQVlBO1NBQVcsR0FBRyxFQUFFO1FBRTdELE1BQU11QyxXQUFXLE1BQU0zRCxNQUFNd0QsY0FBYztZQUN6QztlQUNHRTtlQUNBRDtTQUNKLEVBQUU7WUFDRHhDO1lBQ0EyQyxRQUFRO1lBQ1JDLE9BQU87WUFDUEMsT0FBTztRQUNUO1FBRUEsSUFBR0gsU0FBU0ksTUFBTSxFQUFFO1lBQ2xCLHNDQUFzQztZQUN0Q0MsUUFBUXBELEdBQUcsQ0FBQytDLFNBQVNJLE1BQU07WUFDM0IsSUFBR3pCLGVBQWU7Z0JBQ2hCQSxjQUFjcUIsU0FBU0ksTUFBTTtZQUMvQjtRQUNGO1FBRUEsSUFBR0osU0FBU00sTUFBTSxFQUFFO1lBQ2xCLHNDQUFzQztZQUN0Q0QsUUFBUUUsS0FBSyxDQUFDUCxTQUFTTSxNQUFNO1lBQzdCLElBQUczQixlQUFlO2dCQUNoQkEsY0FBY3FCLFNBQVNNLE1BQU07WUFDL0I7UUFDRjtRQUVBLElBQUlFLFdBQWdCO1lBQUNDLFVBQVU7WUFBR0gsUUFBUTtZQUFJRixRQUFRO1FBQUU7UUFDeEQsSUFBRzVDLGVBQWU7WUFDaEJnRCxXQUFXLE1BQU1uRSxNQUFNd0QsY0FBYztnQkFDbkM7bUJBQ0dFO21CQUNBRDthQUNKLEVBQUU7Z0JBQ0R4QztnQkFDQTJDLFFBQVE7Z0JBQ1JDLE9BQU87Z0JBQ1BDLE9BQU87WUFDVDtZQUVBLElBQUdLLFNBQVNKLE1BQU0sRUFBRTtnQkFDbEIsc0NBQXNDO2dCQUN0Q0MsUUFBUXBELEdBQUcsQ0FBQ3VELFNBQVNKLE1BQU07WUFDN0I7WUFFQSxJQUFHSSxTQUFTRixNQUFNLEVBQUU7Z0JBQ2xCLHNDQUFzQztnQkFDdENELFFBQVFFLEtBQUssQ0FBQ0MsU0FBU0YsTUFBTTtZQUMvQjtRQUNGO1FBRUEsZ0NBQWdDO1FBQ2hDLElBQUdYLGtCQUFrQnJELFdBQVdxRCxpQkFBaUI7WUFDL0MsSUFBSTtnQkFDRm5ELFdBQVdtRDtnQkFDWCxJQUFHakIsT0FBTztvQkFDUnpCLElBQUksQ0FBQyxtQ0FBbUMsRUFBRTBDLGdCQUFnQixFQUFFLFFBQVFyQjtnQkFDdEU7WUFDRixFQUFFLE9BQU1pQyxPQUFPO2dCQUNiLGlDQUFpQztnQkFDakMsSUFBRzdCLE9BQU87b0JBQ1J6QixJQUFJLENBQUMsMENBQTBDLEVBQUVzRCxNQUFNRyxPQUFPLEVBQUUsRUFBRSxRQUFRcEM7Z0JBQzVFO1lBQ0Y7UUFDRjtRQUVBLE1BQU1xQyxpQkFBaUJYLFNBQVNNLE1BQU0sRUFBRU0sU0FBUyx3QkFBd0JaLFNBQVNNLE1BQU0sRUFBRU0sU0FBUztRQUNuRyxJQUFHRCxnQkFBZ0I7WUFDakIvQixRQUFRaUMsSUFBSSxDQUFDO1lBQ2I1RCxJQUFJLENBQUMsRUFBRSxFQUFFdUIsUUFBUSx1RkFBdUYsQ0FBQyxFQUFFLFNBQVNGO1lBQ3BILE9BQU87UUFDVDtRQUVBLElBQUcwQixTQUFTUyxRQUFRLEtBQUssS0FBS0QsU0FBU0MsUUFBUSxLQUFLLEdBQUc7WUFDckQ3QixRQUFRa0MsT0FBTyxDQUFDO1lBQ2hCLE9BQU87UUFDVDtRQUVBLE1BQU1DLGVBQ0osQUFBQ2YsQ0FBQUEsU0FBU00sTUFBTSxFQUFFTSxTQUFTLGdDQUFnQ1osU0FBU0ksTUFBTSxFQUFFUSxTQUFTLDRCQUEyQixLQUMvRyxDQUFBLENBQUNwRCxpQkFBaUJnRCxTQUFTRixNQUFNLEVBQUVNLFNBQVMsZ0NBQWdDSixTQUFTSixNQUFNLEVBQUVRLFNBQVMsNEJBQTJCO1FBRXBJLElBQUdHLGNBQWM7WUFDZm5DLFFBQVFrQyxPQUFPLENBQUM7WUFDaEIsT0FBTztRQUNUO1FBQ0FsQyxRQUFRaUMsSUFBSSxDQUFDO1FBQ2I1RCxJQUFJLENBQUMsRUFBRSxFQUFFdUIsUUFBUSx5Q0FBeUMsQ0FBQyxFQUFFLFNBQVNGO1FBQ3RFLE9BQU87SUFDVCxFQUFFLE9BQU1pQyxPQUFPO1FBQ2IzQixRQUFRaUMsSUFBSSxDQUFDO1FBQ2I1RCxJQUFJLENBQUMsRUFBRSxFQUFFdUIsUUFBUSxRQUFRLEVBQUUrQixNQUFNRyxPQUFPLEVBQUUsRUFBRSxTQUFTcEM7UUFDckQsT0FBTztJQUNUO0FBQ0Y7QUFFQSxNQUFNMEMsYUFBYSxPQUNqQjFELEtBQ0EyRCxRQUNBM0M7SUFFQSxNQUFNTSxVQUFVN0IsY0FBY3VCO0lBQzlCTSxRQUFRc0MsS0FBSyxDQUFDO0lBRWQsSUFBSTtRQUNGLE1BQU1DLGVBQWUsSUFBSUM7UUFDekIsTUFBTUMsUUFBUUosT0FBT0ssS0FBSyxDQUFDO1FBQzNCLElBQUlDLGNBQWM7UUFFbEIsS0FBSSxNQUFNQyxRQUFRSCxNQUFPO1lBQ3ZCLElBQUdHLEtBQUtDLEtBQUssQ0FBQyx3Q0FBd0M7Z0JBQ3BERixjQUFjQyxLQUFLRSxJQUFJO2dCQUN2QixJQUFHLENBQUNQLGFBQWFRLEdBQUcsQ0FBQ0osY0FBYztvQkFDakNKLGFBQWFTLEdBQUcsQ0FBQ0wsYUFBYSxFQUFFO2dCQUNsQztZQUNGLE9BQU8sSUFBR0EsZUFBZUMsS0FBS0UsSUFBSSxNQUFNRixLQUFLQyxLQUFLLENBQUMsb0NBQW9DO2dCQUNyRixNQUFNSSxhQUFhVixhQUFhVyxHQUFHLENBQUNQO2dCQUNwQyxJQUFHTSxZQUFZO29CQUNiQSxXQUFXRSxJQUFJLENBQUNQLEtBQUtFLElBQUk7Z0JBQzNCO1lBQ0Y7UUFDRjtRQUVBLElBQUdQLGFBQWFhLElBQUksS0FBSyxHQUFHO1lBQzFCL0UsSUFBSSw0Q0FBNEMsUUFBUXFCO1lBRXhELE1BQU0yRCxXQUFXaEIsT0FBT0ssS0FBSyxDQUFDO1lBRTlCLEtBQUksTUFBTVksV0FBV0QsU0FBVTtnQkFDN0IsSUFBR0MsUUFBUVIsSUFBSSxPQUFPLElBQUk7b0JBQ3hCO2dCQUNGO2dCQUVBLE1BQU1MLFFBQVFhLFFBQVFaLEtBQUssQ0FBQztnQkFDNUIsTUFBTWEsV0FBV2QsS0FBSyxDQUFDLEVBQUUsQ0FBQ0ssSUFBSTtnQkFFOUIsSUFBR1MsU0FBU1YsS0FBSyxDQUFDLHVCQUF1QjtvQkFDdkNOLGFBQWFTLEdBQUcsQ0FBQ08sVUFBVSxFQUFFO29CQUU3QixJQUFJLElBQUlDLElBQUksR0FBR0EsSUFBSWYsTUFBTWhDLE1BQU0sRUFBRStDLElBQUs7d0JBQ3BDLElBQUdmLEtBQUssQ0FBQ2UsRUFBRSxDQUFDVixJQUFJLE9BQU8sSUFBSTs0QkFDekJQLGFBQWFXLEdBQUcsQ0FBQ0ssV0FBV0osS0FBS1YsS0FBSyxDQUFDZSxFQUFFLENBQUNWLElBQUk7d0JBQ2hEO29CQUNGO2dCQUNGO1lBQ0Y7UUFDRjtRQUVBLElBQUdQLGFBQWFhLElBQUksS0FBSyxHQUFHO1lBQzFCL0UsSUFBSSxxQ0FBcUMsUUFBUXFCO1lBRWpELE1BQU0rRCxnQkFBZ0I7WUFDdEIsTUFBTUMsWUFBWXJCLE9BQU9RLEtBQUssQ0FBQ1ksa0JBQWtCLEVBQUU7WUFFbkQsS0FBSSxNQUFNRixZQUFZRyxVQUFXO2dCQUMvQixJQUFHLENBQUNuQixhQUFhUSxHQUFHLENBQUNRLGFBQWE3RixXQUFXNkYsV0FBVztvQkFDdERoQixhQUFhUyxHQUFHLENBQUNPLFVBQVUsRUFBRTtnQkFDL0I7WUFDRjtZQUVBLE1BQU1JLGFBQWE7Z0JBQ2pCM0YsWUFBWVUsS0FBSztnQkFDakJWLFlBQVlVLEtBQUs7Z0JBQ2pCVixZQUFZVSxLQUFLO2dCQUNqQlYsWUFBWVUsS0FBSztnQkFDakJWLFlBQVlVLEtBQUs7YUFDbEI7WUFFRCxLQUFJLE1BQU1rRixRQUFRRCxXQUFZO2dCQUM1QixJQUFHakcsV0FBV2tHLFNBQVMsQ0FBQ3JCLGFBQWFRLEdBQUcsQ0FBQ2EsT0FBTztvQkFDOUNyQixhQUFhUyxHQUFHLENBQUNZLE1BQU0sRUFBRTtnQkFDM0I7WUFDRjtRQUNGO1FBRUEsS0FBSSxNQUFNTCxZQUFZaEIsYUFBYS9CLElBQUksR0FBSTtZQUN6QyxJQUFHLENBQUM5QyxXQUFXNkYsV0FBVztnQkFDeEJsRixJQUFJLENBQUMsZ0JBQWdCLEVBQUVrRixVQUFVLEVBQUUsUUFBUTdEO2dCQUMzQztZQUNGO1lBRUFyQixJQUFJLENBQUMsaUJBQWlCLEVBQUVrRixVQUFVLEVBQUUsUUFBUTdEO1lBRTVDLE1BQU1tRSxjQUFjM0YsVUFBVW1DLE1BQU0sQ0FBQ3lELEVBQUUsRUFBRUMsYUFBYSxZQUFZdEYsUUFBUWtDLEdBQUcsQ0FBQ3FELFVBQVUsS0FBSztZQUU3RixJQUFHSCxhQUFhO2dCQUNkLElBQUk7b0JBQ0YsTUFBTUksU0FBUyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7d0VBd0U4QyxDQUFDO29CQUUvRCxJQUFJO3dCQUNGLE1BQU1DLGFBQWFsRyxZQUFZVSxLQUFLO3dCQUNwQ2IsY0FBY3FHLFlBQVlELFFBQVE7d0JBRWxDLGlDQUFpQzt3QkFDakMsTUFBTXhHLE1BQU0sVUFBVTs0QkFBQzs0QkFBUTs0QkFBVThGOzRCQUFVOzRCQUFpQlc7eUJBQVcsRUFBRTs0QkFDL0V4Rjs0QkFDQTJDLFFBQVE7NEJBQ1JFLE9BQU87d0JBQ1Q7d0JBRUEsSUFBSTs0QkFDRjNELFdBQVdzRzt3QkFDYixFQUFFLE9BQU0xRSxRQUFRLENBQ2hCO3dCQUVBbkIsSUFBSSxDQUFDLDJCQUEyQixFQUFFa0YsVUFBVSxFQUFFLFFBQVE3RDtvQkFDeEQsRUFBRSxPQUFLO3dCQUNMLE1BQU15RSxjQUFjLE1BQU1DLGlCQUFpQmIsVUFBVTdEO3dCQUNyRCxJQUFHeUUsYUFBYTs0QkFDZDlGLElBQUksQ0FBQyx3QkFBd0IsRUFBRWtGLFVBQVUsRUFBRSxRQUFRN0Q7d0JBQ3JEO29CQUNGO2dCQUNGLEVBQUUsT0FBTWlDLE9BQU87b0JBQ2J0RCxJQUFJLENBQUMsdUJBQXVCLEVBQUVzRCxNQUFNRyxPQUFPLEVBQUUsRUFBRSxTQUFTcEM7b0JBQ3hELE1BQU0wRSxpQkFBaUJiLFVBQVU3RDtnQkFDbkM7WUFDRixPQUFPO2dCQUNMLE1BQU15RSxjQUFjLE1BQU1DLGlCQUFpQmIsVUFBVTdEO2dCQUNyRCxJQUFHeUUsYUFBYTtvQkFDZDlGLElBQUksQ0FBQyx3QkFBd0IsRUFBRWtGLFVBQVUsRUFBRSxRQUFRN0Q7Z0JBQ3JEO2dCQUVBLE1BQU0yRSxhQUFhOUIsYUFBYVcsR0FBRyxDQUFDSyxhQUFhLEVBQUU7Z0JBQ25ELElBQUdjLFdBQVc1RCxNQUFNLEdBQUcsR0FBRztvQkFDeEIsSUFBSTt3QkFDRixNQUFNLEVBQUM2RCxhQUFhLEVBQUMsR0FBRyxNQUFNLE1BQU0sQ0FBQzt3QkFFckMsTUFBTUMsY0FBYzVHLGFBQWE0RixVQUFVO3dCQUUzQyxNQUFNVSxTQUFTLENBQUM7QUFDNUIsRUFBRUksV0FBV0csSUFBSSxDQUFDLE1BQU07Ozs7QUFJeEIsRUFBRUQsWUFBWTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozt1RUEyRnlELENBQUM7d0JBRTVELE1BQU1FLGVBQWUsTUFBTUgsY0FBY0wsUUFBUXZFO3dCQUVqRCxJQUFHK0UsZ0JBQWdCQSxpQkFBaUJGLGFBQWE7NEJBQy9DMUcsY0FBYzBGLFVBQVVrQixjQUFjOzRCQUN0Q3BHLElBQUksQ0FBQyxvQkFBb0IsRUFBRWtGLFVBQVUsRUFBRSxRQUFRN0Q7d0JBQ2pEO29CQUNGLEVBQUUsT0FBTWlDLE9BQU87d0JBQ2J0RCxJQUFJLENBQUMsMkJBQTJCLEVBQUVrRixTQUFTLEVBQUUsRUFBRTVCLE1BQU1HLE9BQU8sRUFBRSxFQUFFLFNBQVNwQztvQkFDM0U7Z0JBQ0Y7WUFDRjtRQUNGO1FBRUFNLFFBQVFrQyxPQUFPLENBQUM7SUFDbEIsRUFBRSxPQUFNUCxPQUFPO1FBQ2IzQixRQUFRaUMsSUFBSSxDQUFDO1FBQ2I1RCxJQUFJLENBQUMsT0FBTyxFQUFFc0QsTUFBTUcsT0FBTyxFQUFFLEVBQUUsU0FBU3BDO1FBQ3hDLElBQUcsQ0FBQ0EsT0FBTztZQUNUK0IsUUFBUUUsS0FBSyxDQUFDQTtRQUNoQjtJQUNGO0FBQ0Y7QUFFQSxNQUFNeUMsbUJBQW1CLE9BQU9iLFVBQWtCN0Q7SUFDaEQsSUFBSXlFLGNBQWM7SUFFbEIsSUFBSTtRQUNGLE1BQU1JLGNBQWM1RyxhQUFhNEYsVUFBVTtRQUMzQyxJQUFJbUIsYUFBYUg7UUFFakIsSUFBR2hCLFNBQVN2QixRQUFRLENBQUMsaUJBQWlCO1lBQ3BDM0QsSUFBSSxpQ0FBaUMsUUFBUXFCO1lBRTdDZ0YsYUFBYUEsV0FBV0MsT0FBTyxDQUM3QixvRUFDQTtZQUdGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLHlDQUNBO1lBR0ZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsOEJBQ0E7WUFFRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3Qiw0QkFDQTtZQUdGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLDJDQUNBO1lBR0ZELGFBQWFBLFdBQVdDLE9BQU8sQ0FBQyxtQkFBbUI7WUFFbkQsSUFBRyxDQUFDRCxXQUFXMUMsUUFBUSxDQUFDLG1CQUFtQjBDLFdBQVcxQyxRQUFRLENBQUMsU0FBUztnQkFDdEUwQyxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLGlDQUNBO1lBRUo7UUFDRjtRQUVBLElBQUdwQixTQUFTdkIsUUFBUSxDQUFDLGlCQUFpQjtZQUNwQzNELElBQUksbURBQW1ELFFBQVFxQjtZQUUvRGdGLGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsMEJBQ0E7WUFHRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUFDLFlBQVk7UUFDOUM7UUFFQSxJQUFHcEIsU0FBU3ZCLFFBQVEsQ0FBQyxpQkFBaUI7WUFDcEMzRCxJQUFJLGlDQUFpQyxRQUFRcUI7WUFFN0NnRixhQUFhQSxXQUFXQyxPQUFPLENBQUMsY0FBYztZQUU5Q0QsYUFBYUEsV0FBV0MsT0FBTyxDQUFDLFNBQVM7WUFDekNELGFBQWFBLFdBQVdDLE9BQU8sQ0FBQyxTQUFTO1lBQ3pDRCxhQUFhQSxXQUFXQyxPQUFPLENBQUMsU0FBUztZQUN6Q0QsYUFBYUEsV0FBV0MsT0FBTyxDQUFDLFFBQVE7UUFDMUM7UUFFQSxJQUFHcEIsU0FBU3ZCLFFBQVEsQ0FBQyxXQUFXO1lBQzlCM0QsSUFBSSwyQkFBMkIsUUFBUXFCO1lBRXZDZ0YsYUFBYUEsV0FBV0MsT0FBTyxDQUFDLG1CQUFtQjtZQUVuRCxJQUFHLENBQUNELFdBQVcxQyxRQUFRLENBQUMsbUJBQW1CMEMsV0FBVzFDLFFBQVEsQ0FBQyxTQUFTO2dCQUN0RTBDLGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsOEJBQ0E7WUFFSjtZQUVBRCxhQUFhQSxXQUFXQyxPQUFPLENBQUMsU0FBUztRQUMzQztRQUVBLElBQUdwQixTQUFTdkIsUUFBUSxDQUFDLGVBQWU7WUFDbEMzRCxJQUFJLCtCQUErQixRQUFRcUI7WUFFM0NnRixhQUFhQSxXQUFXQyxPQUFPLENBQzdCLHFFQUNBO1lBR0ZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsZUFDQTtZQUVGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLGNBQ0E7WUFHRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3QixpRkFDQTtZQUdGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLG9DQUNBO1lBRUZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsMENBQ0E7WUFFRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3Qix5Q0FDQTtZQUVGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLG1EQUNBO1lBRUZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsNEJBQ0E7WUFHRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3QixxREFDQTtZQUdGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLDhDQUNBO1lBR0ZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0Isd0RBQ0E7WUFFRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3QixtQ0FDQTtZQUVGRCxhQUFhQSxXQUFXQyxPQUFPLENBQzdCLDJDQUNBO1lBR0ZELGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsNEdBQ0E7WUFHRkQsYUFBYUEsV0FBV0MsT0FBTyxDQUM3QixvQkFDQTtRQUVKO1FBRUEsSUFBR0QsZUFBZUgsYUFBYTtZQUM3QjFHLGNBQWMwRixVQUFVbUIsWUFBWTtZQUNwQ3JHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRWtGLFVBQVUsRUFBRSxRQUFRN0Q7WUFDM0N5RSxjQUFjO1FBQ2hCO1FBRUEsT0FBT0E7SUFDVCxFQUFFLE9BQU14QyxPQUFPO1FBQ2J0RCxJQUFJLENBQUMsK0JBQStCLEVBQUVrRixTQUFTLEVBQUUsRUFBRTVCLE1BQU1HLE9BQU8sRUFBRSxFQUFFLFNBQVNwQztRQUM3RSxPQUFPO0lBQ1Q7QUFDRjtBQUVBLE1BQU1rRixlQUFlLE9BQU9sRyxLQUFhZ0IsT0FBZ0JJLFFBQWlCLEtBQUs7SUFDN0UsTUFBTStFLGdCQUFnQjtRQUFDO1FBQU07UUFBTztRQUFPO1FBQU07S0FBTztJQUN4RCxNQUFNQyxpQkFBaUI7SUFDdkIsSUFBSWpFLGdCQUFnQjtJQUVwQixLQUFJLE1BQU1rRSxVQUFVRixjQUFlO1FBQ2pDLE1BQU1HLGdCQUFnQmhILFlBQVlVLEtBQUssQ0FBQyxFQUFFLEVBQUVvRyxlQUFlLENBQUMsRUFBRUMsUUFBUTtRQUN0RSxJQUFHckgsV0FBV3NILGdCQUFnQjtZQUM1Qm5FLGdCQUFnQm1FO1lBQ2hCO1FBQ0Y7SUFDRjtJQUVBLElBQUduRSxlQUFlO1FBQ2hCLElBQUk7WUFDRiwwRUFBMEU7WUFDMUUsTUFBTWtFLFNBQVM5RyxRQUFRNEMsZUFBZW9FLEtBQUssQ0FBQztZQUM1QyxJQUFJQyxhQUFhckU7WUFFakIsbUNBQW1DO1lBQ25DLElBQUdrRSxXQUFXLE9BQU87Z0JBQ25CLElBQUk7b0JBQ0YsTUFBTUksTUFBTSxJQUFJQyxJQUFJLENBQUMsT0FBTyxFQUFFdkUsZUFBZTtvQkFDN0NxRSxhQUFhQyxJQUFJRSxJQUFJO29CQUNyQixJQUFHdkYsT0FBTzt3QkFDUnpCLElBQUksQ0FBQyxpQ0FBaUMsRUFBRTZHLFlBQVksRUFBRSxRQUFReEY7b0JBQ2hFO2dCQUNGLEVBQUUsT0FBTTRGLFVBQVU7b0JBQ2hCakgsSUFBSSxDQUFDLG1DQUFtQyxFQUFFaUgsU0FBU3hELE9BQU8sRUFBRSxFQUFFLFFBQVFoQyxTQUFTLENBQUNKO29CQUNoRndGLGFBQWEsQ0FBQyxPQUFPLEVBQUVyRSxlQUFlO2dCQUN4QztZQUNGO1lBRUEsSUFBR2YsT0FBTztnQkFDUnpCLElBQUksQ0FBQyw2QkFBNkIsRUFBRTZHLFdBQVcsVUFBVSxFQUFFSCxPQUFPLENBQUMsQ0FBQyxFQUFFLFFBQVFyRjtZQUNoRjtZQUVBLElBQUk2RjtZQUNKLElBQUk7Z0JBQ0ZBLFlBQVksTUFBTSxNQUFNLENBQUNMO1lBQzNCLEVBQUUsT0FBTU0sYUFBYTtnQkFDbkIsSUFBR0EsWUFBWTFELE9BQU8sQ0FBQ0UsUUFBUSxDQUFDLG1DQUFtQztvQkFDakUzRCxJQUFJLENBQUMsMEJBQTBCLEVBQUV3QyxjQUFjLDhEQUE4RCxDQUFDLEVBQUUsU0FBU25CO29CQUN6SCxJQUFHSSxPQUFPO3dCQUNSMkIsUUFBUUUsS0FBSyxDQUFDNkQ7b0JBQ2hCO29CQUNBO2dCQUNGO2dCQUNBLE1BQU1BO1lBQ1I7WUFFQSxpRUFBaUU7WUFDakUsSUFBSUMsYUFBYTtZQUNqQixJQUFHRixVQUFVRyxPQUFPLEVBQUU7Z0JBQ3BCRCxhQUFhRixVQUFVRyxPQUFPO2dCQUM5QixJQUFHNUYsT0FBTztvQkFDUnpCLElBQUksQ0FBQyx3QkFBd0IsRUFBRXdDLGVBQWUsRUFBRSxRQUFRbkI7Z0JBQzFEO1lBQ0YsT0FBTztnQkFDTCx1Q0FBdUM7Z0JBQ3ZDK0YsYUFBYUY7Z0JBQ2IsSUFBR3pGLE9BQU87b0JBQ1J6QixJQUFJLENBQUMsdUJBQXVCLEVBQUV3QyxlQUFlLEVBQUUsUUFBUW5CO2dCQUN6RDtZQUNGO1lBRUEsSUFBRytGLGNBQWNBLFdBQVczQixFQUFFLEVBQUU7Z0JBQzlCekYsSUFBSSxDQUFDLDBCQUEwQixFQUFFTCxZQUFZVSxLQUFLbUMsZUFBZSxzQkFBc0IsQ0FBQyxFQUFFLFFBQVFuQjtnQkFDbEd4QixVQUFVbUMsTUFBTSxDQUFDeUQsRUFBRSxHQUFHO29CQUFDLEdBQUc1RixVQUFVbUMsTUFBTSxDQUFDeUQsRUFBRTtvQkFBRSxHQUFHMkIsV0FBVzNCLEVBQUU7Z0JBQUE7WUFDakU7UUFDRixFQUFFLE9BQU1uQyxPQUFPO1lBQ2J0RCxJQUFJLENBQUMsb0NBQW9DLEVBQUV3QyxjQUFjLEVBQUUsRUFBRWMsTUFBTUcsT0FBTyxFQUFFLEVBQUUsUUFBUXBDO1lBQ3RGLElBQUdJLE9BQU87Z0JBQ1IyQixRQUFRRSxLQUFLLENBQUNBO1lBQ2hCO1FBQ0Y7SUFDRjtBQUNGO0FBRUE7O0NBRUMsR0FDRCxNQUFNZ0UsbUJBQW1CLE9BQU9qSCxLQUFhZ0IsT0FBZ0JJO0lBQzNELDZEQUE2RDtJQUM3RCxJQUFHNUIsVUFBVW1DLE1BQU0sQ0FBQ0MsTUFBTSxJQUFJQyxPQUFPQyxJQUFJLENBQUN0QyxVQUFVbUMsTUFBTSxDQUFDQyxNQUFNLEVBQUVHLE1BQU0sR0FBRyxHQUFHO1FBQzdFcEMsSUFBSSxtREFBbUQsUUFBUXlCLFNBQVMsQ0FBQ0o7UUFDekUsT0FBTztJQUNUO0lBRUEsNERBQTREO0lBQzVELE1BQU1tRixnQkFBZ0I7UUFBQztRQUFNO1FBQU87UUFBTztRQUFNO0tBQU87SUFDeEQsTUFBTUMsaUJBQWlCO0lBRXZCLEtBQUksTUFBTUMsVUFBVUYsY0FBZTtRQUNqQyxNQUFNRyxnQkFBZ0JoSCxZQUFZVSxLQUFLLENBQUMsRUFBRSxFQUFFb0csZUFBZSxDQUFDLEVBQUVDLFFBQVE7UUFDdEUsSUFBR3JILFdBQVdzSCxnQkFBZ0I7WUFDNUIsSUFBSTtnQkFDRiwwRUFBMEU7Z0JBQzFFLE1BQU1ZLGFBQWEzSCxRQUFRK0csZUFBZUMsS0FBSyxDQUFDO2dCQUNoRCxJQUFJQyxhQUFhRjtnQkFFakIsbUNBQW1DO2dCQUNuQyxJQUFHWSxlQUFlLE9BQU87b0JBQ3ZCLElBQUk7d0JBQ0YsTUFBTVQsTUFBTSxJQUFJQyxJQUFJLENBQUMsT0FBTyxFQUFFSixlQUFlO3dCQUM3Q0UsYUFBYUMsSUFBSUUsSUFBSTt3QkFDckIsSUFBR3ZGLE9BQU87NEJBQ1J6QixJQUFJLENBQUMsaUNBQWlDLEVBQUU2RyxZQUFZLEVBQUUsUUFBUXhGO3dCQUNoRTtvQkFDRixFQUFFLE9BQU00RixVQUFVO3dCQUNoQmpILElBQUksQ0FBQyxtQ0FBbUMsRUFBRWlILFNBQVN4RCxPQUFPLEVBQUUsRUFBRSxRQUFRaEMsU0FBUyxDQUFDSjt3QkFDaEZ3RixhQUFhLENBQUMsT0FBTyxFQUFFRixlQUFlO29CQUN4QztnQkFDRjtnQkFFQSxJQUFHbEYsT0FBTztvQkFDUnpCLElBQUksQ0FBQyw2QkFBNkIsRUFBRTZHLFdBQVcsVUFBVSxFQUFFVSxXQUFXLENBQUMsQ0FBQyxFQUFFLFFBQVFsRztnQkFDcEY7Z0JBRUEsSUFBSTZGO2dCQUNKLElBQUk7b0JBQ0ZBLFlBQVksTUFBTSxNQUFNLENBQUNMO2dCQUMzQixFQUFFLE9BQU1NLGFBQWE7b0JBQ25CLElBQUdBLFlBQVkxRCxPQUFPLENBQUNFLFFBQVEsQ0FBQyxtQ0FBbUM7d0JBQ2pFM0QsSUFBSSxDQUFDLDBCQUEwQixFQUFFMkcsY0FBYyw4REFBOEQsQ0FBQyxFQUFFLFNBQVN0Rjt3QkFDekgsSUFBR0ksT0FBTzs0QkFDUjJCLFFBQVFFLEtBQUssQ0FBQzZEO3dCQUNoQjt3QkFDQTtvQkFDRjtvQkFDQSxNQUFNQTtnQkFDUjtnQkFFQSxpRUFBaUU7Z0JBQ2pFLElBQUlDLGFBQWE7Z0JBQ2pCLElBQUdGLFVBQVVHLE9BQU8sRUFBRTtvQkFDcEJELGFBQWFGLFVBQVVHLE9BQU87b0JBQzlCLElBQUc1RixPQUFPO3dCQUNSekIsSUFBSSxDQUFDLHdCQUF3QixFQUFFMkcsZUFBZSxFQUFFLFFBQVF0RjtvQkFDMUQ7Z0JBQ0YsT0FBTztvQkFDTCx1Q0FBdUM7b0JBQ3ZDK0YsYUFBYUY7b0JBQ2IsSUFBR3pGLE9BQU87d0JBQ1J6QixJQUFJLENBQUMsdUJBQXVCLEVBQUUyRyxlQUFlLEVBQUUsUUFBUXRGO29CQUN6RDtnQkFDRjtnQkFFQSxJQUFHK0YsY0FBY0EsV0FBV25GLE1BQU0sSUFBSUMsT0FBT0MsSUFBSSxDQUFDaUYsV0FBV25GLE1BQU0sRUFBRUcsTUFBTSxHQUFHLEdBQUc7b0JBQy9FcEMsSUFBSSxDQUFDLDhCQUE4QixFQUFFTCxZQUFZVSxLQUFLc0csZUFBZSxzQkFBc0IsQ0FBQyxFQUFFLFFBQVFsRixTQUFTLENBQUNKO29CQUNoSHhCLFVBQVVtQyxNQUFNLENBQUNDLE1BQU0sR0FBRzt3QkFBQyxHQUFHcEMsVUFBVW1DLE1BQU0sQ0FBQ0MsTUFBTTt3QkFBRSxHQUFHbUYsV0FBV25GLE1BQU07b0JBQUE7b0JBQzNFLE9BQU87Z0JBQ1Q7WUFDRixFQUFFLE9BQU1xQixPQUFPO2dCQUNidEQsSUFBSSxDQUFDLHdDQUF3QyxFQUFFMkcsY0FBYyxFQUFFLEVBQUVyRCxNQUFNRyxPQUFPLEVBQUUsRUFBRSxRQUFRcEM7Z0JBQzFGLElBQUdJLE9BQU87b0JBQ1IyQixRQUFRRSxLQUFLLENBQUNBO2dCQUNoQjtZQUNGO1FBQ0Y7SUFDRjtJQUVBLE9BQU87QUFDVDtBQUVBLE1BQU1rRSxxQkFBcUIsQ0FBQ3RDLFVBQWtCN0Q7SUFDNUMsSUFBSTtRQUNGLE1BQU02RSxjQUFjNUcsYUFBYTRGLFVBQVU7UUFFM0MsSUFBR2dCLFlBQVk5RCxNQUFNLEdBQUcsU0FBUztZQUMvQnBDLElBQUksQ0FBQyx5Q0FBeUMsRUFBRWtGLFVBQVUsRUFBRSxRQUFRN0Q7WUFDcEUsT0FBTztRQUNUO1FBQ0EsaURBQWlEO1FBQ2pELGFBQWE7UUFDYiw2Q0FBNkM7UUFDN0Msa0NBQWtDO1FBQ2xDLDZDQUE2QztRQUU3Qyx3RUFBd0U7UUFDeEUsSUFBSWdGLGFBQWFILFlBQVlJLE9BQU8sQ0FDbEMscUJBQ0EsQ0FBQzlCO1lBQ0MsSUFBR0EsTUFBTWIsUUFBUSxDQUFDLGdCQUNoQmEsTUFBTWIsUUFBUSxDQUFDLGNBQ2ZhLE1BQU1iLFFBQVEsQ0FBQyxjQUNmYSxNQUFNYixRQUFRLENBQUMsWUFBWTtnQkFDM0IsT0FBT2E7WUFDVDtZQUNBLE9BQU87UUFDVDtRQUdGLCtDQUErQztRQUMvQzZCLGFBQWFBLFdBQVdDLE9BQU8sQ0FDN0IsYUFDQSxDQUFDOUI7WUFDQyxJQUFHQSxNQUFNYixRQUFRLENBQUMsV0FBV2EsTUFBTWIsUUFBUSxDQUFDLFVBQVU7Z0JBQ3BELE9BQU9hO1lBQ1Q7WUFDQSxPQUFPO1FBQ1Q7UUFHRiwrREFBK0Q7UUFDL0Q2QixhQUFhQSxXQUFXQyxPQUFPLENBQUMsaUJBQWlCO1FBRWpELG9DQUFvQztRQUNwQyxJQUFHRCxlQUFlSCxhQUFhO1lBQzdCMUcsY0FBYzBGLFVBQVVtQixZQUFZO1lBQ3BDckcsSUFBSSxDQUFDLHNCQUFzQixFQUFFa0YsVUFBVSxFQUFFLFFBQVE3RDtZQUNqRCxPQUFPO1FBQ1Q7UUFFQSxPQUFPO0lBQ1QsRUFBRSxPQUFNaUMsT0FBTztRQUNidEQsSUFBSSxDQUFDLDZCQUE2QixFQUFFa0YsU0FBUyxFQUFFLEVBQUU1QixNQUFNRyxPQUFPLEVBQUUsRUFBRSxTQUFTcEM7UUFDM0UsT0FBTztJQUNUO0FBQ0Y7QUFFQSxPQUFPLE1BQU1vRyxPQUFPLE9BQU9DLEtBQWtEQyxXQUF5QnZILFFBQVF3SCxJQUFJO0lBQ2hILE1BQU0sRUFDSnJHLFVBQVUsS0FBSyxFQUNmQyxNQUFNLEtBQUssRUFDWEMsUUFBUSxLQUFLLEVBQ2JKLFFBQVEsS0FBSyxFQUNiVyxTQUFTLElBQUksRUFDYjZGLGlCQUFpQixLQUFLLEVBQ3RCLG1CQUFtQkMscUJBQXFCLEtBQUssRUFDOUMsR0FBR0o7SUFFSixNQUFNSyx1QkFBdUJGLGtCQUFrQkM7SUFFL0M5SCxJQUFJLEdBQUd1QixRQUFRLFdBQVcsQ0FBQyxFQUFFLFFBQVFGO0lBRXJDLE1BQU1oQixNQUFNRCxRQUFRQyxHQUFHO0lBQ3ZCLE1BQU1zQixVQUFVN0IsY0FBY3VCO0lBRTlCLE1BQU1rRixhQUFhbEcsS0FBS2dCLE9BQU9JO0lBRS9CLElBQUlpQixpQkFBZ0M7SUFFcEMsSUFBSTtRQUNGLE1BQU1uQyxnQkFBZ0JJLGlCQUFpQk47UUFDdkNMLElBQUksQ0FBQyxXQUFXLEVBQUVPLGdCQUFnQixhQUFhLGVBQWUsbUJBQW1CLENBQUMsRUFBRSxRQUFRYztRQUU1RixJQUFHZCxlQUFlO1lBQ2hCVixVQUFVbUkseUJBQXlCO1FBQ3JDO1FBRUFwSCxpQkFBaUJQO1FBRWpCLE1BQU1lLG9CQUFvQmYsS0FBS0UsZUFBZWM7UUFFOUMsTUFBTU8sb0JBQW9CakMsWUFBWVUsS0FBSztRQUMzQyxNQUFNd0Isc0JBQXNCbEMsWUFBWVUsS0FBSztRQUM3QyxNQUFNNEgsa0JBQWtCNUksV0FBV3VDLHNCQUNqQ3ZDLFdBQVd3Qyx3QkFDWHhDLFdBQVdNLFlBQVlVLEtBQUssb0JBQzVCaEIsV0FBV00sWUFBWVUsS0FBSyxzQkFDNUJoQixXQUFXTSxZQUFZVSxLQUFLLHFCQUM1QmhCLFdBQVdNLFlBQVlVLEtBQUssc0JBQzVCaEIsV0FBV00sWUFBWVUsS0FBSztRQUU5QixNQUFNNkgscUJBQXFCLE1BQU1aLGlCQUFpQmpILEtBQUtnQixPQUFPSTtRQUU5RCxJQUFHeUcsb0JBQW9CO1lBQ3JCbEksSUFBSSxxREFBcUQsUUFBUXFCO1FBQ25FO1FBRUEsSUFBR2hDLFdBQVdNLFlBQVlVLEtBQUssb0JBQW9CO1lBQ2pEZCxXQUFXSSxZQUFZVSxLQUFLO1FBQzlCO1FBRUEsSUFBSW1DLGdCQUFnQjtRQUNwQixJQUFJMkYseUJBQXlCO1FBRTdCLElBQUcsQ0FBQ0YsbUJBQW1CLENBQUNDLG9CQUFvQjtZQUMxQyxNQUFNN0YsZ0JBQWdCO2dCQUNwQjFDLFlBQVlPLGdCQUFnQjtnQkFDNUJQLFlBQVlPLGdCQUFnQjtnQkFDNUJQLFlBQVlTLFFBQVFrQyxHQUFHLENBQUNDLFFBQVEsSUFBSSw2QkFBNkI7Z0JBQ2pFNUMsWUFBWVMsUUFBUWtDLEdBQUcsQ0FBQ0MsUUFBUSxJQUFJLDZCQUE2QjthQUNsRTtZQUVELEtBQUksTUFBTUUsUUFBUUosY0FBZTtnQkFDL0IsSUFBR2hELFdBQVdvRCxPQUFPO29CQUNuQkQsZ0JBQWdCQztvQkFDaEI7Z0JBQ0Y7WUFDRjtZQUVBLElBQUdoQixPQUFPO2dCQUNSekIsSUFBSSxDQUFDLG1CQUFtQixFQUFFRSxnQkFBZ0IsRUFBRSxRQUFRbUI7Z0JBQ3BEckIsSUFBSSxDQUFDLHFCQUFxQixFQUFFNEIsbUJBQW1CLEVBQUUsUUFBUVA7Z0JBQ3pEckIsSUFBSSxDQUFDLHVCQUF1QixFQUFFaUksaUJBQWlCLEVBQUUsUUFBUTVHO2dCQUN6RHJCLElBQUksQ0FBQyxrQkFBa0IsRUFBRXdDLGVBQWUsRUFBRSxRQUFRbkI7Z0JBQ2xEckIsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQ3dDLGlCQUFpQm5ELFdBQVdtRCxnQkFBZ0IsRUFBRSxRQUFRbkI7WUFDcEY7WUFFQSxJQUFHbUIsaUJBQWlCbkQsV0FBV21ELGdCQUFnQjtnQkFDN0N4QyxJQUFJLGlGQUFpRixRQUFRcUI7WUFDL0YsT0FBTztnQkFDTDhHLHlCQUF5QjtZQUMzQjtRQUNGO1FBRUEsSUFBR25HLFFBQVE7WUFDVCxNQUFNb0csaUJBQWlCekksWUFBWVUsS0FBSzJCO1lBQ3hDLElBQUczQyxXQUFXK0ksaUJBQWlCO2dCQUM3QnBJLElBQUksQ0FBQyxzQ0FBc0MsRUFBRWdDLFFBQVEsRUFBRSxRQUFRWDtnQkFDL0Q4Ryx5QkFBeUI7WUFDM0IsT0FBTztnQkFDTG5JLElBQUksQ0FBQywwQ0FBMEMsRUFBRWdDLE9BQU8sb0NBQW9DLENBQUMsRUFBRSxRQUFRWDtZQUN6RztRQUNGO1FBRUEsSUFBRzhHLHdCQUF3QjtZQUN6Qm5JLElBQUksd0VBQXdFLFFBQVFxQjtZQUNwRixNQUFNZ0gsZUFBZS9ILDBCQUEwQkMsZUFBZUY7WUFDOURxQyxpQkFBaUIyRixhQUFhN0gsVUFBVTtRQUMxQztRQUVBLElBQUk4SCxlQUFlO1FBQ25CLE1BQU01RyxnQkFBZ0IsQ0FBQzZHO1lBQ3JCRCxnQkFBZ0IsR0FBR0MsT0FBTyxFQUFFLENBQUM7UUFDL0I7UUFFQSxNQUFNQyxTQUFTLE1BQU1sSCxpQkFBaUJqQixLQUFLZ0IsT0FBT0UsU0FBUyxNQUFNRSxPQUFPbEIsZUFBZW1CO1FBRXZGLElBQUdxRyxzQkFBc0I7WUFDdkJwRyxRQUFRc0MsS0FBSyxDQUFDO1lBRWQsTUFBTXdFLE9BQU8sTUFBTSxNQUFNLENBQUM7WUFDMUIsTUFBTUMsUUFBUUQsS0FBS0UsSUFBSSxDQUFDLGtDQUFrQztnQkFDeER0STtnQkFDQXVJLFFBQVE7b0JBQUM7b0JBQXNCO29CQUFhO29CQUFjO2lCQUFjO1lBQzFFO1lBRUEsSUFBSUMsaUJBQWlCO1lBQ3JCLEtBQUksTUFBTXRELFFBQVFtRCxNQUFPO2dCQUN2QixNQUFNeEQsV0FBV3ZGLFlBQVlVLEtBQUtrRjtnQkFDbEMsSUFBR2lDLG1CQUFtQnRDLFVBQVU3RCxRQUFRO29CQUN0Q3dIO2dCQUNGO1lBQ0Y7WUFFQWxILFFBQVFrQyxPQUFPLENBQUMsQ0FBQyxzQkFBc0IsRUFBRWdGLGVBQWUsTUFBTSxDQUFDO1FBQ2pFO1FBRUEsSUFBR0wsV0FBVyxLQUFLaEgsS0FBSztZQUN0QixNQUFNc0gsZUFBZWpKLFVBQVVtQyxNQUFNLENBQUN5RCxFQUFFLEVBQUVDLFlBQVk3RixVQUFVbUMsTUFBTSxDQUFDeUQsRUFBRSxDQUFDQyxRQUFRLEtBQUs7WUFFdkYsSUFBR29ELGNBQWM7Z0JBQ2Y5SSxJQUFJLDRDQUE0QyxRQUFRcUI7Z0JBQ3hELE1BQU0wQyxXQUFXMUQsS0FBS2lJLGNBQWNqSDtnQkFFcEMsTUFBTTBILGlCQUFpQixNQUFNekgsaUJBQWlCakIsS0FBS2dCLE9BQU9FLFNBQVMsT0FBT0UsT0FBT2xCO2dCQUVqRm9ILFNBQVNvQjtnQkFDVCxPQUFPQTtZQUNUO1lBQ0EvSSxJQUFJLGtEQUFrRCxRQUFRcUI7WUFDOURyQixJQUFJLDZFQUE2RSxRQUFRcUI7WUFDekZyQixJQUFJLENBQUM7Ozs7Ozs7O0VBUVQsQ0FBQyxFQUFFLFFBQVFxQjtRQUNUO1FBRUFzRyxTQUFTYTtRQUNULE9BQU9BO0lBQ1QsRUFBRSxPQUFNbEYsT0FBTztRQUNidEQsSUFBSSxDQUFDLEVBQUUsRUFBRXVCLFFBQVEsUUFBUSxFQUFFK0IsTUFBTUcsT0FBTyxFQUFFLEVBQUUsU0FBU3BDO1FBQ3JELElBQUdNLFNBQVM7WUFDVkEsUUFBUWlDLElBQUksQ0FBQztRQUNmO1FBQ0ErRCxTQUFTO1FBQ1QsT0FBTztJQUNULFNBQVU7UUFDUixNQUFNcUIsZ0JBQWdCO1lBQ3BCdEc7WUFDQS9DLFlBQVlVLEtBQUs7WUFDakJWLFlBQVlVLEtBQUs7U0FDbEI7UUFFRCxLQUFJLE1BQU02RSxZQUFZOEQsY0FBZTtZQUNuQyxJQUFHOUQsWUFBWTdGLFdBQVc2RixXQUFXO2dCQUNuQyxJQUFJO29CQUNGM0YsV0FBVzJGO29CQUNYLElBQUd6RCxPQUFPO3dCQUNSekIsSUFBSSxDQUFDLHNDQUFzQyxFQUFFa0YsVUFBVSxFQUFFLFFBQVE3RDtvQkFDbkU7Z0JBQ0YsRUFBRSxPQUFLLENBQ1A7WUFDRjtRQUNGO0lBQ0Y7QUFDRixFQUFFIn0=
|