UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

301 lines 47.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const os = require("os"); const path = require("path"); const cxapi = require("@aws-cdk/cx-api"); const fs = require("fs-extra"); const init_1 = require("../lib/init"); describe('constructs version', () => { cliTest('create a TypeScript library project', async (workDir) => { await (0, init_1.cliInit)({ type: 'lib', language: 'typescript', workDir, }); // Check that package.json and lib/ got created in the current directory expect(await fs.pathExists(path.join(workDir, 'package.json'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, 'lib'))).toBeTruthy(); }); cliTest('asking for a nonexistent template fails', async (workDir) => { await expect((0, init_1.cliInit)({ type: 'banana', language: 'typescript', workDir, })).rejects.toThrow(/Unknown init template/); }); cliTest('asking for a template but no language prints and throws', async (workDir) => { await expect((0, init_1.cliInit)({ type: 'app', workDir, })).rejects.toThrow(/No language/); }); cliTest('create a TypeScript app project', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'typescript', workDir, }); // Check that package.json and bin/ got created in the current directory expect(await fs.pathExists(path.join(workDir, 'package.json'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, 'bin'))).toBeTruthy(); }); cliTest('create a JavaScript app project', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'javascript', workDir, }); // Check that package.json and bin/ got created in the current directory expect(await fs.pathExists(path.join(workDir, 'package.json'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, 'bin'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, '.git'))).toBeTruthy(); }); cliTest('create a Java app project', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'java', canUseNetwork: false, generateOnly: true, workDir, }); expect(await fs.pathExists(path.join(workDir, 'pom.xml'))).toBeTruthy(); const pom = (await fs.readFile(path.join(workDir, 'pom.xml'), 'utf8')).split(/\r?\n/); const matches = pom.map(line => line.match(/\<constructs\.version\>(.*)\<\/constructs\.version\>/)) .filter(l => l); expect(matches.length).toEqual(1); matches.forEach(m => { const version = m && m[1]; expect(version).toMatch(/\[10\.[\d]+\.[\d]+,11\.0\.0\)/); }); }); cliTest('create a .NET app project in csharp', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'csharp', canUseNetwork: false, generateOnly: true, workDir, }); const csprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.csproj'))[0]; const slnFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.sln'))[0]; expect(csprojFile).toBeDefined(); expect(slnFile).toBeDefined(); const csproj = (await fs.readFile(csprojFile, 'utf8')).split(/\r?\n/); const sln = (await fs.readFile(slnFile, 'utf8')).split(/\r?\n/); expect(csproj).toContainEqual(expect.stringMatching(/\<PackageReference Include="Constructs" Version="\[10\..*,11\..*\)"/)); expect(csproj).toContainEqual(expect.stringMatching(/\<TargetFramework>net8.0<\/TargetFramework>/)); expect(sln).toContainEqual(expect.stringMatching(/\"AwsCdkTest[a-zA-Z0-9]{6}\\AwsCdkTest[a-zA-Z0-9]{6}.csproj\"/)); }); cliTest('create a .NET app project in fsharp', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'fsharp', canUseNetwork: false, generateOnly: true, workDir, }); const fsprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.fsproj'))[0]; const slnFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.sln'))[0]; expect(fsprojFile).toBeDefined(); expect(slnFile).toBeDefined(); const fsproj = (await fs.readFile(fsprojFile, 'utf8')).split(/\r?\n/); const sln = (await fs.readFile(slnFile, 'utf8')).split(/\r?\n/); expect(fsproj).toContainEqual(expect.stringMatching(/\<PackageReference Include="Constructs" Version="\[10\..*,11\..*\)"/)); expect(fsproj).toContainEqual(expect.stringMatching(/\<TargetFramework>net8.0<\/TargetFramework>/)); expect(sln).toContainEqual(expect.stringMatching(/\"AwsCdkTest[a-zA-Z0-9]{6}\\AwsCdkTest[a-zA-Z0-9]{6}.fsproj\"/)); }); cliTestWithDirSpaces('csharp app with spaces', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'csharp', canUseNetwork: false, generateOnly: true, workDir, }); const csprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.csproj'))[0]; expect(csprojFile).toBeDefined(); const csproj = (await fs.readFile(csprojFile, 'utf8')).split(/\r?\n/); expect(csproj).toContainEqual(expect.stringMatching(/\<PackageReference Include="Constructs" Version="\[10\..*,11\..*\)"/)); expect(csproj).toContainEqual(expect.stringMatching(/\<TargetFramework>net8.0<\/TargetFramework>/)); }); cliTestWithDirSpaces('fsharp app with spaces', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'fsharp', canUseNetwork: false, generateOnly: true, workDir, }); const fsprojFile = (await recursiveListFiles(workDir)).filter(f => f.endsWith('.fsproj'))[0]; expect(fsprojFile).toBeDefined(); const fsproj = (await fs.readFile(fsprojFile, 'utf8')).split(/\r?\n/); expect(fsproj).toContainEqual(expect.stringMatching(/\<PackageReference Include="Constructs" Version="\[10\..*,11\..*\)"/)); expect(fsproj).toContainEqual(expect.stringMatching(/\<TargetFramework>net8.0<\/TargetFramework>/)); }); cliTest('create a Python app project', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'python', canUseNetwork: false, generateOnly: true, workDir, }); expect(await fs.pathExists(path.join(workDir, 'requirements.txt'))).toBeTruthy(); const setupPy = (await fs.readFile(path.join(workDir, 'requirements.txt'), 'utf8')).split(/\r?\n/); // return RegExpMatchArray (result of line.match()) for every lines that match re. const matches = setupPy.map(line => line.match(/^constructs(.*)/)) .filter(l => l); expect(matches.length).toEqual(1); matches.forEach(m => { const version = m && m[1]; expect(version).toMatch(/>=10\.\d+\.\d,<11\.0\.0/); }); }); cliTest('--generate-only should skip git init', async (workDir) => { await (0, init_1.cliInit)({ type: 'app', language: 'javascript', canUseNetwork: false, generateOnly: true, workDir, }); // Check that package.json and bin/ got created in the current directory expect(await fs.pathExists(path.join(workDir, 'package.json'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, 'bin'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, '.git'))).toBeFalsy(); }); cliTest('git directory does not throw off the initer!', async (workDir) => { fs.mkdirSync(path.join(workDir, '.git')); await (0, init_1.cliInit)({ type: 'app', language: 'typescript', canUseNetwork: false, workDir, }); // Check that package.json and bin/ got created in the current directory expect(await fs.pathExists(path.join(workDir, 'package.json'))).toBeTruthy(); expect(await fs.pathExists(path.join(workDir, 'bin'))).toBeTruthy(); }); cliTest('CLI uses recommended feature flags from data file to initialize context', async (workDir) => { const recommendedFlagsFile = path.join(__dirname, '..', 'lib', 'init-templates', '.recommended-feature-flags.json'); await withReplacedFile(recommendedFlagsFile, JSON.stringify({ banana: 'yellow' }), () => (0, init_1.cliInit)({ type: 'app', language: 'typescript', canUseNetwork: false, generateOnly: true, workDir, })); const cdkFile = await fs.readJson(path.join(workDir, 'cdk.json')); expect(cdkFile.context).toEqual({ banana: 'yellow' }); }); cliTest('CLI uses init versions file to initialize template', async (workDir) => { const recommendedFlagsFile = path.join(__dirname, '..', 'lib', 'init-templates', '.init-version.json'); await withReplacedFile(recommendedFlagsFile, JSON.stringify({ 'aws-cdk-lib': '100.1.1', 'constructs': '^200.2.2' }), () => (0, init_1.cliInit)({ type: 'app', language: 'typescript', canUseNetwork: false, generateOnly: true, workDir, })); const packageJson = await fs.readJson(path.join(workDir, 'package.json')); expect(packageJson.dependencies['aws-cdk-lib']).toEqual('100.1.1'); expect(packageJson.dependencies.constructs).toEqual('^200.2.2'); }); test('verify "future flags" are added to cdk.json', async () => { for (const templ of await (0, init_1.availableInitTemplates)()) { for (const lang of templ.languages) { await withTempDir(async (tmpDir) => { await (0, init_1.cliInit)({ type: templ.name, language: lang, canUseNetwork: false, generateOnly: true, workDir: tmpDir, }); // ok if template doesn't have a cdk.json file (e.g. the "lib" template) if (!await fs.pathExists(path.join(tmpDir, 'cdk.json'))) { return; } const config = await fs.readJson(path.join(tmpDir, 'cdk.json')); const context = config.context || {}; const recommendedFlags = await (0, init_1.currentlyRecommendedAwsCdkLibFlags)(); for (const [key, actual] of Object.entries(context)) { expect(key in recommendedFlags).toBeTruthy(); expect(recommendedFlags[key]).toEqual(actual); } // assert that expired future flags are not part of the cdk.json Object.keys(context).forEach(k => { expect(cxapi.CURRENT_VERSION_EXPIRED_FLAGS.includes(k)).toEqual(false); }); }); } } }, // This is a lot to test, and it can be slow-ish, especially when ran with other tests. 30000); }); test('when no version number is present (e.g., local development), the v2 templates are chosen by default', async () => { expect((await (0, init_1.availableInitTemplates)()).length).toBeGreaterThan(0); }); test('check available init languages', async () => { const langs = await (0, init_1.availableInitLanguages)(); expect(langs.length).toBeGreaterThan(0); expect(langs).toContain('typescript'); }); test('exercise printing available templates', async () => { await (0, init_1.printAvailableTemplates)(); }); function cliTest(name, handler) { test(name, () => withTempDir(handler)); } async function withTempDir(cb) { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aws-cdk-test')); try { await cb(tmpDir); } finally { await fs.remove(tmpDir); } } function cliTestWithDirSpaces(name, handler) { test(name, () => withTempDirWithSpaces(handler)); } async function withTempDirWithSpaces(cb) { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aws-cdk-test with-space')); try { await cb(tmpDir); } finally { await fs.remove(tmpDir); } } /** * List all files underneath dir */ async function recursiveListFiles(rdir) { const ret = new Array(); await recurse(rdir); return ret; async function recurse(dir) { for (const name of await fs.readdir(dir)) { const fullPath = path.join(dir, name); if ((await fs.stat(fullPath)).isDirectory()) { await recurse(fullPath); } else { ret.push(fullPath); } } } } async function withReplacedFile(fileName, contents, cb) { const oldContents = await fs.readFile(fileName, 'utf8'); await fs.writeFile(fileName, contents); try { await cb(); } finally { await fs.writeFile(fileName, oldContents); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW5pdC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix5Q0FBeUM7QUFDekMsK0JBQStCO0FBQy9CLHNDQUFtSjtBQUVuSixRQUFRLENBQUMsb0JBQW9CLEVBQUUsR0FBRyxFQUFFO0lBQ2xDLE9BQU8sQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDL0QsTUFBTSxJQUFBLGNBQU8sRUFBQztZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsUUFBUSxFQUFFLFlBQVk7WUFDdEIsT0FBTztTQUNSLENBQUMsQ0FBQztRQUVILHdFQUF3RTtRQUN4RSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM3RSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUN0RSxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sQ0FBQyx5Q0FBeUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDbkUsTUFBTSxNQUFNLENBQUMsSUFBQSxjQUFPLEVBQUM7WUFDbkIsSUFBSSxFQUFFLFFBQVE7WUFDZCxRQUFRLEVBQUUsWUFBWTtZQUN0QixPQUFPO1NBQ1IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQy9DLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLHlEQUF5RCxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUNuRixNQUFNLE1BQU0sQ0FBQyxJQUFBLGNBQU8sRUFBQztZQUNuQixJQUFJLEVBQUUsS0FBSztZQUNYLE9BQU87U0FDUixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLGlDQUFpQyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUMzRCxNQUFNLElBQUEsY0FBTyxFQUFDO1lBQ1osSUFBSSxFQUFFLEtBQUs7WUFDWCxRQUFRLEVBQUUsWUFBWTtZQUN0QixPQUFPO1NBQ1IsQ0FBQyxDQUFDO1FBRUgsd0VBQXdFO1FBQ3hFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3RFLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLGlDQUFpQyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUMzRCxNQUFNLElBQUEsY0FBTyxFQUFDO1lBQ1osSUFBSSxFQUFFLEtBQUs7WUFDWCxRQUFRLEVBQUUsWUFBWTtZQUN0QixPQUFPO1NBQ1IsQ0FBQyxDQUFDO1FBRUgsd0VBQXdFO1FBQ3hFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3BFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3ZFLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLDJCQUEyQixFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUNyRCxNQUFNLElBQUEsY0FBTyxFQUFDO1lBQ1osSUFBSSxFQUFFLEtBQUs7WUFDWCxRQUFRLEVBQUUsTUFBTTtZQUNoQixhQUFhLEVBQUUsS0FBSztZQUNwQixZQUFZLEVBQUUsSUFBSTtZQUNsQixPQUFPO1NBQ1IsQ0FBQyxDQUFDO1FBRUgsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFeEUsTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEYsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsc0RBQXNELENBQUMsQ0FBQzthQUNoRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVsQixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ2xCLE1BQU0sT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQzNELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLENBQUMscUNBQXFDLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQy9ELE1BQU0sSUFBQSxjQUFPLEVBQUM7WUFDWixJQUFJLEVBQUUsS0FBSztZQUNYLFFBQVEsRUFBRSxRQUFRO1lBQ2xCLGFBQWEsRUFBRSxLQUFLO1lBQ3BCLFlBQVksRUFBRSxJQUFJO1lBQ2xCLE9BQU87U0FDUixDQUFDLENBQUM7UUFFSCxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0YsTUFBTSxPQUFPLEdBQUcsQ0FBQyxNQUFNLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZGLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFOUIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3RFLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVoRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMscUVBQXFFLENBQUMsQ0FBQyxDQUFDO1FBQzVILE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDLENBQUM7UUFDcEcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLCtEQUErRCxDQUFDLENBQUMsQ0FBQztJQUNySCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDL0QsTUFBTSxJQUFBLGNBQU8sRUFBQztZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsUUFBUSxFQUFFLFFBQVE7WUFDbEIsYUFBYSxFQUFFLEtBQUs7WUFDcEIsWUFBWSxFQUFFLElBQUk7WUFDbEIsT0FBTztTQUNSLENBQUMsQ0FBQztRQUVILE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RixNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUU5QixNQUFNLE1BQU0sR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEUsTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWhFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDLENBQUM7UUFDNUgsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLDZDQUE2QyxDQUFDLENBQUMsQ0FBQztRQUNwRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsK0RBQStELENBQUMsQ0FBQyxDQUFDO0lBQ3JILENBQUMsQ0FBQyxDQUFDO0lBRUgsb0JBQW9CLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQy9ELE1BQU0sSUFBQSxjQUFPLEVBQUM7WUFDWixJQUFJLEVBQUUsS0FBSztZQUNYLFFBQVEsRUFBRSxRQUFRO1lBQ2xCLGFBQWEsRUFBRSxLQUFLO1lBQ3BCLFlBQVksRUFBRSxJQUFJO1lBQ2xCLE9BQU87U0FDUixDQUFDLENBQUM7UUFFSCxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0YsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRWpDLE1BQU0sTUFBTSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUV0RSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMscUVBQXFFLENBQUMsQ0FBQyxDQUFDO1FBQzVILE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDLENBQUM7SUFDdEcsQ0FBQyxDQUFDLENBQUM7SUFFSCxvQkFBb0IsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDL0QsTUFBTSxJQUFBLGNBQU8sRUFBQztZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsUUFBUSxFQUFFLFFBQVE7WUFDbEIsYUFBYSxFQUFFLEtBQUs7WUFDcEIsWUFBWSxFQUFFLElBQUk7WUFDbEIsT0FBTztTQUNSLENBQUMsQ0FBQztRQUVILE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RixNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFakMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXRFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxxRUFBcUUsQ0FBQyxDQUFDLENBQUM7UUFDNUgsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLDZDQUE2QyxDQUFDLENBQUMsQ0FBQztJQUN0RyxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sQ0FBQyw2QkFBNkIsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDdkQsTUFBTSxJQUFBLGNBQU8sRUFBQztZQUNaLElBQUksRUFBRSxLQUFLO1lBQ1gsUUFBUSxFQUFFLFFBQVE7WUFDbEIsYUFBYSxFQUFFLEtBQUs7WUFDcEIsWUFBWSxFQUFFLElBQUk7WUFDbEIsT0FBTztTQUNSLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDakYsTUFBTSxPQUFPLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsa0JBQWtCLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuRyxrRkFBa0Y7UUFDbEYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQzthQUMvRCxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVsQixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ2xCLE1BQU0sT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLENBQUMsc0NBQXNDLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQ2hFLE1BQU0sSUFBQSxjQUFPLEVBQUM7WUFDWixJQUFJLEVBQUUsS0FBSztZQUNYLFFBQVEsRUFBRSxZQUFZO1lBQ3RCLGFBQWEsRUFBRSxLQUFLO1lBQ3BCLFlBQVksRUFBRSxJQUFJO1lBQ2xCLE9BQU87U0FDUixDQUFDLENBQUM7UUFFSCx3RUFBd0U7UUFDeEUsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDN0UsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEUsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDdEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLENBQUMsOENBQThDLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQ3hFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUV6QyxNQUFNLElBQUEsY0FBTyxFQUFDO1lBQ1osSUFBSSxFQUFFLEtBQUs7WUFDWCxRQUFRLEVBQUUsWUFBWTtZQUN0QixhQUFhLEVBQUUsS0FBSztZQUNwQixPQUFPO1NBQ1IsQ0FBQyxDQUFDO1FBRUgsd0VBQXdFO1FBQ3hFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3RFLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxDQUFDLHlFQUF5RSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUNuRyxNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztRQUNwSCxNQUFNLGdCQUFnQixDQUFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFBLGNBQU8sRUFBQztZQUMvRixJQUFJLEVBQUUsS0FBSztZQUNYLFFBQVEsRUFBRSxZQUFZO1lBQ3RCLGFBQWEsRUFBRSxLQUFLO1lBQ3BCLFlBQVksRUFBRSxJQUFJO1lBQ2xCLE9BQU87U0FDUixDQUFDLENBQUMsQ0FBQztRQUVKLE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLENBQUMsb0RBQW9ELEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQzlFLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3ZHLE1BQU0sZ0JBQWdCLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBQSxjQUFPLEVBQUM7WUFDakksSUFBSSxFQUFFLEtBQUs7WUFDWCxRQUFRLEVBQUUsWUFBWTtZQUN0QixhQUFhLEVBQUUsS0FBSztZQUNwQixZQUFZLEVBQUUsSUFBSTtZQUNsQixPQUFPO1NBQ1IsQ0FBQyxDQUFDLENBQUM7UUFFSixNQUFNLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUMxRSxNQUFNLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNuRSxNQUFNLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDbEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsNkNBQTZDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDN0QsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLElBQUEsNkJBQXNCLEdBQUUsRUFBRSxDQUFDO1lBQ25ELEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNuQyxNQUFNLFdBQVcsQ0FBQyxLQUFLLEVBQUMsTUFBTSxFQUFDLEVBQUU7b0JBQy9CLE1BQU0sSUFBQSxjQUFPLEVBQUM7d0JBQ1osSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO3dCQUNoQixRQUFRLEVBQUUsSUFBSTt3QkFDZCxhQUFhLEVBQUUsS0FBSzt3QkFDcEIsWUFBWSxFQUFFLElBQUk7d0JBQ2xCLE9BQU8sRUFBRSxNQUFNO3FCQUNoQixDQUFDLENBQUM7b0JBRUgsd0VBQXdFO29CQUN4RSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQzt3QkFDeEQsT0FBTztvQkFDVCxDQUFDO29CQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO29CQUNoRSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztvQkFDckMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLElBQUEseUNBQWtDLEdBQUUsQ0FBQztvQkFDcEUsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQzt3QkFDcEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO3dCQUM3QyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQ2hELENBQUM7b0JBRUQsZ0VBQWdFO29CQUNoRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTt3QkFDL0IsTUFBTSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3pFLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBQ0QsdUZBQXVGO0lBQ3ZGLEtBQU0sQ0FBQyxDQUFDO0FBQ1YsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMscUdBQXFHLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDckgsTUFBTSxDQUFDLENBQUMsTUFBTSxJQUFBLDZCQUFzQixHQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsZ0NBQWdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDaEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFBLDZCQUFzQixHQUFFLENBQUM7SUFDN0MsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUN4QyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN2RCxNQUFNLElBQUEsOEJBQXVCLEdBQUUsQ0FBQztBQUNsQyxDQUFDLENBQUMsQ0FBQztBQUVILFNBQVMsT0FBTyxDQUFDLElBQVksRUFBRSxPQUE2QztJQUMxRSxJQUFJLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ3pDLENBQUM7QUFFRCxLQUFLLFVBQVUsV0FBVyxDQUFDLEVBQXdDO0lBQ2pFLE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25CLENBQUM7WUFBUyxDQUFDO1FBQ1QsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFCLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxJQUFZLEVBQUUsT0FBNkM7SUFDdkYsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxLQUFLLFVBQVUscUJBQXFCLENBQUMsRUFBd0M7SUFDM0UsTUFBTSxNQUFNLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLHlCQUF5QixDQUFDLENBQUMsQ0FBQztJQUNuRixJQUFJLENBQUM7UUFDSCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQixDQUFDO1lBQVMsQ0FBQztRQUNULE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQixDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGtCQUFrQixDQUFDLElBQVk7SUFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztJQUNoQyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQixPQUFPLEdBQUcsQ0FBQztJQUVYLEtBQUssVUFBVSxPQUFPLENBQUMsR0FBVztRQUNoQyxLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO2dCQUM1QyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMxQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNyQixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsS0FBSyxVQUFVLGdCQUFnQixDQUFDLFFBQWdCLEVBQUUsUUFBYSxFQUFFLEVBQXVCO0lBQ3RGLE1BQU0sV0FBVyxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDeEQsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2QyxJQUFJLENBQUM7UUFDSCxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ2IsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQzVDLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBhdmFpbGFibGVJbml0TGFuZ3VhZ2VzLCBhdmFpbGFibGVJbml0VGVtcGxhdGVzLCBjbGlJbml0LCBjdXJyZW50bHlSZWNvbW1lbmRlZEF3c0Nka0xpYkZsYWdzLCBwcmludEF2YWlsYWJsZVRlbXBsYXRlcyB9IGZyb20gJy4uL2xpYi9pbml0JztcblxuZGVzY3JpYmUoJ2NvbnN0cnVjdHMgdmVyc2lvbicsICgpID0+IHtcbiAgY2xpVGVzdCgnY3JlYXRlIGEgVHlwZVNjcmlwdCBsaWJyYXJ5IHByb2plY3QnLCBhc3luYyAod29ya0RpcikgPT4ge1xuICAgIGF3YWl0IGNsaUluaXQoe1xuICAgICAgdHlwZTogJ2xpYicsXG4gICAgICBsYW5ndWFnZTogJ3R5cGVzY3JpcHQnLFxuICAgICAgd29ya0RpcixcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIHRoYXQgcGFja2FnZS5qc29uIGFuZCBsaWIvIGdvdCBjcmVhdGVkIGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeVxuICAgIGV4cGVjdChhd2FpdCBmcy5wYXRoRXhpc3RzKHBhdGguam9pbih3b3JrRGlyLCAncGFja2FnZS5qc29uJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICdsaWInKSkpLnRvQmVUcnV0aHkoKTtcbiAgfSk7XG5cbiAgY2xpVGVzdCgnYXNraW5nIGZvciBhIG5vbmV4aXN0ZW50IHRlbXBsYXRlIGZhaWxzJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBhd2FpdCBleHBlY3QoY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYmFuYW5hJyxcbiAgICAgIGxhbmd1YWdlOiAndHlwZXNjcmlwdCcsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pKS5yZWplY3RzLnRvVGhyb3coL1Vua25vd24gaW5pdCB0ZW1wbGF0ZS8pO1xuICB9KTtcblxuICBjbGlUZXN0KCdhc2tpbmcgZm9yIGEgdGVtcGxhdGUgYnV0IG5vIGxhbmd1YWdlIHByaW50cyBhbmQgdGhyb3dzJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBhd2FpdCBleHBlY3QoY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIHdvcmtEaXIsXG4gICAgfSkpLnJlamVjdHMudG9UaHJvdygvTm8gbGFuZ3VhZ2UvKTtcbiAgfSk7XG5cbiAgY2xpVGVzdCgnY3JlYXRlIGEgVHlwZVNjcmlwdCBhcHAgcHJvamVjdCcsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgYXdhaXQgY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAndHlwZXNjcmlwdCcsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pO1xuXG4gICAgLy8gQ2hlY2sgdGhhdCBwYWNrYWdlLmpzb24gYW5kIGJpbi8gZ290IGNyZWF0ZWQgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5XG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICdwYWNrYWdlLmpzb24nKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoYXdhaXQgZnMucGF0aEV4aXN0cyhwYXRoLmpvaW4od29ya0RpciwgJ2JpbicpKSkudG9CZVRydXRoeSgpO1xuICB9KTtcblxuICBjbGlUZXN0KCdjcmVhdGUgYSBKYXZhU2NyaXB0IGFwcCBwcm9qZWN0JywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBhd2FpdCBjbGlJbml0KHtcbiAgICAgIHR5cGU6ICdhcHAnLFxuICAgICAgbGFuZ3VhZ2U6ICdqYXZhc2NyaXB0JyxcbiAgICAgIHdvcmtEaXIsXG4gICAgfSk7XG5cbiAgICAvLyBDaGVjayB0aGF0IHBhY2thZ2UuanNvbiBhbmQgYmluLyBnb3QgY3JlYXRlZCBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnlcbiAgICBleHBlY3QoYXdhaXQgZnMucGF0aEV4aXN0cyhwYXRoLmpvaW4od29ya0RpciwgJ3BhY2thZ2UuanNvbicpKSkudG9CZVRydXRoeSgpO1xuICAgIGV4cGVjdChhd2FpdCBmcy5wYXRoRXhpc3RzKHBhdGguam9pbih3b3JrRGlyLCAnYmluJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICcuZ2l0JykpKS50b0JlVHJ1dGh5KCk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2NyZWF0ZSBhIEphdmEgYXBwIHByb2plY3QnLCBhc3luYyAod29ya0RpcikgPT4ge1xuICAgIGF3YWl0IGNsaUluaXQoe1xuICAgICAgdHlwZTogJ2FwcCcsXG4gICAgICBsYW5ndWFnZTogJ2phdmEnLFxuICAgICAgY2FuVXNlTmV0d29yazogZmFsc2UsXG4gICAgICBnZW5lcmF0ZU9ubHk6IHRydWUsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICdwb20ueG1sJykpKS50b0JlVHJ1dGh5KCk7XG5cbiAgICBjb25zdCBwb20gPSAoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKHdvcmtEaXIsICdwb20ueG1sJyksICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG4gICAgY29uc3QgbWF0Y2hlcyA9IHBvbS5tYXAobGluZSA9PiBsaW5lLm1hdGNoKC9cXDxjb25zdHJ1Y3RzXFwudmVyc2lvblxcPiguKilcXDxcXC9jb25zdHJ1Y3RzXFwudmVyc2lvblxcPi8pKVxuICAgICAgLmZpbHRlcihsID0+IGwpO1xuXG4gICAgZXhwZWN0KG1hdGNoZXMubGVuZ3RoKS50b0VxdWFsKDEpO1xuICAgIG1hdGNoZXMuZm9yRWFjaChtID0+IHtcbiAgICAgIGNvbnN0IHZlcnNpb24gPSBtICYmIG1bMV07XG4gICAgICBleHBlY3QodmVyc2lvbikudG9NYXRjaCgvXFxbMTBcXC5bXFxkXStcXC5bXFxkXSssMTFcXC4wXFwuMFxcKS8pO1xuICAgIH0pO1xuICB9KTtcblxuICBjbGlUZXN0KCdjcmVhdGUgYSAuTkVUIGFwcCBwcm9qZWN0IGluIGNzaGFycCcsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgYXdhaXQgY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAnY3NoYXJwJyxcbiAgICAgIGNhblVzZU5ldHdvcms6IGZhbHNlLFxuICAgICAgZ2VuZXJhdGVPbmx5OiB0cnVlLFxuICAgICAgd29ya0RpcixcbiAgICB9KTtcblxuICAgIGNvbnN0IGNzcHJvakZpbGUgPSAoYXdhaXQgcmVjdXJzaXZlTGlzdEZpbGVzKHdvcmtEaXIpKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKCcuY3Nwcm9qJykpWzBdO1xuICAgIGNvbnN0IHNsbkZpbGUgPSAoYXdhaXQgcmVjdXJzaXZlTGlzdEZpbGVzKHdvcmtEaXIpKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKCcuc2xuJykpWzBdO1xuICAgIGV4cGVjdChjc3Byb2pGaWxlKS50b0JlRGVmaW5lZCgpO1xuICAgIGV4cGVjdChzbG5GaWxlKS50b0JlRGVmaW5lZCgpO1xuXG4gICAgY29uc3QgY3Nwcm9qID0gKGF3YWl0IGZzLnJlYWRGaWxlKGNzcHJvakZpbGUsICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG4gICAgY29uc3Qgc2xuID0gKGF3YWl0IGZzLnJlYWRGaWxlKHNsbkZpbGUsICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG5cbiAgICBleHBlY3QoY3Nwcm9qKS50b0NvbnRhaW5FcXVhbChleHBlY3Quc3RyaW5nTWF0Y2hpbmcoL1xcPFBhY2thZ2VSZWZlcmVuY2UgSW5jbHVkZT1cIkNvbnN0cnVjdHNcIiBWZXJzaW9uPVwiXFxbMTBcXC4uKiwxMVxcLi4qXFwpXCIvKSk7XG4gICAgZXhwZWN0KGNzcHJvaikudG9Db250YWluRXF1YWwoZXhwZWN0LnN0cmluZ01hdGNoaW5nKC9cXDxUYXJnZXRGcmFtZXdvcms+bmV0OC4wPFxcL1RhcmdldEZyYW1ld29yaz4vKSk7XG4gICAgZXhwZWN0KHNsbikudG9Db250YWluRXF1YWwoZXhwZWN0LnN0cmluZ01hdGNoaW5nKC9cXFwiQXdzQ2RrVGVzdFthLXpBLVowLTldezZ9XFxcXEF3c0Nka1Rlc3RbYS16QS1aMC05XXs2fS5jc3Byb2pcXFwiLykpO1xuICB9KTtcblxuICBjbGlUZXN0KCdjcmVhdGUgYSAuTkVUIGFwcCBwcm9qZWN0IGluIGZzaGFycCcsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgYXdhaXQgY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAnZnNoYXJwJyxcbiAgICAgIGNhblVzZU5ldHdvcms6IGZhbHNlLFxuICAgICAgZ2VuZXJhdGVPbmx5OiB0cnVlLFxuICAgICAgd29ya0RpcixcbiAgICB9KTtcblxuICAgIGNvbnN0IGZzcHJvakZpbGUgPSAoYXdhaXQgcmVjdXJzaXZlTGlzdEZpbGVzKHdvcmtEaXIpKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKCcuZnNwcm9qJykpWzBdO1xuICAgIGNvbnN0IHNsbkZpbGUgPSAoYXdhaXQgcmVjdXJzaXZlTGlzdEZpbGVzKHdvcmtEaXIpKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKCcuc2xuJykpWzBdO1xuICAgIGV4cGVjdChmc3Byb2pGaWxlKS50b0JlRGVmaW5lZCgpO1xuICAgIGV4cGVjdChzbG5GaWxlKS50b0JlRGVmaW5lZCgpO1xuXG4gICAgY29uc3QgZnNwcm9qID0gKGF3YWl0IGZzLnJlYWRGaWxlKGZzcHJvakZpbGUsICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG4gICAgY29uc3Qgc2xuID0gKGF3YWl0IGZzLnJlYWRGaWxlKHNsbkZpbGUsICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG5cbiAgICBleHBlY3QoZnNwcm9qKS50b0NvbnRhaW5FcXVhbChleHBlY3Quc3RyaW5nTWF0Y2hpbmcoL1xcPFBhY2thZ2VSZWZlcmVuY2UgSW5jbHVkZT1cIkNvbnN0cnVjdHNcIiBWZXJzaW9uPVwiXFxbMTBcXC4uKiwxMVxcLi4qXFwpXCIvKSk7XG4gICAgZXhwZWN0KGZzcHJvaikudG9Db250YWluRXF1YWwoZXhwZWN0LnN0cmluZ01hdGNoaW5nKC9cXDxUYXJnZXRGcmFtZXdvcms+bmV0OC4wPFxcL1RhcmdldEZyYW1ld29yaz4vKSk7XG4gICAgZXhwZWN0KHNsbikudG9Db250YWluRXF1YWwoZXhwZWN0LnN0cmluZ01hdGNoaW5nKC9cXFwiQXdzQ2RrVGVzdFthLXpBLVowLTldezZ9XFxcXEF3c0Nka1Rlc3RbYS16QS1aMC05XXs2fS5mc3Byb2pcXFwiLykpO1xuICB9KTtcblxuICBjbGlUZXN0V2l0aERpclNwYWNlcygnY3NoYXJwIGFwcCB3aXRoIHNwYWNlcycsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgYXdhaXQgY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAnY3NoYXJwJyxcbiAgICAgIGNhblVzZU5ldHdvcms6IGZhbHNlLFxuICAgICAgZ2VuZXJhdGVPbmx5OiB0cnVlLFxuICAgICAgd29ya0RpcixcbiAgICB9KTtcblxuICAgIGNvbnN0IGNzcHJvakZpbGUgPSAoYXdhaXQgcmVjdXJzaXZlTGlzdEZpbGVzKHdvcmtEaXIpKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKCcuY3Nwcm9qJykpWzBdO1xuICAgIGV4cGVjdChjc3Byb2pGaWxlKS50b0JlRGVmaW5lZCgpO1xuXG4gICAgY29uc3QgY3Nwcm9qID0gKGF3YWl0IGZzLnJlYWRGaWxlKGNzcHJvakZpbGUsICd1dGY4JykpLnNwbGl0KC9cXHI/XFxuLyk7XG5cbiAgICBleHBlY3QoY3Nwcm9qKS50b0NvbnRhaW5FcXVhbChleHBlY3Quc3RyaW5nTWF0Y2hpbmcoL1xcPFBhY2thZ2VSZWZlcmVuY2UgSW5jbHVkZT1cIkNvbnN0cnVjdHNcIiBWZXJzaW9uPVwiXFxbMTBcXC4uKiwxMVxcLi4qXFwpXCIvKSk7XG4gICAgZXhwZWN0KGNzcHJvaikudG9Db250YWluRXF1YWwoZXhwZWN0LnN0cmluZ01hdGNoaW5nKC9cXDxUYXJnZXRGcmFtZXdvcms+bmV0OC4wPFxcL1RhcmdldEZyYW1ld29yaz4vKSk7XG4gIH0pO1xuXG4gIGNsaVRlc3RXaXRoRGlyU3BhY2VzKCdmc2hhcnAgYXBwIHdpdGggc3BhY2VzJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBhd2FpdCBjbGlJbml0KHtcbiAgICAgIHR5cGU6ICdhcHAnLFxuICAgICAgbGFuZ3VhZ2U6ICdmc2hhcnAnLFxuICAgICAgY2FuVXNlTmV0d29yazogZmFsc2UsXG4gICAgICBnZW5lcmF0ZU9ubHk6IHRydWUsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZnNwcm9qRmlsZSA9IChhd2FpdCByZWN1cnNpdmVMaXN0RmlsZXMod29ya0RpcikpLmZpbHRlcihmID0+IGYuZW5kc1dpdGgoJy5mc3Byb2onKSlbMF07XG4gICAgZXhwZWN0KGZzcHJvakZpbGUpLnRvQmVEZWZpbmVkKCk7XG5cbiAgICBjb25zdCBmc3Byb2ogPSAoYXdhaXQgZnMucmVhZEZpbGUoZnNwcm9qRmlsZSwgJ3V0ZjgnKSkuc3BsaXQoL1xccj9cXG4vKTtcblxuICAgIGV4cGVjdChmc3Byb2opLnRvQ29udGFpbkVxdWFsKGV4cGVjdC5zdHJpbmdNYXRjaGluZygvXFw8UGFja2FnZVJlZmVyZW5jZSBJbmNsdWRlPVwiQ29uc3RydWN0c1wiIFZlcnNpb249XCJcXFsxMFxcLi4qLDExXFwuLipcXClcIi8pKTtcbiAgICBleHBlY3QoZnNwcm9qKS50b0NvbnRhaW5FcXVhbChleHBlY3Quc3RyaW5nTWF0Y2hpbmcoL1xcPFRhcmdldEZyYW1ld29yaz5uZXQ4LjA8XFwvVGFyZ2V0RnJhbWV3b3JrPi8pKTtcbiAgfSk7XG5cbiAgY2xpVGVzdCgnY3JlYXRlIGEgUHl0aG9uIGFwcCBwcm9qZWN0JywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBhd2FpdCBjbGlJbml0KHtcbiAgICAgIHR5cGU6ICdhcHAnLFxuICAgICAgbGFuZ3VhZ2U6ICdweXRob24nLFxuICAgICAgY2FuVXNlTmV0d29yazogZmFsc2UsXG4gICAgICBnZW5lcmF0ZU9ubHk6IHRydWUsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICdyZXF1aXJlbWVudHMudHh0JykpKS50b0JlVHJ1dGh5KCk7XG4gICAgY29uc3Qgc2V0dXBQeSA9IChhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4od29ya0RpciwgJ3JlcXVpcmVtZW50cy50eHQnKSwgJ3V0ZjgnKSkuc3BsaXQoL1xccj9cXG4vKTtcbiAgICAvLyByZXR1cm4gUmVnRXhwTWF0Y2hBcnJheSAocmVzdWx0IG9mIGxpbmUubWF0Y2goKSkgZm9yIGV2ZXJ5IGxpbmVzIHRoYXQgbWF0Y2ggcmUuXG4gICAgY29uc3QgbWF0Y2hlcyA9IHNldHVwUHkubWFwKGxpbmUgPT4gbGluZS5tYXRjaCgvXmNvbnN0cnVjdHMoLiopLykpXG4gICAgICAuZmlsdGVyKGwgPT4gbCk7XG5cbiAgICBleHBlY3QobWF0Y2hlcy5sZW5ndGgpLnRvRXF1YWwoMSk7XG4gICAgbWF0Y2hlcy5mb3JFYWNoKG0gPT4ge1xuICAgICAgY29uc3QgdmVyc2lvbiA9IG0gJiYgbVsxXTtcbiAgICAgIGV4cGVjdCh2ZXJzaW9uKS50b01hdGNoKC8+PTEwXFwuXFxkK1xcLlxcZCw8MTFcXC4wXFwuMC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBjbGlUZXN0KCctLWdlbmVyYXRlLW9ubHkgc2hvdWxkIHNraXAgZ2l0IGluaXQnLCBhc3luYyAod29ya0RpcikgPT4ge1xuICAgIGF3YWl0IGNsaUluaXQoe1xuICAgICAgdHlwZTogJ2FwcCcsXG4gICAgICBsYW5ndWFnZTogJ2phdmFzY3JpcHQnLFxuICAgICAgY2FuVXNlTmV0d29yazogZmFsc2UsXG4gICAgICBnZW5lcmF0ZU9ubHk6IHRydWUsXG4gICAgICB3b3JrRGlyLFxuICAgIH0pO1xuXG4gICAgLy8gQ2hlY2sgdGhhdCBwYWNrYWdlLmpzb24gYW5kIGJpbi8gZ290IGNyZWF0ZWQgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5XG4gICAgZXhwZWN0KGF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHdvcmtEaXIsICdwYWNrYWdlLmpzb24nKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoYXdhaXQgZnMucGF0aEV4aXN0cyhwYXRoLmpvaW4od29ya0RpciwgJ2JpbicpKSkudG9CZVRydXRoeSgpO1xuICAgIGV4cGVjdChhd2FpdCBmcy5wYXRoRXhpc3RzKHBhdGguam9pbih3b3JrRGlyLCAnLmdpdCcpKSkudG9CZUZhbHN5KCk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2dpdCBkaXJlY3RvcnkgZG9lcyBub3QgdGhyb3cgb2ZmIHRoZSBpbml0ZXIhJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBmcy5ta2RpclN5bmMocGF0aC5qb2luKHdvcmtEaXIsICcuZ2l0JykpO1xuXG4gICAgYXdhaXQgY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAndHlwZXNjcmlwdCcsXG4gICAgICBjYW5Vc2VOZXR3b3JrOiBmYWxzZSxcbiAgICAgIHdvcmtEaXIsXG4gICAgfSk7XG5cbiAgICAvLyBDaGVjayB0aGF0IHBhY2thZ2UuanNvbiBhbmQgYmluLyBnb3QgY3JlYXRlZCBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnlcbiAgICBleHBlY3QoYXdhaXQgZnMucGF0aEV4aXN0cyhwYXRoLmpvaW4od29ya0RpciwgJ3BhY2thZ2UuanNvbicpKSkudG9CZVRydXRoeSgpO1xuICAgIGV4cGVjdChhd2FpdCBmcy5wYXRoRXhpc3RzKHBhdGguam9pbih3b3JrRGlyLCAnYmluJykpKS50b0JlVHJ1dGh5KCk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ0NMSSB1c2VzIHJlY29tbWVuZGVkIGZlYXR1cmUgZmxhZ3MgZnJvbSBkYXRhIGZpbGUgdG8gaW5pdGlhbGl6ZSBjb250ZXh0JywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBjb25zdCByZWNvbW1lbmRlZEZsYWdzRmlsZSA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdsaWInLCAnaW5pdC10ZW1wbGF0ZXMnLCAnLnJlY29tbWVuZGVkLWZlYXR1cmUtZmxhZ3MuanNvbicpO1xuICAgIGF3YWl0IHdpdGhSZXBsYWNlZEZpbGUocmVjb21tZW5kZWRGbGFnc0ZpbGUsIEpTT04uc3RyaW5naWZ5KHsgYmFuYW5hOiAneWVsbG93JyB9KSwgKCkgPT4gY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAndHlwZXNjcmlwdCcsXG4gICAgICBjYW5Vc2VOZXR3b3JrOiBmYWxzZSxcbiAgICAgIGdlbmVyYXRlT25seTogdHJ1ZSxcbiAgICAgIHdvcmtEaXIsXG4gICAgfSkpO1xuXG4gICAgY29uc3QgY2RrRmlsZSA9IGF3YWl0IGZzLnJlYWRKc29uKHBhdGguam9pbih3b3JrRGlyLCAnY2RrLmpzb24nKSk7XG4gICAgZXhwZWN0KGNka0ZpbGUuY29udGV4dCkudG9FcXVhbCh7IGJhbmFuYTogJ3llbGxvdycgfSk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ0NMSSB1c2VzIGluaXQgdmVyc2lvbnMgZmlsZSB0byBpbml0aWFsaXplIHRlbXBsYXRlJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBjb25zdCByZWNvbW1lbmRlZEZsYWdzRmlsZSA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdsaWInLCAnaW5pdC10ZW1wbGF0ZXMnLCAnLmluaXQtdmVyc2lvbi5qc29uJyk7XG4gICAgYXdhaXQgd2l0aFJlcGxhY2VkRmlsZShyZWNvbW1lbmRlZEZsYWdzRmlsZSwgSlNPTi5zdHJpbmdpZnkoeyAnYXdzLWNkay1saWInOiAnMTAwLjEuMScsICdjb25zdHJ1Y3RzJzogJ14yMDAuMi4yJyB9KSwgKCkgPT4gY2xpSW5pdCh7XG4gICAgICB0eXBlOiAnYXBwJyxcbiAgICAgIGxhbmd1YWdlOiAndHlwZXNjcmlwdCcsXG4gICAgICBjYW5Vc2VOZXR3b3JrOiBmYWxzZSxcbiAgICAgIGdlbmVyYXRlT25seTogdHJ1ZSxcbiAgICAgIHdvcmtEaXIsXG4gICAgfSkpO1xuXG4gICAgY29uc3QgcGFja2FnZUpzb24gPSBhd2FpdCBmcy5yZWFkSnNvbihwYXRoLmpvaW4od29ya0RpciwgJ3BhY2thZ2UuanNvbicpKTtcbiAgICBleHBlY3QocGFja2FnZUpzb24uZGVwZW5kZW5jaWVzWydhd3MtY2RrLWxpYiddKS50b0VxdWFsKCcxMDAuMS4xJyk7XG4gICAgZXhwZWN0KHBhY2thZ2VKc29uLmRlcGVuZGVuY2llcy5jb25zdHJ1Y3RzKS50b0VxdWFsKCdeMjAwLjIuMicpO1xuICB9KTtcblxuICB0ZXN0KCd2ZXJpZnkgXCJmdXR1cmUgZmxhZ3NcIiBhcmUgYWRkZWQgdG8gY2RrLmpzb24nLCBhc3luYyAoKSA9PiB7XG4gICAgZm9yIChjb25zdCB0ZW1wbCBvZiBhd2FpdCBhdmFpbGFibGVJbml0VGVtcGxhdGVzKCkpIHtcbiAgICAgIGZvciAoY29uc3QgbGFuZyBvZiB0ZW1wbC5sYW5ndWFnZXMpIHtcbiAgICAgICAgYXdhaXQgd2l0aFRlbXBEaXIoYXN5bmMgdG1wRGlyID0+IHtcbiAgICAgICAgICBhd2FpdCBjbGlJbml0KHtcbiAgICAgICAgICAgIHR5cGU6IHRlbXBsLm5hbWUsXG4gICAgICAgICAgICBsYW5ndWFnZTogbGFuZyxcbiAgICAgICAgICAgIGNhblVzZU5ldHdvcms6IGZhbHNlLFxuICAgICAgICAgICAgZ2VuZXJhdGVPbmx5OiB0cnVlLFxuICAgICAgICAgICAgd29ya0RpcjogdG1wRGlyLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gb2sgaWYgdGVtcGxhdGUgZG9lc24ndCBoYXZlIGEgY2RrLmpzb24gZmlsZSAoZS5nLiB0aGUgXCJsaWJcIiB0ZW1wbGF0ZSlcbiAgICAgICAgICBpZiAoIWF3YWl0IGZzLnBhdGhFeGlzdHMocGF0aC5qb2luKHRtcERpciwgJ2Nkay5qc29uJykpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY29uZmlnID0gYXdhaXQgZnMucmVhZEpzb24ocGF0aC5qb2luKHRtcERpciwgJ2Nkay5qc29uJykpO1xuICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBjb25maWcuY29udGV4dCB8fCB7fTtcbiAgICAgICAgICBjb25zdCByZWNvbW1lbmRlZEZsYWdzID0gYXdhaXQgY3VycmVudGx5UmVjb21tZW5kZWRBd3NDZGtMaWJGbGFncygpO1xuICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgYWN0dWFsXSBvZiBPYmplY3QuZW50cmllcyhjb250ZXh0KSkge1xuICAgICAgICAgICAgZXhwZWN0KGtleSBpbiByZWNvbW1lbmRlZEZsYWdzKS50b0JlVHJ1dGh5KCk7XG4gICAgICAgICAgICBleHBlY3QocmVjb21tZW5kZWRGbGFnc1trZXldKS50b0VxdWFsKGFjdHVhbCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gYXNzZXJ0IHRoYXQgZXhwaXJlZCBmdXR1cmUgZmxhZ3MgYXJlIG5vdCBwYXJ0IG9mIHRoZSBjZGsuanNvblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNvbnRleHQpLmZvckVhY2goayA9PiB7XG4gICAgICAgICAgICBleHBlY3QoY3hhcGkuQ1VSUkVOVF9WRVJTSU9OX0VYUElSRURfRkxBR1MuaW5jbHVkZXMoaykpLnRvRXF1YWwoZmFsc2UpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIC8vIFRoaXMgaXMgYSBsb3QgdG8gdGVzdCwgYW5kIGl0IGNhbiBiZSBzbG93LWlzaCwgZXNwZWNpYWxseSB3aGVuIHJhbiB3aXRoIG90aGVyIHRlc3RzLlxuICAzMF8wMDApO1xufSk7XG5cbnRlc3QoJ3doZW4gbm8gdmVyc2lvbiBudW1iZXIgaXMgcHJlc2VudCAoZS5nLiwgbG9jYWwgZGV2ZWxvcG1lbnQpLCB0aGUgdjIgdGVtcGxhdGVzIGFyZSBjaG9zZW4gYnkgZGVmYXVsdCcsIGFzeW5jICgpID0+IHtcbiAgZXhwZWN0KChhd2FpdCBhdmFpbGFibGVJbml0VGVtcGxhdGVzKCkpLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApO1xufSk7XG5cbnRlc3QoJ2NoZWNrIGF2YWlsYWJsZSBpbml0IGxhbmd1YWdlcycsIGFzeW5jICgpID0+IHtcbiAgY29uc3QgbGFuZ3MgPSBhd2FpdCBhdmFpbGFibGVJbml0TGFuZ3VhZ2VzKCk7XG4gIGV4cGVjdChsYW5ncy5sZW5ndGgpLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgZXhwZWN0KGxhbmdzKS50b0NvbnRhaW4oJ3R5cGVzY3JpcHQnKTtcbn0pO1xuXG50ZXN0KCdleGVyY2lzZSBwcmludGluZyBhdmFpbGFibGUgdGVtcGxhdGVzJywgYXN5bmMgKCkgPT4ge1xuICBhd2FpdCBwcmludEF2YWlsYWJsZVRlbXBsYXRlcygpO1xufSk7XG5cbmZ1bmN0aW9uIGNsaVRlc3QobmFtZTogc3RyaW5nLCBoYW5kbGVyOiAoZGlyOiBzdHJpbmcpID0+IHZvaWQgfCBQcm9taXNlPGFueT4pOiB2b2lkIHtcbiAgdGVzdChuYW1lLCAoKSA9PiB3aXRoVGVtcERpcihoYW5kbGVyKSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdpdGhUZW1wRGlyKGNiOiAoZGlyOiBzdHJpbmcpID0+IHZvaWQgfCBQcm9taXNlPGFueT4pIHtcbiAgY29uc3QgdG1wRGlyID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksICdhd3MtY2RrLXRlc3QnKSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgY2IodG1wRGlyKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy5yZW1vdmUodG1wRGlyKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjbGlUZXN0V2l0aERpclNwYWNlcyhuYW1lOiBzdHJpbmcsIGhhbmRsZXI6IChkaXI6IHN0cmluZykgPT4gdm9pZCB8IFByb21pc2U8YW55Pik6IHZvaWQge1xuICB0ZXN0KG5hbWUsICgpID0+IHdpdGhUZW1wRGlyV2l0aFNwYWNlcyhoYW5kbGVyKSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdpdGhUZW1wRGlyV2l0aFNwYWNlcyhjYjogKGRpcjogc3RyaW5nKSA9PiB2b2lkIHwgUHJvbWlzZTxhbnk+KSB7XG4gIGNvbnN0IHRtcERpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCAnYXdzLWNkay10ZXN0IHdpdGgtc3BhY2UnKSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgY2IodG1wRGlyKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy5yZW1vdmUodG1wRGlyKTtcbiAgfVxufVxuXG4vKipcbiAqIExpc3QgYWxsIGZpbGVzIHVuZGVybmVhdGggZGlyXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlY3Vyc2l2ZUxpc3RGaWxlcyhyZGlyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIGNvbnN0IHJldCA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gIGF3YWl0IHJlY3Vyc2UocmRpcik7XG4gIHJldHVybiByZXQ7XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVjdXJzZShkaXI6IHN0cmluZykge1xuICAgIGZvciAoY29uc3QgbmFtZSBvZiBhd2FpdCBmcy5yZWFkZGlyKGRpcikpIHtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKGRpciwgbmFtZSk7XG4gICAgICBpZiAoKGF3YWl0IGZzLnN0YXQoZnVsbFBhdGgpKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGF3YWl0IHJlY3Vyc2UoZnVsbFBhdGgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0LnB1c2goZnVsbFBhdGgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiB3aXRoUmVwbGFjZWRGaWxlKGZpbGVOYW1lOiBzdHJpbmcsIGNvbnRlbnRzOiBhbnksIGNiOiAoKSA9PiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IG9sZENvbnRlbnRzID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZU5hbWUsICd1dGY4Jyk7XG4gIGF3YWl0IGZzLndyaXRlRmlsZShmaWxlTmFtZSwgY29udGVudHMpO1xuICB0cnkge1xuICAgIGF3YWl0IGNiKCk7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVOYW1lLCBvbGRDb250ZW50cyk7XG4gIH1cbn1cbiJdfQ==