Innovenergy_trunk/frontend/node_modules/testcafe/lib/runner/index.js

622 lines
106 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const debug_1 = __importDefault(require("debug"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const events_1 = require("events");
const config_storage_1 = __importDefault(require("../dashboard/config-storage"));
const lodash_1 = require("lodash");
const bootstrapper_1 = __importDefault(require("./bootstrapper"));
const reporter_1 = __importDefault(require("../reporter"));
const task_1 = __importDefault(require("./task"));
const debug_logger_1 = __importDefault(require("../notifications/debug-logger"));
const runtime_1 = require("../errors/runtime");
const types_1 = require("../errors/types");
const type_assertions_1 = require("../errors/runtime/type-assertions");
const utils_1 = require("../errors/test-run/utils");
const detect_ffmpeg_1 = __importDefault(require("../utils/detect-ffmpeg"));
const check_file_path_1 = __importDefault(require("../utils/check-file-path"));
const handle_errors_1 = require("../utils/handle-errors");
const option_names_1 = __importDefault(require("../configuration/option-names"));
const flag_list_1 = __importDefault(require("../utils/flag-list"));
const prepare_reporters_1 = __importDefault(require("../utils/prepare-reporters"));
const load_1 = __importDefault(require("../custom-client-scripts/load"));
const utils_2 = require("../custom-client-scripts/utils");
const reporter_stream_controller_1 = __importDefault(require("./reporter-stream-controller"));
const customizable_compilers_1 = __importDefault(require("../configuration/customizable-compilers"));
const string_1 = require("../utils/string");
const is_localhost_1 = __importDefault(require("../utils/is-localhost"));
const warning_log_1 = __importDefault(require("../notifications/warning-log"));
const authentication_helper_1 = __importDefault(require("../cli/authentication-helper"));
const testcafe_browser_tools_1 = require("testcafe-browser-tools");
const is_ci_1 = __importDefault(require("is-ci"));
const remote_1 = __importDefault(require("../browser/provider/built-in/remote"));
const connection_1 = __importDefault(require("../browser/connection"));
const os_family_1 = __importDefault(require("os-family"));
const detect_display_1 = __importDefault(require("../utils/detect-display"));
const quarantine_1 = require("../utils/get-options/quarantine");
const log_entry_1 = __importDefault(require("../utils/log-entry"));
const message_bus_1 = __importDefault(require("../utils/message-bus"));
const get_env_options_1 = __importDefault(require("../dashboard/get-env-options"));
const skip_js_errors_1 = require("../utils/get-options/skip-js-errors");
const DEBUG_LOGGER = (0, debug_1.default)('testcafe:runner');
const DASHBOARD_REPORTER_NAME = 'dashboard';
class Runner extends events_1.EventEmitter {
constructor({ proxy, browserConnectionGateway, configuration, compilerService }) {
super();
this._messageBus = new message_bus_1.default();
this.proxy = proxy;
this.bootstrapper = this._createBootstrapper(browserConnectionGateway, compilerService, this._messageBus, configuration);
this.pendingTaskPromises = [];
this.configuration = configuration;
this.isCli = configuration._options && configuration._options.isCli;
this.warningLog = new warning_log_1.default(null, warning_log_1.default.createAddWarningCallback(this._messageBus));
this.compilerService = compilerService;
this._options = {};
this._hasTaskErrors = false;
this.apiMethodWasCalled = new flag_list_1.default([
option_names_1.default.src,
option_names_1.default.browsers,
option_names_1.default.reporter,
option_names_1.default.clientScripts,
]);
}
_createBootstrapper(browserConnectionGateway, compilerService, messageBus, configuration) {
return new bootstrapper_1.default({ browserConnectionGateway, compilerService, messageBus, configuration });
}
_disposeBrowserSet(browserSet) {
return browserSet.dispose().catch(e => DEBUG_LOGGER(e));
}
_disposeReporters(reporters) {
return Promise.all(reporters.map(reporter => reporter.dispose().catch(e => DEBUG_LOGGER(e))));
}
_disposeTestedApp(testedApp) {
return testedApp ? testedApp.kill().catch(e => DEBUG_LOGGER(e)) : Promise.resolve();
}
async _disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp, runnableConfigurationId) {
task.abort();
task.unRegisterClientScriptRouting();
task.clearListeners();
this._messageBus.abort();
await this._finalizeCompilerServiceState(task, runnableConfigurationId);
await this._disposeAssets(browserSet, reporters, testedApp);
}
_disposeAssets(browserSet, reporters, testedApp) {
return Promise.all([
this._disposeBrowserSet(browserSet),
this._disposeReporters(reporters),
this._disposeTestedApp(testedApp),
]);
}
_prepareArrayParameter(array) {
array = (0, lodash_1.flattenDeep)(array);
if (this.isCli)
return array.length === 0 ? void 0 : array;
return array;
}
_createCancelablePromise(taskPromise) {
const promise = taskPromise.then(({ completionPromise }) => completionPromise);
const removeFromPending = () => (0, lodash_1.pull)(this.pendingTaskPromises, promise);
promise
.then(removeFromPending)
.catch(removeFromPending);
promise.cancel = () => taskPromise
.then(({ cancelTask }) => cancelTask())
.then(removeFromPending);
this.pendingTaskPromises.push(promise);
return promise;
}
async _finalizeCompilerServiceState(task, runnableConfigurationId) {
var _a;
if (!this.compilerService)
return;
await ((_a = this.compilerService) === null || _a === void 0 ? void 0 : _a.removeUnitsFromState({ runnableConfigurationId }));
// NOTE: In some cases (browser restart, stop task on first fail, etc.),
// the fixture contexts may not be deleted.
// We remove all fixture context at the end of test execution to clean forgotten contexts.
const fixtureIds = (0, lodash_1.uniq)(task.tests.map(test => test.fixture.id));
await this.compilerService.removeFixtureCtxsFromState({ fixtureIds });
}
// Run task
_getFailedTestCount(task, reporter) {
let failedTestCount = reporter.taskInfo.testCount - reporter.taskInfo.passed;
if (task.opts.stopOnFirstFail && !!failedTestCount)
failedTestCount = 1;
return failedTestCount;
}
async _getTaskResult(task, browserSet, reporters, testedApp, runnableConfigurationId) {
if (!task.opts.live) {
task.on('browser-job-done', async (job) => {
await Promise.all(job.browserConnections.map(async (bc) => {
await browserSet.releaseConnection(bc);
}));
});
}
this._messageBus.clearListeners('error');
const browserSetErrorPromise = (0, promisify_event_1.default)(browserSet, 'error');
const taskErrorPromise = (0, promisify_event_1.default)(task, 'error');
const messageBusErrorPromise = (0, promisify_event_1.default)(this._messageBus, 'error');
const streamController = new reporter_stream_controller_1.default(this._messageBus, reporters);
const taskDonePromise = this._messageBus.once('done')
.then(() => browserSetErrorPromise.cancel())
.then(() => {
return Promise.all(reporters.map(reporter => reporter.taskInfo.pendingTaskDonePromise));
});
const promises = [
taskDonePromise,
browserSetErrorPromise,
taskErrorPromise,
messageBusErrorPromise,
];
if (testedApp)
promises.push(testedApp.errorPromise);
try {
await Promise.race(promises);
}
catch (err) {
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp, runnableConfigurationId);
throw err;
}
await this._disposeAssets(browserSet, reporters, testedApp);
await this._finalizeCompilerServiceState(task, runnableConfigurationId);
if (streamController.multipleStreamError)
throw streamController.multipleStreamError;
return this._getFailedTestCount(task, reporters[0]);
}
_createTask(tests, browserConnectionGroups, proxy, opts, warningLog) {
return new task_1.default({
tests,
browserConnectionGroups,
proxy,
opts,
runnerWarningLog: warningLog,
compilerService: this.compilerService,
messageBus: this._messageBus,
});
}
_runTask({ reporters, browserSet, tests, testedApp, options, runnableConfigurationId }) {
const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, options, this.warningLog);
const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp, runnableConfigurationId);
let completed = false;
this._messageBus.on('start', handle_errors_1.startHandlingTestErrors);
if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
this._messageBus.on('test-run-start', handle_errors_1.addRunningTest);
this._messageBus.on('test-run-done', ({ errs }) => {
if (errs.length)
this._hasTaskErrors = true;
(0, handle_errors_1.removeRunningTest)();
});
}
this._messageBus.on('done', handle_errors_1.stopHandlingTestErrors);
task.on('error', handle_errors_1.stopHandlingTestErrors);
const onTaskCompleted = () => {
task.unRegisterClientScriptRouting();
completed = true;
};
completionPromise
.then(onTaskCompleted)
.catch(onTaskCompleted);
const cancelTask = async () => {
if (!completed)
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp, runnableConfigurationId);
};
return { completionPromise, cancelTask };
}
_registerAssets(assets) {
assets.forEach(asset => this.proxy.GET(asset.path, asset.info));
}
_validateDebugLogger() {
const debugLogger = this.configuration.getOption(option_names_1.default.debugLogger);
const debugLoggerDefinedCorrectly = debugLogger === null || !!debugLogger &&
['showBreakpoint', 'hideBreakpoint'].every(method => method in debugLogger && (0, lodash_1.isFunction)(debugLogger[method]));
if (!debugLoggerDefinedCorrectly) {
this.configuration.mergeOptions({
[option_names_1.default.debugLogger]: debug_logger_1.default,
});
}
}
_validateSpeedOption() {
const speed = this.configuration.getOption(option_names_1.default.speed);
if (speed === void 0)
return;
if (typeof speed !== 'number' || isNaN(speed) || speed < 0.01 || speed > 1)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSpeedValue);
}
_validateConcurrencyOption() {
const concurrency = this.configuration.getOption(option_names_1.default.concurrency);
if (concurrency === void 0)
return;
if (typeof concurrency !== 'number' || isNaN(concurrency) || concurrency < 1)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidConcurrencyFactor);
if (concurrency > 1 && this.bootstrapper.browsers.some(browser => {
return browser instanceof connection_1.default
? browser.browserInfo.browserOption.cdpPort
: browser.browserOption.cdpPort;
}))
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetConcurrencyWithCDPPort);
}
_validateSkipJsErrorsOption() {
const skipJsErrorsOptions = this.configuration.getOption(option_names_1.default.skipJsErrors);
if (!skipJsErrorsOptions)
return;
(0, skip_js_errors_1.validateSkipJsErrorsOptionValue)(skipJsErrorsOptions, runtime_1.GeneralError);
}
_validateCustomActionsOption() {
const customActions = this.configuration.getOption(option_names_1.default.customActions);
if (!customActions)
return;
if (typeof customActions !== 'object')
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidCustomActionsOptionType);
for (const name in customActions) {
if (typeof customActions[name] !== 'function')
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidCustomActionType, name, typeof customActions[name]);
}
}
async _validateBrowsers() {
const browsers = this.configuration.getOption(option_names_1.default.browsers);
if (!browsers || Array.isArray(browsers) && !browsers.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.browserNotSet);
if (os_family_1.default.mac)
await this._checkRequiredPermissions(browsers);
if (os_family_1.default.linux && !(0, detect_display_1.default)())
await this._checkThatTestsCanRunWithoutDisplay(browsers);
}
_validateRequestTimeoutOption(optionName) {
const requestTimeout = this.configuration.getOption(optionName);
if (requestTimeout === void 0)
return;
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumber, null, `"${optionName}" option`, requestTimeout);
}
_validateProxyBypassOption() {
let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
if (proxyBypass === void 0)
return;
(0, type_assertions_1.assertType)([type_assertions_1.is.string, type_assertions_1.is.array], null, 'The "proxyBypass" argument', proxyBypass);
if (typeof proxyBypass === 'string')
proxyBypass = [proxyBypass];
proxyBypass = proxyBypass.reduce((arr, rules) => {
(0, type_assertions_1.assertType)(type_assertions_1.is.string, null, 'The "proxyBypass" argument', rules);
return arr.concat(rules.split(','));
}, []);
this.configuration.mergeOptions({ proxyBypass });
}
_getScreenshotOptions() {
let { path, pathPattern, takeOnFails } = this.configuration.getOption(option_names_1.default.screenshots) || {};
if (!path)
path = this.configuration.getOption(option_names_1.default.screenshotPath);
if (!pathPattern)
pathPattern = this.configuration.getOption(option_names_1.default.screenshotPathPattern);
if (!takeOnFails)
takeOnFails = false;
return { path, pathPattern, takeOnFails };
}
_validateScreenshotOptions() {
const { path, pathPattern } = this._getScreenshotOptions();
const disableScreenshots = this.configuration.getOption(option_names_1.default.disableScreenshots) || !path;
this.configuration.mergeOptions({ [option_names_1.default.disableScreenshots]: disableScreenshots });
if (disableScreenshots)
return;
if (path) {
this._validateScreenshotPath(path, 'screenshots base directory path');
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { path: (0, path_1.resolve)(path) } });
}
if (pathPattern) {
this._validateScreenshotPath(pathPattern, 'screenshots path pattern');
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPattern } });
}
}
async _validateVideoOptions() {
const videoPath = this.configuration.getOption(option_names_1.default.videoPath);
const videoEncodingOptions = this.configuration.getOption(option_names_1.default.videoEncodingOptions);
let videoOptions = this.configuration.getOption(option_names_1.default.videoOptions);
if (!videoPath) {
if (videoOptions || videoEncodingOptions)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetVideoOptionsWithoutBaseVideoPathSpecified);
return;
}
this.configuration.mergeOptions({ [option_names_1.default.videoPath]: (0, path_1.resolve)(videoPath) });
if (!videoOptions) {
videoOptions = {};
this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
}
if (videoOptions.ffmpegPath)
videoOptions.ffmpegPath = (0, path_1.resolve)(videoOptions.ffmpegPath);
else
videoOptions.ffmpegPath = await (0, detect_ffmpeg_1.default)();
if (!videoOptions.ffmpegPath)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
}
_validateCompilerOptions() {
const compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
if (!compilerOptions)
return;
const specifiedCompilers = Object.keys(compilerOptions);
const customizedCompilers = Object.keys(customizable_compilers_1.default);
const wrongCompilers = specifiedCompilers.filter(compiler => !customizedCompilers.includes(compiler));
if (!wrongCompilers.length)
return;
const compilerListStr = (0, string_1.getConcatenatedValuesString)(wrongCompilers, void 0, "'");
const pluralSuffix = (0, string_1.getPluralSuffix)(wrongCompilers);
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotCustomizeSpecifiedCompilers, compilerListStr, pluralSuffix);
}
_validateRetryTestPagesOption() {
const retryTestPagesOption = this.configuration.getOption(option_names_1.default.retryTestPages);
if (!retryTestPagesOption)
return;
const ssl = this.configuration.getOption(option_names_1.default.ssl);
if (ssl)
return;
const hostname = this.configuration.getOption(option_names_1.default.hostname);
if ((0, is_localhost_1.default)(hostname))
return;
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotEnableRetryTestPagesOption);
}
_validateQuarantineOptions() {
const quarantineMode = this.configuration.getOption(option_names_1.default.quarantineMode);
if (typeof quarantineMode === 'object')
(0, quarantine_1.validateQuarantineOptions)(quarantineMode);
}
async _validateRunOptions() {
this._validateDebugLogger();
this._validateScreenshotOptions();
await this._validateVideoOptions();
this._validateSpeedOption();
this._validateProxyBypassOption();
this._validateCompilerOptions();
this._validateRetryTestPagesOption();
this._validateRequestTimeoutOption(option_names_1.default.pageRequestTimeout);
this._validateRequestTimeoutOption(option_names_1.default.ajaxRequestTimeout);
this._validateQuarantineOptions();
this._validateConcurrencyOption();
this._validateSkipJsErrorsOption();
this._validateCustomActionsOption();
await this._validateBrowsers();
}
_createRunnableConfiguration() {
return this.bootstrapper
.createRunnableConfiguration()
.then(runnableConfiguration => {
this.emit('done-bootstrapping');
return runnableConfiguration;
});
}
_validateScreenshotPath(screenshotPath, pathType) {
const forbiddenCharsList = (0, check_file_path_1.default)(screenshotPath);
if (forbiddenCharsList.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, (0, utils_1.renderForbiddenCharsList)(forbiddenCharsList));
}
_setBootstrapperOptions() {
this.configuration.prepare();
this.configuration.notifyAboutOverriddenOptions(this.warningLog);
this.configuration.notifyAboutDeprecatedOptions(this.warningLog);
this.bootstrapper.sources = this.configuration.getOption(option_names_1.default.src) || this.bootstrapper.sources;
this.bootstrapper.browsers = this.configuration.getOption(option_names_1.default.browsers) || this.bootstrapper.browsers;
this.bootstrapper.concurrency = this.configuration.getOption(option_names_1.default.concurrency);
this.bootstrapper.appCommand = this.configuration.getOption(option_names_1.default.appCommand) || this.bootstrapper.appCommand;
this.bootstrapper.appInitDelay = this.configuration.getOption(option_names_1.default.appInitDelay);
this.bootstrapper.filter = this.configuration.getOption(option_names_1.default.filter) || this.bootstrapper.filter;
this.bootstrapper.reporters = this.configuration.getOption(option_names_1.default.reporter) || this.bootstrapper.reporters;
this.bootstrapper.tsConfigPath = this.configuration.getOption(option_names_1.default.tsConfigPath);
this.bootstrapper.clientScripts = this.configuration.getOption(option_names_1.default.clientScripts) || this.bootstrapper.clientScripts;
this.bootstrapper.disableMultipleWindows = this.configuration.getOption(option_names_1.default.disableMultipleWindows);
this.bootstrapper.proxyless = this.configuration.getOption(option_names_1.default.experimentalProxyless);
this.bootstrapper.compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
this.bootstrapper.browserInitTimeout = this.configuration.getOption(option_names_1.default.browserInitTimeout);
this.bootstrapper.hooks = this.configuration.getOption(option_names_1.default.hooks);
this.bootstrapper.configuration = this.configuration;
}
async _addDashboardReporterIfNeeded() {
const dashboardOptions = await this._getDashboardOptions();
let reporterOptions = this.configuration.getOption(option_names_1.default.reporter);
// NOTE: we should send reports when sendReport is undefined
// TODO: make this option binary instead of tri-state
if (!dashboardOptions.token || dashboardOptions.sendReport === false)
return;
if (!reporterOptions)
reporterOptions = [];
const dashboardReporter = reporterOptions.find(reporter => reporter.name === DASHBOARD_REPORTER_NAME);
if (!dashboardReporter)
reporterOptions.push({ name: DASHBOARD_REPORTER_NAME, options: dashboardOptions });
else
dashboardReporter.options = dashboardOptions;
this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporterOptions });
}
_turnOnScreenshotsIfNeeded() {
const { takeOnFails } = this._getScreenshotOptions();
const reporterOptions = this.configuration.getOption(option_names_1.default.reporter);
if (!takeOnFails && reporterOptions && (0, lodash_1.castArray)(reporterOptions).some(reporter => reporter.name === DASHBOARD_REPORTER_NAME))
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { takeOnFails: true, autoTakeOnFails: true } });
}
async _getDashboardOptions() {
const storageOptions = await this._loadDashboardOptionsFromStorage();
const configOptions = this.configuration.getOption(option_names_1.default.dashboard);
const envOptions = (0, get_env_options_1.default)();
return (0, lodash_1.merge)({}, storageOptions, configOptions, envOptions);
}
async _loadDashboardOptionsFromStorage() {
const storage = new config_storage_1.default();
await storage.load();
return storage.options;
}
async _prepareClientScripts(tests, clientScripts) {
return Promise.all(tests.map(async (test) => {
if (test.isLegacy)
return;
let loadedTestClientScripts = await (0, load_1.default)(test.clientScripts, (0, path_1.dirname)(test.testFile.filename));
loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
test.clientScripts = (0, utils_2.setUniqueUrls)(loadedTestClientScripts);
}));
}
async _hasLocalBrowsers(browserInfo) {
for (const browser of browserInfo) {
if (browser instanceof connection_1.default)
continue;
if (await browser.provider.isLocalBrowser(void 0, browser.browserName))
return true;
}
return false;
}
async _checkRequiredPermissions(browserInfo) {
const hasLocalBrowsers = await this._hasLocalBrowsers(browserInfo);
const { error } = await (0, authentication_helper_1.default)(() => (0, testcafe_browser_tools_1.findWindow)(''), testcafe_browser_tools_1.errors.UnableToAccessScreenRecordingAPIError, {
interactive: hasLocalBrowsers && !is_ci_1.default,
});
if (!error)
return;
if (hasLocalBrowsers)
throw error;
remote_1.default.canDetectLocalBrowsers = false;
}
async _checkThatTestsCanRunWithoutDisplay(browserInfoSource) {
for (let browserInfo of browserInfoSource) {
if (browserInfo instanceof connection_1.default)
browserInfo = browserInfo.browserInfo;
const isLocalBrowser = await browserInfo.provider.isLocalBrowser(void 0, browserInfo.browserName);
const isHeadlessBrowser = await browserInfo.provider.isHeadlessBrowser(void 0, browserInfo.browserName);
if (isLocalBrowser && !isHeadlessBrowser) {
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotRunLocalNonHeadlessBrowserWithoutDisplay, browserInfo.alias);
}
}
}
async _setConfigurationOptions() {
await this.configuration.asyncMergeOptions(this._options);
}
// API
embeddingOptions(opts) {
const { assets, TestRunCtor } = opts;
this._registerAssets(assets);
this._options.TestRunCtor = TestRunCtor;
return this;
}
src(...sources) {
if (this.apiMethodWasCalled.src)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
this._options[option_names_1.default.src] = this._prepareArrayParameter(sources);
this.apiMethodWasCalled.src = true;
return this;
}
browsers(...browsers) {
if (this.apiMethodWasCalled.browsers)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.browsers);
this._options.browsers = this._prepareArrayParameter(browsers);
this.apiMethodWasCalled.browsers = true;
return this;
}
concurrency(concurrency) {
this._options.concurrency = concurrency;
return this;
}
reporter(name, output) {
if (this.apiMethodWasCalled.reporter)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.reporter);
this._options[option_names_1.default.reporter] = this._prepareArrayParameter((0, prepare_reporters_1.default)(name, output));
this.apiMethodWasCalled.reporter = true;
return this;
}
filter(filter) {
this._options.filter = filter;
return this;
}
useProxy(proxy, proxyBypass) {
this._options.proxy = proxy;
this._options.proxyBypass = proxyBypass;
return this;
}
screenshots(...options) {
let fullPage;
let thumbnails;
let [path, takeOnFails, pathPattern] = options;
if (options.length === 1 && options[0] && typeof options[0] === 'object')
({ path, takeOnFails, pathPattern, fullPage, thumbnails } = options[0]);
this._options.screenshots = { path, takeOnFails, pathPattern, fullPage, thumbnails };
return this;
}
video(path, options, encodingOptions) {
this._options[option_names_1.default.videoPath] = path;
this._options[option_names_1.default.videoOptions] = options;
this._options[option_names_1.default.videoEncodingOptions] = encodingOptions;
return this;
}
startApp(command, initDelay) {
this._options[option_names_1.default.appCommand] = command;
this._options[option_names_1.default.appInitDelay] = initDelay;
return this;
}
tsConfigPath(path) {
this._options[option_names_1.default.tsConfigPath] = path;
return this;
}
clientScripts(...scripts) {
if (this.apiMethodWasCalled.clientScripts)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.clientScripts);
this._options[option_names_1.default.clientScripts] = this._prepareArrayParameter(scripts);
this.apiMethodWasCalled.clientScripts = true;
return this;
}
compilerOptions(opts) {
this._options[option_names_1.default.compilerOptions] = opts;
return this;
}
run(options = {}) {
let reporters;
this.apiMethodWasCalled.reset();
this._messageBus.clearListeners();
const messageBusErrorPromise = (0, promisify_event_1.default)(this._messageBus, 'error');
this._options = Object.assign(this._options, options);
const runTaskPromise = Promise.resolve()
.then(() => this._setConfigurationOptions())
.then(async () => {
await this._addDashboardReporterIfNeeded();
await this._turnOnScreenshotsIfNeeded();
})
.then(() => reporter_1.default.getReporterPlugins(this.configuration.getOption(option_names_1.default.reporter)))
.then(reporterPlugins => {
reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, this._messageBus, reporter.outStream, reporter.name));
return Promise.all(reporters.map(reporter => reporter.init()));
})
.then(() => this._setBootstrapperOptions())
.then(() => {
(0, log_entry_1.default)(DEBUG_LOGGER, this.configuration);
return this._validateRunOptions();
})
.then(() => this._createRunnableConfiguration())
.then(async ({ browserSet, tests, testedApp, commonClientScripts, id }) => {
var _a, _b;
await this._prepareClientScripts(tests, commonClientScripts);
const dashboardReporter = (_a = reporters.find(r => r.plugin.name === 'dashboard')) === null || _a === void 0 ? void 0 : _a.plugin;
const dashboardUrl = (dashboardReporter === null || dashboardReporter === void 0 ? void 0 : dashboardReporter.getReportUrl) ? dashboardReporter.getReportUrl() : '';
const resultOptions = Object.assign(Object.assign({}, this.configuration.getOptions()), { dashboardUrl });
await ((_b = this.bootstrapper.compilerService) === null || _b === void 0 ? void 0 : _b.setOptions({ value: resultOptions }));
return this._runTask({
reporters,
browserSet,
tests,
testedApp,
options: resultOptions,
runnableConfigurationId: id,
});
});
const promises = [
runTaskPromise,
messageBusErrorPromise,
];
return this._createCancelablePromise(Promise.race(promises));
}
async stop() {
// NOTE: When taskPromise is cancelled, it is removed from
// the pendingTaskPromises array, which leads to shifting indexes
// towards the beginning. So, we must copy the array in order to iterate it,
// or we can perform iteration from the end to the beginning.
const cancellationPromises = this.pendingTaskPromises.reduceRight((result, taskPromise) => {
result.push(taskPromise.cancel());
return result;
}, []);
await Promise.all(cancellationPromises);
}
}
exports.default = Runner;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVEO0FBQ3ZELGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsbUNBQXNDO0FBQ3RDLGlGQUFpRTtBQUVqRSxtQ0FPZ0I7QUFFaEIsa0VBQTBDO0FBQzFDLDJEQUFtQztBQUNuQyxrREFBMEI7QUFDMUIsaUZBQStEO0FBQy9ELCtDQUFpRDtBQUNqRCwyQ0FBaUQ7QUFDakQsdUVBQW1FO0FBQ25FLG9EQUFvRTtBQUNwRSwyRUFBa0Q7QUFDbEQsK0VBQXFEO0FBQ3JELDBEQUtnQztBQUVoQyxpRkFBeUQ7QUFDekQsbUVBQTBDO0FBQzFDLG1GQUEwRDtBQUMxRCx5RUFBOEQ7QUFDOUQsMERBQStEO0FBQy9ELDhGQUFvRTtBQUNwRSxxR0FBNEU7QUFDNUUsNENBQStFO0FBQy9FLHlFQUFnRDtBQUNoRCwrRUFBc0Q7QUFDdEQseUZBQWdFO0FBQ2hFLG1FQUE0RDtBQUM1RCxrREFBeUI7QUFDekIsaUZBQXdFO0FBQ3hFLHVFQUFzRDtBQUN0RCwwREFBMkI7QUFDM0IsNkVBQW9EO0FBQ3BELGdFQUE0RTtBQUM1RSxtRUFBMEM7QUFDMUMsdUVBQThDO0FBQzlDLG1GQUF5RDtBQUN6RCx3RUFBc0Y7QUFFdEYsTUFBTSxZQUFZLEdBQWMsSUFBQSxlQUFLLEVBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUN6RCxNQUFNLHVCQUF1QixHQUFHLFdBQVcsQ0FBQztBQUU1QyxNQUFxQixNQUFPLFNBQVEscUJBQVk7SUFDNUMsWUFBYSxFQUFFLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFO1FBQzVFLEtBQUssRUFBRSxDQUFDO1FBRVIsSUFBSSxDQUFDLFdBQVcsR0FBVyxJQUFJLHFCQUFVLEVBQUUsQ0FBQztRQUM1QyxJQUFJLENBQUMsS0FBSyxHQUFpQixLQUFLLENBQUM7UUFDakMsSUFBSSxDQUFDLFlBQVksR0FBVSxJQUFJLENBQUMsbUJBQW1CLENBQUMsd0JBQXdCLEVBQUUsZUFBZSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDaEksSUFBSSxDQUFDLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsYUFBYSxHQUFTLGFBQWEsQ0FBQztRQUN6QyxJQUFJLENBQUMsS0FBSyxHQUFpQixhQUFhLENBQUMsUUFBUSxJQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1FBQ2xGLElBQUksQ0FBQyxVQUFVLEdBQVksSUFBSSxxQkFBVSxDQUFDLElBQUksRUFBRSxxQkFBVSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3ZHLElBQUksQ0FBQyxlQUFlLEdBQU8sZUFBZSxDQUFDO1FBQzNDLElBQUksQ0FBQyxRQUFRLEdBQWMsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxjQUFjLEdBQVEsS0FBSyxDQUFDO1FBRWpDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLG1CQUFRLENBQUM7WUFDbkMsc0JBQVksQ0FBQyxHQUFHO1lBQ2hCLHNCQUFZLENBQUMsUUFBUTtZQUNyQixzQkFBWSxDQUFDLFFBQVE7WUFDckIsc0JBQVksQ0FBQyxhQUFhO1NBQzdCLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxtQkFBbUIsQ0FBRSx3QkFBd0IsRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLGFBQWE7UUFDckYsT0FBTyxJQUFJLHNCQUFZLENBQUMsRUFBRSx3QkFBd0IsRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUM7SUFDdEcsQ0FBQztJQUVELGtCQUFrQixDQUFFLFVBQVU7UUFDMUIsT0FBTyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVELGlCQUFpQixDQUFFLFNBQVM7UUFDeEIsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFFRCxpQkFBaUIsQ0FBRSxTQUFTO1FBQ3hCLE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUN4RixDQUFDO0lBRUQsS0FBSyxDQUFDLDRCQUE0QixDQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSx1QkFBdUI7UUFDL0YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2IsSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFekIsTUFBTSxJQUFJLENBQUMsNkJBQTZCLENBQUMsSUFBSSxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDeEUsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELGNBQWMsQ0FBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFNBQVM7UUFDNUMsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDO1lBQ2YsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQztZQUNuQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7U0FDcEMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELHNCQUFzQixDQUFFLEtBQUs7UUFDekIsS0FBSyxHQUFHLElBQUEsb0JBQU8sRUFBQyxLQUFLLENBQUMsQ0FBQztRQUV2QixJQUFJLElBQUksQ0FBQyxLQUFLO1lBQ1YsT0FBTyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUUvQyxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQsd0JBQXdCLENBQUUsV0FBVztRQUNqQyxNQUFNLE9BQU8sR0FBYSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3pGLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBQSxhQUFNLEVBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRTFFLE9BQU87YUFDRixJQUFJLENBQUMsaUJBQWlCLENBQUM7YUFDdkIsS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFOUIsT0FBTyxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxXQUFXO2FBQzdCLElBQUksQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFDO2FBQ3RDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRTdCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFdkMsT0FBTyxPQUFPLENBQUM7SUFDbkIsQ0FBQztJQUVELEtBQUssQ0FBQyw2QkFBNkIsQ0FBRSxJQUFJLEVBQUUsdUJBQXVCOztRQUM5RCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWU7WUFDckIsT0FBTztRQUVYLE1BQU0sQ0FBQSxNQUFBLElBQUksQ0FBQyxlQUFlLDBDQUFFLG9CQUFvQixDQUFDLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQyxDQUFBLENBQUM7UUFFOUUsd0VBQXdFO1FBQ3hFLDJDQUEyQztRQUMzQywwRkFBMEY7UUFDMUYsTUFBTSxVQUFVLEdBQUcsSUFBQSxhQUFJLEVBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFakUsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLDBCQUEwQixDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQsV0FBVztJQUNYLG1CQUFtQixDQUFFLElBQUksRUFBRSxRQUFRO1FBQy9CLElBQUksZUFBZSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO1FBRTdFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxDQUFDLGVBQWU7WUFDOUMsZUFBZSxHQUFHLENBQUMsQ0FBQztRQUV4QixPQUFPLGVBQWUsQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLGNBQWMsQ0FBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsdUJBQXVCO1FBQ2pGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNqQixJQUFJLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFLEtBQUssRUFBQyxHQUFHLEVBQUMsRUFBRTtnQkFDcEMsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFDLEVBQUUsRUFBQyxFQUFFO29CQUNwRCxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDM0MsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNSLENBQUMsQ0FBQyxDQUFDO1NBQ047UUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUV6QyxNQUFNLHNCQUFzQixHQUFHLElBQUEseUJBQWMsRUFBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkUsTUFBTSxnQkFBZ0IsR0FBUyxJQUFBLHlCQUFjLEVBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdELE1BQU0sc0JBQXNCLEdBQUcsSUFBQSx5QkFBYyxFQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekUsTUFBTSxnQkFBZ0IsR0FBUyxJQUFJLG9DQUF3QixDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFekYsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO2FBQ2hELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQzthQUMzQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ1AsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztRQUM1RixDQUFDLENBQUMsQ0FBQztRQUVQLE1BQU0sUUFBUSxHQUFHO1lBQ2IsZUFBZTtZQUNmLHNCQUFzQjtZQUN0QixnQkFBZ0I7WUFDaEIsc0JBQXNCO1NBQ3pCLENBQUM7UUFFRixJQUFJLFNBQVM7WUFDVCxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUUxQyxJQUFJO1lBQ0EsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ2hDO1FBQ0QsT0FBTyxHQUFHLEVBQUU7WUFDUixNQUFNLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUV6RyxNQUFNLEdBQUcsQ0FBQztTQUNiO1FBRUQsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDNUQsTUFBTSxJQUFJLENBQUMsNkJBQTZCLENBQUMsSUFBSSxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFFeEUsSUFBSSxnQkFBZ0IsQ0FBQyxtQkFBbUI7WUFDcEMsTUFBTSxnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQztRQUUvQyxPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELFdBQVcsQ0FBRSxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFVO1FBQ2hFLE9BQU8sSUFBSSxjQUFJLENBQUM7WUFDWixLQUFLO1lBQ0wsdUJBQXVCO1lBQ3ZCLEtBQUs7WUFDTCxJQUFJO1lBQ0osZ0JBQWdCLEVBQUUsVUFBVTtZQUM1QixlQUFlLEVBQUcsSUFBSSxDQUFDLGVBQWU7WUFDdEMsVUFBVSxFQUFRLElBQUksQ0FBQyxXQUFXO1NBQ3JDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxRQUFRLENBQUUsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFO1FBQ25GLE1BQU0sSUFBSSxHQUFnQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzVILE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztRQUMvRyxJQUFJLFNBQVMsR0FBYSxLQUFLLENBQUM7UUFFaEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLHVDQUF1QixDQUFDLENBQUM7UUFFdEQsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsa0JBQWtCLENBQUMsRUFBRTtZQUNoRSxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSw4QkFBYyxDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFO2dCQUM5QyxJQUFJLElBQUksQ0FBQyxNQUFNO29CQUNYLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUUvQixJQUFBLGlDQUFpQixHQUFFLENBQUM7WUFDeEIsQ0FBQyxDQUFDLENBQUM7U0FDTjtRQUVELElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxzQ0FBc0IsQ0FBQyxDQUFDO1FBRXBELElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLHNDQUFzQixDQUFDLENBQUM7UUFFekMsTUFBTSxlQUFlLEdBQUcsR0FBRyxFQUFFO1lBQ3pCLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1lBRXJDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQyxDQUFDO1FBRUYsaUJBQWlCO2FBQ1osSUFBSSxDQUFDLGVBQWUsQ0FBQzthQUNyQixLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFNUIsTUFBTSxVQUFVLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDMUIsSUFBSSxDQUFDLFNBQVM7Z0JBQ1YsTUFBTSxJQUFJLENBQUMsNEJBQTRCLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDakgsQ0FBQyxDQUFDO1FBRUYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzdDLENBQUM7SUFFRCxlQUFlLENBQUUsTUFBTTtRQUNuQixNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQsb0JBQW9CO1FBQ2hCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFM0UsTUFBTSwyQkFBMkIsR0FBRyxXQUFXLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxXQUFXO1lBQ3JFLENBQUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLElBQUksV0FBVyxJQUFJLElBQUEsbUJBQVUsRUFBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRW5ILElBQUksQ0FBQywyQkFBMkIsRUFBRTtZQUM5QixJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztnQkFDNUIsQ0FBQyxzQkFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLHNCQUFrQjthQUNqRCxDQUFDLENBQUM7U0FDTjtJQUNMLENBQUM7SUFFRCxvQkFBb0I7UUFDaEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUvRCxJQUFJLEtBQUssS0FBSyxLQUFLLENBQUM7WUFDaEIsT0FBTztRQUVYLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLEdBQUcsSUFBSSxJQUFJLEtBQUssR0FBRyxDQUFDO1lBQ3RFLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQsMEJBQTBCO1FBQ3RCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFM0UsSUFBSSxXQUFXLEtBQUssS0FBSyxDQUFDO1lBQ3RCLE9BQU87UUFFWCxJQUFJLE9BQU8sV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksV0FBVyxHQUFHLENBQUM7WUFDeEUsTUFBTSxJQUFJLHNCQUFZLENBQUMsc0JBQWMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBRXBFLElBQUksV0FBVyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDN0QsT0FBTyxPQUFPLFlBQVksb0JBQWlCO2dCQUN2QyxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsT0FBTztnQkFDM0MsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO1FBQ3hDLENBQUMsQ0FBQztZQUNFLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQsMkJBQTJCO1FBQ3ZCLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUVwRixJQUFJLENBQUMsbUJBQW1CO1lBQ3BCLE9BQU87UUFFWCxJQUFBLGdEQUErQixFQUFDLG1CQUFtQixFQUFFLHNCQUFZLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBRUQsNEJBQTRCO1FBQ3hCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFL0UsSUFBSSxDQUFDLGFBQWE7WUFDZCxPQUFPO1FBRVgsSUFBSSxPQUFPLGFBQWEsS0FBSyxRQUFRO1lBQ2pDLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUUxRSxLQUFLLE1BQU0sSUFBSSxJQUFJLGFBQWEsRUFBRTtZQUM5QixJQUFJLE9BQU8sYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLLFVBQVU7Z0JBQ3pDLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxFQUFFLE9BQU8sYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDeEc7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQjtRQUNuQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXJFLElBQUksQ0FBQyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNO1lBQ3hELE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFekQsSUFBSSxtQkFBRSxDQUFDLEdBQUc7WUFDTixNQUFNLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVuRCxJQUFJLG1CQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBQSx3QkFBYSxHQUFFO1lBQzVCLE1BQU0sSUFBSSxDQUFDLG1DQUFtQyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFFRCw2QkFBNkIsQ0FBRSxVQUFVO1FBQ3JDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRWhFLElBQUksY0FBYyxLQUFLLEtBQUssQ0FBQztZQUN6QixPQUFPO1FBRVgsSUFBQSw0QkFBVSxFQUFDLG9CQUFFLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLElBQUksVUFBVSxVQUFVLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDckYsQ0FBQztJQUVELDBCQUEwQjtRQUN0QixJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRXpFLElBQUksV0FBVyxLQUFLLEtBQUssQ0FBQztZQUN0QixPQUFPO1FBRVgsSUFBQSw0QkFBVSxFQUFDLENBQUUsb0JBQUUsQ0FBQyxNQUFNLEVBQUUsb0JBQUUsQ0FBQyxLQUFLLENBQUUsRUFBRSxJQUFJLEVBQUUsNEJBQTRCLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFckYsSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRO1lBQy9CLFdBQVcsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWhDLFdBQVcsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQzVDLElBQUEsNEJBQVUsRUFBQyxvQkFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsNEJBQTRCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFakUsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4QyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFUCxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELHFCQUFxQjtRQUNqQixJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV0RyxJQUFJLENBQUMsSUFBSTtZQUNMLElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRXJFLElBQUksQ0FBQyxXQUFXO1lBQ1osV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUVuRixJQUFJLENBQUMsV0FBVztZQUNaLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFFeEIsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7SUFDOUMsQ0FBQztJQUVELDBCQUEwQjtRQUN0QixNQUFNLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRTNELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBRWxHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxzQkFBWSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBRTNGLElBQUksa0JBQWtCO1lBQ2xCLE9BQU87UUFFWCxJQUFJLElBQUksRUFBRTtZQUNOLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztZQUV0RSxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsc0JBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFBLGNBQVcsRUFBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztTQUNoRztRQUVELElBQUksV0FBVyxFQUFFO1lBQ2IsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1lBRXRFLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxzQkFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQ3BGO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxxQkFBcUI7UUFDdkIsTUFBTSxTQUFTLEdBQWMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUU3RixJQUFJLFlBQVksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRTNFLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDWixJQUFJLFlBQVksSUFBSSxvQkFBb0I7Z0JBQ3BDLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsa0RBQWtELENBQUMsQ0FBQztZQUU5RixPQUFPO1NBQ1Y7UUFFRCxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsc0JBQVksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFBLGNBQVcsRUFBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFdEYsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNmLFlBQVksR0FBRyxFQUFFLENBQUM7WUFFbEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLHNCQUFZLENBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztTQUNsRjtRQUVELElBQUksWUFBWSxDQUFDLFVBQVU7WUFDdkIsWUFBWSxDQUFDLFVBQVUsR0FBRyxJQUFBLGNBQVcsRUFBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7O1lBRS9ELFlBQVksQ0FBQyxVQUFVLEdBQUcsTUFBTSxJQUFBLHVCQUFZLEdBQUUsQ0FBQztRQUVuRCxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVU7WUFDeEIsTUFBTSxJQUFJLHNCQUFZLENBQUMsc0JBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCx3QkFBd0I7UUFDcEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUVuRixJQUFJLENBQUMsZUFBZTtZQUNoQixPQUFPO1FBRVgsTUFBTSxrQkFBa0IsR0FBSSxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxnQ0FBcUIsQ0FBQyxDQUFDO1FBQy9ELE1BQU0sY0FBYyxHQUFRLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFM0csSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNO1lBQ3RCLE9BQU87UUFFWCxNQUFNLGVBQWUsR0FBRyxJQUFBLG9DQUEyQixFQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNqRixNQUFNLFlBQVksR0FBTSxJQUFBLHdCQUFlLEVBQUMsY0FBYyxDQUFDLENBQUM7UUFFeEQsTUFBTSxJQUFJLHNCQUFZLENBQUMsc0JBQWMsQ0FBQyxpQ0FBaUMsRUFBRSxlQUFlLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDNUcsQ0FBQztJQUVELDZCQUE2QjtRQUN6QixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFdkYsSUFBSSxDQUFDLG9CQUFvQjtZQUNyQixPQUFPO1FBRVgsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUzRCxJQUFJLEdBQUc7WUFDSCxPQUFPO1FBRVgsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVyRSxJQUFJLElBQUEsc0JBQVcsRUFBQyxRQUFRLENBQUM7WUFDckIsT0FBTztRQUVYLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsMEJBQTBCO1FBQ3RCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFakYsSUFBSSxPQUFPLGNBQWMsS0FBSyxRQUFRO1lBQ2xDLElBQUEsc0NBQXlCLEVBQUMsY0FBYyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELEtBQUssQ0FBQyxtQkFBbUI7UUFDckIsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDbEMsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUNsQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsNkJBQTZCLENBQUMsc0JBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3BFLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxzQkFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDbEMsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDbEMsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7UUFDbkMsSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7UUFDcEMsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsNEJBQTRCO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLFlBQVk7YUFDbkIsMkJBQTJCLEVBQUU7YUFDN0IsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEVBQUU7WUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBRWhDLE9BQU8scUJBQXFCLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQsdUJBQXVCLENBQUUsY0FBYyxFQUFFLFFBQVE7UUFDN0MsTUFBTSxrQkFBa0IsR0FBRyxJQUFBLHlCQUFhLEVBQUMsY0FBYyxDQUFDLENBQUM7UUFFekQsSUFBSSxrQkFBa0IsQ0FBQyxNQUFNO1lBQ3pCLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsa0NBQWtDLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxJQUFBLGdDQUF3QixFQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztJQUMxSixDQUFDO0lBRUQsdUJBQXVCO1FBQ25CLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLGFBQWEsQ0FBQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLEdBQWtCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7UUFDdkgsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEdBQWlCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7UUFDN0gsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEdBQWMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNsRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsR0FBZSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDO1FBQ2pJLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxHQUFhLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbkcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQW1CLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUM7UUFDekgsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLEdBQWdCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUM7UUFDOUgsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEdBQWEsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNuRyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsR0FBWSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDO1FBQ3ZJLElBQUksQ0FBQyxZQUFZLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQzdHLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxHQUFnQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDNUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLEdBQVUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUN0RyxJQUFJLENBQUMsWUFBWSxDQUFDLGtCQUFrQixHQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN6RyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssR0FBb0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1RixJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsR0FBWSxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQ2xFLENBQUM7SUFFRCxLQUFLLENBQUMsNkJBQTZCO1FBQy9CLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUMzRCxJQUFJLGVBQWUsR0FBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTdFLDREQUE0RDtRQUM1RCxxREFBcUQ7UUFDckQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLEtBQUssS0FBSztZQUNoRSxPQUFPO1FBRVgsSUFBSSxDQUFDLGVBQWU7WUFDaEIsZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUV6QixNQUFNLGlCQUFpQixHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLHVCQUF1QixDQUFDLENBQUM7UUFFdEcsSUFBSSxDQUFDLGlCQUFpQjtZQUNsQixlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7O1lBRW5GLGlCQUFpQixDQUFDLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztRQUVqRCxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsc0JBQVksQ0FBQyxRQUFRLENBQUMsRUFBRSxlQUFlLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFFRCwwQkFBMEI7UUFDdEIsTUFBTSxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ3JELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLHNCQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFNUUsSUFBSSxDQUFDLFdBQVcsSUFBSSxlQUFlLElBQUksSUFBQSxrQkFBUyxFQUFDLGVBQWUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssdUJBQXVCLENBQUM7WUFDekgsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLHNCQUFZLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEgsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0I7UUFDdEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQztRQUNyRSxNQUFNLGFBQWEsR0FBSSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxzQkFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sVUFBVSxHQUFPLElBQUEseUJBQWEsR0FBRSxDQUFDO1FBRXZDLE9BQU8sSUFBQSxjQUFLLEVBQUMsRUFBRSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELEtBQUssQ0FBQyxnQ0FBZ0M7UUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSx3QkFBc0IsRUFBRSxDQUFDO1FBRTdDLE1BQU0sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRXJCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUFFLEtBQUssRUFBRSxhQUFhO1FBQzdDLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBQyxJQUFJLEVBQUMsRUFBRTtZQUN0QyxJQUFJLElBQUksQ0FBQyxRQUFRO2dCQUNiLE9BQU87WUFFWCxJQUFJLHVCQUF1QixHQUFHLE1BQU0sSUFBQSxjQUFpQixFQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBQSxjQUFPLEVBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBRTNHLHVCQUF1QixHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUMsQ0FBQztZQUV4RSxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUEscUJBQWEsRUFBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ2hFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFFLFdBQVc7UUFDaEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxXQUFXLEVBQUU7WUFDL0IsSUFBSSxPQUFPLFlBQVksb0JBQWlCO2dCQUNwQyxTQUFTO1lBRWIsSUFBSSxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sQ0FBQyxXQUFXLENBQUM7Z0JBQ2xFLE9BQU8sSUFBSSxDQUFDO1NBQ25CO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVELEtBQUssQ0FBQyx5QkFBeUIsQ0FBRSxXQUFXO1FBQ3hDLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFbkUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBQSwrQkFBb0IsRUFDeEMsR0FBRyxFQUFFLENBQUMsSUFBQSxtQ0FBVSxFQUFDLEVBQUUsQ0FBQyxFQUNwQiwrQkFBTSxDQUFDLHFDQUFxQyxFQUM1QztZQUNJLFdBQVcsRUFBRSxnQkFBZ0IsSUFBSSxDQUFDLGVBQUk7U0FDekMsQ0FDSixDQUFDO1FBRUYsSUFBSSxDQUFDLEtBQUs7WUFDTixPQUFPO1FBRVgsSUFBSSxnQkFBZ0I7WUFDaEIsTUFBTSxLQUFLLENBQUM7UUFFaEIsZ0JBQXFCLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDO0lBQ3pELENBQUM7SUFFRCxLQUFLLENBQUMsbUNBQW1DLENBQUUsaUJBQWlCO1FBQ3hELEtBQUssSUFBSSxXQUFXLElBQUksaUJBQWlCLEVBQUU7WUFDdkMsSUFBSSxXQUFXLFlBQVksb0JBQWlCO2dCQUN4QyxXQUFXLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQztZQUUxQyxNQUFNLGNBQWMsR0FBTSxNQUFNLFdBQVcsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNyRyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sV0FBVyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFeEcsSUFBSSxjQUFjLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDdEMsTUFBTSxJQUFJLHNCQUFZLENBQ2xCLHNCQUFjLENBQUMsOENBQThDLEVBQzdELFdBQVcsQ0FBQyxLQUFLLENBQ3BCLENBQUM7YUFDTDtTQUNKO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyx3QkFBd0I7UUFDMUIsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQsTUFBTTtJQUNOLGdCQUFnQixDQUFFLElBQUk7UUFDbEIsTUFBTSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFFckMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFFeEMsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELEdBQUcsQ0FBRSxHQUFHLE9BQU87UUFDWCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHO1lBQzNCLE1BQU0sSUFBSSxzQkFBWSxDQUFDLHNCQUFjLENBQUMsOEJBQThCLEVBQUUsc0JBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU1RixJQUFJLENBQUMsUUFBUSxDQUFDLHNCQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLEdBQU8sSUFBSSxDQUFDO1FBRXZDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxRQUFRLENBQUUsR0FBRyxRQUFRO1FBQ2pCLElBQUksSUFBSSxDQUFDLGtCQUFrQixDQUFDLFFBQVE7WUFDaEMsTUFBTSxJQUFJLHNCQUFZLENBQUMsc0JBQWMsQ0FBQyw4QkFBOEIsRUFBRSxzQkFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWpHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFhLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUV4QyxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsV0FBVyxDQUFFLFdBQVc7UUFDcEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBRXhDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxRQUFRLENBQUUsSUFBSSxFQUFFLE1BQU07UUFDbEIsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUTtZQUNoQyxNQUFNLElBQUksc0JBQVksQ0FBQyxzQkFBYyxDQUFDLDhCQUE4QixFQUFFLHNCQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFakcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxzQkFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFBLDJCQUFnQixFQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ25HLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEdBQU8sSUFBSSxDQUFDO1FBRTVDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLENBQUUsTUFBTTtRQUNWLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUU5QixPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsUUFBUSxDQUFFLEtBQUssRUFBRSxXQUFXO1FBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFTLEtBQUssQ0FBQztRQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFFeEMsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELFdBQVcsQ0FBRSxHQUFHLE9BQU87UUFDbkIsSUFBSSxRQUFRLENBQUM7UUFDYixJQUFJLFVBQVUsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBQyxHQUFHLE9BQU8sQ0FBQztRQUUvQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRO1lBQ3BFLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFNUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEdBQUcsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLENBQUM7UUFFckYsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELEtBQUssQ0FBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLGVBQWU7UUFDakMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxzQkFBWSxDQUFDLFNBQVMsQ0FBQyxHQUFjLElBQUksQ0FBQztRQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLHNCQUFZLENBQUMsWUFBWSxDQUFDLEdBQVcsT0FBTyxDQUFDO1FBQzNELElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLGVBQWUsQ0FBQztRQUVuRSxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsUUFBUSxDQUFFLE9BQU8sRUFBRSxTQUFTO1FBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQVksQ0FBQyxVQUFVLENBQUMsR0FBSyxPQUFPLENBQUM7UUFDbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxzQkFBWSxDQUFDLFlBQVksQ0FBQyxHQUFHLFNBQVMsQ0FBQztRQUVyRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsWUFBWSxDQUFFLElBQUk7UUFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLHNCQUFZLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBRWhELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxhQUFhLENBQUUsR0FBRyxPQUFPO1FBQ3JCLElBQUksSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWE7WUFDckMsTUFBTSxJQUFJLHNCQUFZLENBQUMsc0JBQWMsQ0FBQyw4QkFBOEIsRUFBRSxzQkFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXRHLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQVksQ0FBQyxhQUFhLENBQUMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakYsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsR0FBTyxJQUFJLENBQUM7UUFFakQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELGVBQWUsQ0FBRSxJQUFJO1FBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQVksQ0FBQyxlQUFlLENBQUMsR0FBRyxJQUFJLENBQUM7UUFFbkQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELEdBQUcsQ0FBRSxPQUFPLEdBQUcsRUFBRTtRQUNiLElBQUksU0FBUyxDQUFDO1FBRWQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFbEMsTUFBTSxzQkFBc0IsR0FBRyxJQUFBLHlCQUFjLEVBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUV6RSxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUV0RCxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFO2FBQ25DLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQzthQUMzQyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDYixNQUFNLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1lBQzNDLE1BQU0sSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7UUFDNUMsQ0FBQyxDQUFDO2FBQ0QsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFRLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsc0JBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2FBQzVGLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRTtZQUNwQixTQUFTLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLElBQUksa0JBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUVoSSxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbkUsQ0FBQyxDQUFDO2FBQ0QsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO2FBQzFDLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDUCxJQUFBLG1CQUFRLEVBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUUzQyxPQUFPLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQ3RDLENBQUMsQ0FBQzthQUNELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsNEJBQTRCLEVBQUUsQ0FBQzthQUMvQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTs7WUFDdEUsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLG1CQUFtQixDQUFDLENBQUM7WUFFN0QsTUFBTSxpQkFBaUIsR0FBRyxNQUFBLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxXQUFXLENBQUMsMENBQUUsTUFBTSxDQUFDO1lBQ3JGLE1BQU0sWUFBWSxHQUFRLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsWUFBWSxFQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBRWxHLE1BQU0sYUFBYSxtQ0FDWixJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxLQUVsQyxZQUFZLEdBQ2YsQ0FBQztZQUVGLE1BQU0sQ0FBQSxNQUFBLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSwwQ0FBRSxVQUFVLENBQUMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQSxDQUFDO1lBRTlFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztnQkFDakIsU0FBUztnQkFDVCxVQUFVO2dCQUNWLEtBQUs7Z0JBQ0wsU0FBUztnQkFDVCxPQUFPLEVBQWtCLGFBQWE7Z0JBQ3RDLHVCQUF1QixFQUFFLEVBQUU7YUFDOUIsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7UUFFUCxNQUFNLFFBQVEsR0FBRztZQUNiLGNBQWM7WUFDZCxzQkFBc0I7U0FDekIsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDTiwwREFBMEQ7UUFDMUQsaUVBQWlFO1FBQ2pFLDRFQUE0RTtRQUM1RSw2REFBNkQ7UUFDN0QsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxFQUFFO1lBQ3RGLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFbEMsT0FBTyxNQUFNLENBQUM7UUFDbEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRVAsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDNUMsQ0FBQztDQUNKO0FBOXdCRCx5QkE4d0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVzb2x2ZSBhcyByZXNvbHZlUGF0aCwgZGlybmFtZSB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBEYXNoYm9hcmRDb25maWdTdG9yYWdlIGZyb20gJy4uL2Rhc2hib2FyZC9jb25maWctc3RvcmFnZSc7XG5cbmltcG9ydCB7XG4gICAgZmxhdHRlbkRlZXAgYXMgZmxhdHRlbixcbiAgICBwdWxsIGFzIHJlbW92ZSxcbiAgICBpc0Z1bmN0aW9uLFxuICAgIHVuaXEsXG4gICAgY2FzdEFycmF5LFxuICAgIG1lcmdlLFxufSBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQgQm9vdHN0cmFwcGVyIGZyb20gJy4vYm9vdHN0cmFwcGVyJztcbmltcG9ydCBSZXBvcnRlciBmcm9tICcuLi9yZXBvcnRlcic7XG5pbXBvcnQgVGFzayBmcm9tICcuL3Rhc2snO1xuaW1wb3J0IGRlZmF1bHREZWJ1Z0xvZ2dlciBmcm9tICcuLi9ub3RpZmljYXRpb25zL2RlYnVnLWxvZ2dlcic7XG5pbXBvcnQgeyBHZW5lcmFsRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uL2Vycm9ycy90eXBlcyc7XG5pbXBvcnQgeyBhc3NlcnRUeXBlLCBpcyB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lL3R5cGUtYXNzZXJ0aW9ucyc7XG5pbXBvcnQgeyByZW5kZXJGb3JiaWRkZW5DaGFyc0xpc3QgfSBmcm9tICcuLi9lcnJvcnMvdGVzdC1ydW4vdXRpbHMnO1xuaW1wb3J0IGRldGVjdEZGTVBFRyBmcm9tICcuLi91dGlscy9kZXRlY3QtZmZtcGVnJztcbmltcG9ydCBjaGVja0ZpbGVQYXRoIGZyb20gJy4uL3V0aWxzL2NoZWNrLWZpbGUtcGF0aCc7XG5pbXBvcnQge1xuICAgIGFkZFJ1bm5pbmdUZXN0LFxuICAgIHJlbW92ZVJ1bm5pbmdUZXN0LFxuICAgIHN0YXJ0SGFuZGxpbmdUZXN0RXJyb3JzLFxuICAgIHN0b3BIYW5kbGluZ1Rlc3RFcnJvcnMsXG59IGZyb20gJy4uL3V0aWxzL2hhbmRsZS1lcnJvcnMnO1xuXG5pbXBvcnQgT1BUSU9OX05BTUVTIGZyb20gJy4uL2NvbmZpZ3VyYXRpb24vb3B0aW9uLW5hbWVzJztcbmltcG9ydCBGbGFnTGlzdCBmcm9tICcuLi91dGlscy9mbGFnLWxpc3QnO1xuaW1wb3J0IHByZXBhcmVSZXBvcnRlcnMgZnJvbSAnLi4vdXRpbHMvcHJlcGFyZS1yZXBvcnRlcnMnO1xuaW1wb3J0IGxvYWRDbGllbnRTY3JpcHRzIGZyb20gJy4uL2N1c3RvbS1jbGllbnQtc2NyaXB0cy9sb2FkJztcbmltcG9ydCB7IHNldFVuaXF1ZVVybHMgfSBmcm9tICcuLi9jdXN0b20tY2xpZW50LXNjcmlwdHMvdXRpbHMnO1xuaW1wb3J0IFJlcG9ydGVyU3RyZWFtQ29udHJvbGxlciBmcm9tICcuL3JlcG9ydGVyLXN0cmVhbS1jb250cm9sbGVyJztcbmltcG9ydCBDdXN0b21pemFibGVDb21waWxlcnMgZnJvbSAnLi4vY29uZmlndXJhdGlvbi9jdXN0b21pemFibGUtY29tcGlsZXJzJztcbmltcG9ydCB7IGdldENvbmNhdGVuYXRlZFZhbHVlc1N0cmluZywgZ2V0UGx1cmFsU3VmZml4IH0gZnJvbSAnLi4vdXRpbHMvc3RyaW5nJztcbmltcG9ydCBpc0xvY2FsaG9zdCBmcm9tICcuLi91dGlscy9pcy1sb2NhbGhvc3QnO1xuaW1wb3J0IFdhcm5pbmdMb2cgZnJvbSAnLi4vbm90aWZpY2F0aW9ucy93YXJuaW5nLWxvZyc7XG5pbXBvcnQgYXV0aGVudGljYXRpb25IZWxwZXIgZnJvbSAnLi4vY2xpL2F1dGhlbnRpY2F0aW9uLWhlbHBlcic7XG5pbXBvcnQgeyBlcnJvcnMsIGZpbmRXaW5kb3cgfSBmcm9tICd0ZXN0Y2FmZS1icm93c2VyLXRvb2xzJztcbmltcG9ydCBpc0NJIGZyb20gJ2lzLWNpJztcbmltcG9ydCBSZW1vdGVCcm93c2VyUHJvdmlkZXIgZnJvbSAnLi4vYnJvd3Nlci9wcm92aWRlci9idWlsdC1pbi9yZW1vdGUnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uIGZyb20gJy4uL2Jyb3dzZXIvY29ubmVjdGlvbic7XG5pbXBvcnQgT1MgZnJvbSAnb3MtZmFtaWx5JztcbmltcG9ydCBkZXRlY3REaXNwbGF5IGZyb20gJy4uL3V0aWxzL2RldGVjdC1kaXNwbGF5JztcbmltcG9ydCB7IHZhbGlkYXRlUXVhcmFudGluZU9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9nZXQtb3B0aW9ucy9xdWFyYW50aW5lJztcbmltcG9ydCBsb2dFbnRyeSBmcm9tICcuLi91dGlscy9sb2ctZW50cnknO1xuaW1wb3J0IE1lc3NhZ2VCdXMgZnJvbSAnLi4vdXRpbHMvbWVzc2FnZS1idXMnO1xuaW1wb3J0IGdldEVudk9wdGlvbnMgZnJvbSAnLi4vZGFzaGJvYXJkL2dldC1lbnYtb3B0aW9ucyc7XG5pbXBvcnQgeyB2YWxpZGF0ZVNraXBKc0Vycm9yc09wdGlvblZhbHVlIH0gZnJvbSAnLi4vdXRpbHMvZ2V0LW9wdGlvbnMvc2tpcC1qcy1lcnJvcnMnO1xuXG5jb25zdCBERUJVR19MT0dHRVIgICAgICAgICAgICA9IGRlYnVnKCd0ZXN0Y2FmZTpydW5uZXInKTtcbmNvbnN0IERBU0hCT0FSRF9SRVBPUlRFUl9OQU1FID0gJ2Rhc2hib2FyZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJ1bm5lciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gICAgY29uc3RydWN0b3IgKHsgcHJveHksIGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSwgY29uZmlndXJhdGlvbiwgY29tcGlsZXJTZXJ2aWNlIH0pIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLl9tZXNzYWdlQnVzICAgICAgICAgPSBuZXcgTWVzc2FnZUJ1cygpO1xuICAgICAgICB0aGlzLnByb3h5ICAgICAgICAgICAgICAgPSBwcm94eTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIgICAgICAgID0gdGhpcy5fY3JlYXRlQm9vdHN0cmFwcGVyKGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSwgY29tcGlsZXJTZXJ2aWNlLCB0aGlzLl9tZXNzYWdlQnVzLCBjb25maWd1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5wZW5kaW5nVGFza1Byb21pc2VzID0gW107XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbiAgICAgICA9IGNvbmZpZ3VyYXRpb247XG4gICAgICAgIHRoaXMuaXNDbGkgICAgICAgICAgICAgICA9IGNvbmZpZ3VyYXRpb24uX29wdGlvbnMgJiYgY29uZmlndXJhdGlvbi5fb3B0aW9ucy5pc0NsaTtcbiAgICAgICAgdGhpcy53YXJuaW5nTG9nICAgICAgICAgID0gbmV3IFdhcm5pbmdMb2cobnVsbCwgV2FybmluZ0xvZy5jcmVhdGVBZGRXYXJuaW5nQ2FsbGJhY2sodGhpcy5fbWVzc2FnZUJ1cykpO1xuICAgICAgICB0aGlzLmNvbXBpbGVyU2VydmljZSAgICAgPSBjb21waWxlclNlcnZpY2U7XG4gICAgICAgIHRoaXMuX29wdGlvbnMgICAgICAgICAgICA9IHt9O1xuICAgICAgICB0aGlzLl9oYXNUYXNrRXJyb3JzICAgICAgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZCA9IG5ldyBGbGFnTGlzdChbXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuc3JjLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLmJyb3dzZXJzLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLnJlcG9ydGVyLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHMsXG4gICAgICAgIF0pO1xuICAgIH1cblxuICAgIF9jcmVhdGVCb290c3RyYXBwZXIgKGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSwgY29tcGlsZXJTZXJ2aWNlLCBtZXNzYWdlQnVzLCBjb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHJldHVybiBuZXcgQm9vdHN0cmFwcGVyKHsgYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LCBjb21waWxlclNlcnZpY2UsIG1lc3NhZ2VCdXMsIGNvbmZpZ3VyYXRpb24gfSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VCcm93c2VyU2V0IChicm93c2VyU2V0KSB7XG4gICAgICAgIHJldHVybiBicm93c2VyU2V0LmRpc3Bvc2UoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VSZXBvcnRlcnMgKHJlcG9ydGVycykge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5kaXNwb3NlKCkuY2F0Y2goZSA9PiBERUJVR19MT0dHRVIoZSkpKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VUZXN0ZWRBcHAgKHRlc3RlZEFwcCkge1xuICAgICAgICByZXR1cm4gdGVzdGVkQXBwID8gdGVzdGVkQXBwLmtpbGwoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSkgOiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZGlzcG9zZVRhc2tBbmRSZWxhdGVkQXNzZXRzICh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCwgcnVubmFibGVDb25maWd1cmF0aW9uSWQpIHtcbiAgICAgICAgdGFzay5hYm9ydCgpO1xuICAgICAgICB0YXNrLnVuUmVnaXN0ZXJDbGllbnRTY3JpcHRSb3V0aW5nKCk7XG4gICAgICAgIHRhc2suY2xlYXJMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5fbWVzc2FnZUJ1cy5hYm9ydCgpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX2ZpbmFsaXplQ29tcGlsZXJTZXJ2aWNlU3RhdGUodGFzaywgcnVubmFibGVDb25maWd1cmF0aW9uSWQpO1xuICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlQXNzZXRzKGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKTtcbiAgICB9XG5cbiAgICBfZGlzcG9zZUFzc2V0cyAoYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIHRoaXMuX2Rpc3Bvc2VCcm93c2VyU2V0KGJyb3dzZXJTZXQpLFxuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZVJlcG9ydGVycyhyZXBvcnRlcnMpLFxuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZVRlc3RlZEFwcCh0ZXN0ZWRBcHApLFxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICBfcHJlcGFyZUFycmF5UGFyYW1ldGVyIChhcnJheSkge1xuICAgICAgICBhcnJheSA9IGZsYXR0ZW4oYXJyYXkpO1xuXG4gICAgICAgIGlmICh0aGlzLmlzQ2xpKVxuICAgICAgICAgICAgcmV0dXJuIGFycmF5Lmxlbmd0aCA9PT0gMCA/IHZvaWQgMCA6IGFycmF5O1xuXG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2FuY2VsYWJsZVByb21pc2UgKHRhc2tQcm9taXNlKSB7XG4gICAgICAgIGNvbnN0IHByb21pc2UgICAgICAgICAgID0gdGFza1Byb21pc2UudGhlbigoeyBjb21wbGV0aW9uUHJvbWlzZSB9KSA9PiBjb21wbGV0aW9uUHJvbWlzZSk7XG4gICAgICAgIGNvbnN0IHJlbW92ZUZyb21QZW5kaW5nID0gKCkgPT4gcmVtb3ZlKHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcywgcHJvbWlzZSk7XG5cbiAgICAgICAgcHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4ocmVtb3ZlRnJvbVBlbmRpbmcpXG4gICAgICAgICAgICAuY2F0Y2gocmVtb3ZlRnJvbVBlbmRpbmcpO1xuXG4gICAgICAgIHByb21pc2UuY2FuY2VsID0gKCkgPT4gdGFza1Byb21pc2VcbiAgICAgICAgICAgIC50aGVuKCh7IGNhbmNlbFRhc2sgfSkgPT4gY2FuY2VsVGFzaygpKVxuICAgICAgICAgICAgLnRoZW4ocmVtb3ZlRnJvbVBlbmRpbmcpO1xuXG4gICAgICAgIHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcy5wdXNoKHByb21pc2UpO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIGFzeW5jIF9maW5hbGl6ZUNvbXBpbGVyU2VydmljZVN0YXRlICh0YXNrLCBydW5uYWJsZUNvbmZpZ3VyYXRpb25JZCkge1xuICAgICAgICBpZiAoIXRoaXMuY29tcGlsZXJTZXJ2aWNlKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuY29tcGlsZXJTZXJ2aWNlPy5yZW1vdmVVbml0c0Zyb21TdGF0ZSh7IHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkIH0pO1xuXG4gICAgICAgIC8vIE5PVEU6IEluIHNvbWUgY2FzZXMgKGJyb3dzZXIgcmVzdGFydCwgc3RvcCB0YXNrIG9uIGZpcnN0IGZhaWwsIGV0Yy4pLFxuICAgICAgICAvLyB0aGUgZml4dHVyZSBjb250ZXh0cyBtYXkgbm90IGJlIGRlbGV0ZWQuXG4gICAgICAgIC8vIFdlIHJlbW92ZSBhbGwgZml4dHVyZSBjb250ZXh0IGF0IHRoZSBlbmQgb2YgdGVzdCBleGVjdXRpb24gdG8gY2xlYW4gZm9yZ290dGVuIGNvbnRleHRzLlxuICAgICAgICBjb25zdCBmaXh0dXJlSWRzID0gdW5pcSh0YXNrLnRlc3RzLm1hcCh0ZXN0ID0+IHRlc3QuZml4dHVyZS5pZCkpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuY29tcGlsZXJTZXJ2aWNlLnJlbW92ZUZpeHR1cmVDdHhzRnJvbVN0YXRlKHsgZml4dHVyZUlkcyB9KTtcbiAgICB9XG5cbiAgICAvLyBSdW4gdGFza1xuICAgIF9nZXRGYWlsZWRUZXN0Q291bnQgKHRhc2ssIHJlcG9ydGVyKSB7XG4gICAgICAgIGxldCBmYWlsZWRUZXN0Q291bnQgPSByZXBvcnRlci50YXNrSW5mby50ZXN0Q291bnQgLSByZXBvcnRlci50YXNrSW5mby5wYXNzZWQ7XG5cbiAgICAgICAgaWYgKHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWwgJiYgISFmYWlsZWRUZXN0Q291bnQpXG4gICAgICAgICAgICBmYWlsZWRUZXN0Q291bnQgPSAxO1xuXG4gICAgICAgIHJldHVybiBmYWlsZWRUZXN0Q291bnQ7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFRhc2tSZXN1bHQgKHRhc2ssIGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwLCBydW5uYWJsZUNvbmZpZ3VyYXRpb25JZCkge1xuICAgICAgICBpZiAoIXRhc2sub3B0cy5saXZlKSB7XG4gICAgICAgICAgICB0YXNrLm9uKCdicm93c2VyLWpvYi1kb25lJywgYXN5bmMgam9iID0+IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChqb2IuYnJvd3NlckNvbm5lY3Rpb25zLm1hcChhc3luYyBiYyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJTZXQucmVsZWFzZUNvbm5lY3Rpb24oYmMpO1xuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fbWVzc2FnZUJ1cy5jbGVhckxpc3RlbmVycygnZXJyb3InKTtcblxuICAgICAgICBjb25zdCBicm93c2VyU2V0RXJyb3JQcm9taXNlID0gcHJvbWlzaWZ5RXZlbnQoYnJvd3NlclNldCwgJ2Vycm9yJyk7XG4gICAgICAgIGNvbnN0IHRhc2tFcnJvclByb21pc2UgICAgICAgPSBwcm9taXNpZnlFdmVudCh0YXNrLCAnZXJyb3InKTtcbiAgICAgICAgY29uc3QgbWVzc2FnZUJ1c0Vycm9yUHJvbWlzZSA9IHByb21pc2lmeUV2ZW50KHRoaXMuX21lc3NhZ2VCdXMsICdlcnJvcicpO1xuICAgICAgICBjb25zdCBzdHJlYW1Db250cm9sbGVyICAgICAgID0gbmV3IFJlcG9ydGVyU3RyZWFtQ29udHJvbGxlcih0aGlzLl9tZXNzYWdlQnVzLCByZXBvcnRlcnMpO1xuXG4gICAgICAgIGNvbnN0IHRhc2tEb25lUHJvbWlzZSA9IHRoaXMuX21lc3NhZ2VCdXMub25jZSgnZG9uZScpXG4gICAgICAgICAgICAudGhlbigoKSA9PiBicm93c2VyU2V0RXJyb3JQcm9taXNlLmNhbmNlbCgpKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChyZXBvcnRlcnMubWFwKHJlcG9ydGVyID0+IHJlcG9ydGVyLnRhc2tJbmZvLnBlbmRpbmdUYXNrRG9uZVByb21pc2UpKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW1xuICAgICAgICAgICAgdGFza0RvbmVQcm9taXNlLFxuICAgICAgICAgICAgYnJvd3NlclNldEVycm9yUHJvbWlzZSxcbiAgICAgICAgICAgIHRhc2tFcnJvclByb21pc2UsXG4gICAgICAgICAgICBtZXNzYWdlQnVzRXJyb3JQcm9taXNlLFxuICAgICAgICBdO1xuXG4gICAgICAgIGlmICh0ZXN0ZWRBcHApXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRlc3RlZEFwcC5lcnJvclByb21pc2UpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLnJhY2UocHJvbWlzZXMpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Rpc3Bvc2VUYXNrQW5kUmVsYXRlZEFzc2V0cyh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCwgcnVubmFibGVDb25maWd1cmF0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlQXNzZXRzKGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fZmluYWxpemVDb21waWxlclNlcnZpY2VTdGF0ZSh0YXNrLCBydW5uYWJsZUNvbmZpZ3VyYXRpb25JZCk7XG5cbiAgICAgICAgaWYgKHN0cmVhbUNvbnRyb2xsZXIubXVsdGlwbGVTdHJlYW1FcnJvcilcbiAgICAgICAgICAgIHRocm93IHN0cmVhbUNvbnRyb2xsZXIubXVsdGlwbGVTdHJlYW1FcnJvcjtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0RmFpbGVkVGVzdENvdW50KHRhc2ssIHJlcG9ydGVyc1swXSk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVRhc2sgKHRlc3RzLCBicm93c2VyQ29ubmVjdGlvbkdyb3VwcywgcHJveHksIG9wdHMsIHdhcm5pbmdMb2cpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUYXNrKHtcbiAgICAgICAgICAgIHRlc3RzLFxuICAgICAgICAgICAgYnJvd3NlckNvbm5lY3Rpb25Hcm91cHMsXG4gICAgICAgICAgICBwcm94eSxcbiAgICAgICAgICAgIG9wdHMsXG4gICAgICAgICAgICBydW5uZXJXYXJuaW5nTG9nOiB3YXJuaW5nTG9nLFxuICAgICAgICAgICAgY29tcGlsZXJTZXJ2aWNlOiAgdGhpcy5jb21waWxlclNlcnZpY2UsXG4gICAgICAgICAgICBtZXNzYWdlQnVzOiAgICAgICB0aGlzLl9tZXNzYWdlQnVzLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfcnVuVGFzayAoeyByZXBvcnRlcnMsIGJyb3dzZXJTZXQsIHRlc3RzLCB0ZXN0ZWRBcHAsIG9wdGlvbnMsIHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkIH0pIHtcbiAgICAgICAgY29uc3QgdGFzayAgICAgICAgICAgICAgPSB0aGlzLl9jcmVhdGVUYXNrKHRlc3RzLCBicm93c2VyU2V0LmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzLCB0aGlzLnByb3h5LCBvcHRpb25zLCB0aGlzLndhcm5pbmdMb2cpO1xuICAgICAgICBjb25zdCBjb21wbGV0aW9uUHJvbWlzZSA9IHRoaXMuX2dldFRhc2tSZXN1bHQodGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHAsIHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkKTtcbiAgICAgICAgbGV0IGNvbXBsZXRlZCAgICAgICAgICAgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl9tZXNzYWdlQnVzLm9uKCdzdGFydCcsIHN0YXJ0SGFuZGxpbmdUZXN0RXJyb3JzKTtcblxuICAgICAgICBpZiAoIXRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNraXBVbmNhdWdodEVycm9ycykpIHtcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VCdXMub24oJ3Rlc3QtcnVuLXN0YXJ0JywgYWRkUnVubmluZ1Rlc3QpO1xuICAgICAgICAgICAgdGhpcy5fbWVzc2FnZUJ1cy5vbigndGVzdC1ydW4tZG9uZScsICh7IGVycnMgfSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJzLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faGFzVGFza0Vycm9ycyA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICByZW1vdmVSdW5uaW5nVGVzdCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9tZXNzYWdlQnVzLm9uKCdkb25lJywgc3RvcEhhbmRsaW5nVGVzdEVycm9ycyk7XG5cbiAgICAgICAgdGFzay5vbignZXJyb3InLCBzdG9wSGFuZGxpbmdUZXN0RXJyb3JzKTtcblxuICAgICAgICBjb25zdCBvblRhc2tDb21wbGV0ZWQgPSAoKSA9PiB7XG4gICAgICAgICAgICB0YXNrLnVuUmVnaXN0ZXJDbGllbnRTY3JpcHRSb3V0aW5nKCk7XG5cbiAgICAgICAgICAgIGNvbXBsZXRlZCA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29tcGxldGlvblByb21pc2VcbiAgICAgICAgICAgIC50aGVuKG9uVGFza0NvbXBsZXRlZClcbiAgICAgICAgICAgIC5jYXRjaChvblRhc2tDb21wbGV0ZWQpO1xuXG4gICAgICAgIGNvbnN0IGNhbmNlbFRhc2sgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNvbXBsZXRlZClcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlVGFza0FuZFJlbGF0ZWRBc3NldHModGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHAsIHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4geyBjb21wbGV0aW9uUHJvbWlzZSwgY2FuY2VsVGFzayB9O1xuICAgIH1cblxuICAgIF9yZWdpc3RlckFzc2V0cyAoYXNzZXRzKSB7XG4gICAgICAgIGFzc2V0cy5mb3JFYWNoKGFzc2V0ID0+IHRoaXMucHJveHkuR0VUKGFzc2V0LnBhdGgsIGFzc2V0LmluZm8pKTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVEZWJ1Z0xvZ2dlciAoKSB7XG4gICAgICAgIGNvbnN0IGRlYnVnTG9nZ2VyID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuZGVidWdMb2dnZXIpO1xuXG4gICAgICAgIGNvbnN0IGRlYnVnTG9nZ2VyRGVmaW5lZENvcnJlY3RseSA9IGRlYnVnTG9nZ2VyID09PSBudWxsIHx8ICEhZGVidWdMb2dnZXIgJiZcbiAgICAgICAgICAgIFsnc2hvd0JyZWFrcG9pbnQnLCAnaGlkZUJyZWFrcG9pbnQnXS5ldmVyeShtZXRob2QgPT4gbWV0aG9kIGluIGRlYnVnTG9nZ2VyICYmIGlzRnVuY3Rpb24oZGVidWdMb2dnZXJbbWV0aG9kXSkpO1xuXG4gICAgICAgIGlmICghZGVidWdMb2dnZXJEZWZpbmVkQ29ycmVjdGx5KSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHtcbiAgICAgICAgICAgICAgICBbT1BUSU9OX05BTUVTLmRlYnVnTG9nZ2VyXTogZGVmYXVsdERlYnVnTG9nZ2VyLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfdmFsaWRhdGVTcGVlZE9wdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHNwZWVkID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc3BlZWQpO1xuXG4gICAgICAgIGlmIChzcGVlZCA9PT0gdm9pZCAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc3BlZWQgIT09ICdudW1iZXInIHx8IGlzTmFOKHNwZWVkKSB8fCBzcGVlZCA8IDAuMDEgfHwgc3BlZWQgPiAxKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkU3BlZWRWYWx1ZSk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlQ29uY3VycmVuY3lPcHRpb24gKCkge1xuICAgICAgICBjb25zdCBjb25jdXJyZW5jeSA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmNvbmN1cnJlbmN5KTtcblxuICAgICAgICBpZiAoY29uY3VycmVuY3kgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmN1cnJlbmN5ICE9PSAnbnVtYmVyJyB8fCBpc05hTihjb25jdXJyZW5jeSkgfHwgY29uY3VycmVuY3kgPCAxKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkQ29uY3VycmVuY3lGYWN0b3IpO1xuXG4gICAgICAgIGlmIChjb25jdXJyZW5jeSA+IDEgJiYgdGhpcy5ib290c3RyYXBwZXIuYnJvd3NlcnMuc29tZShicm93c2VyID0+IHtcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyIGluc3RhbmNlb2YgQnJvd3NlckNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICA/IGJyb3dzZXIuYnJvd3NlckluZm8uYnJvd3Nlck9wdGlvbi5jZHBQb3J0XG4gICAgICAgICAgICAgICAgOiBicm93c2VyLmJyb3dzZXJPcHRpb24uY2RwUG9ydDtcbiAgICAgICAgfSkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdFNldENvbmN1cnJlbmN5V2l0aENEUFBvcnQpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVNraXBKc0Vycm9yc09wdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHNraXBKc0Vycm9yc09wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5za2lwSnNFcnJvcnMpO1xuXG4gICAgICAgIGlmICghc2tpcEpzRXJyb3JzT3B0aW9ucylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YWxpZGF0ZVNraXBKc0Vycm9yc09wdGlvblZhbHVlKHNraXBKc0Vycm9yc09wdGlvbnMsIEdlbmVyYWxFcnJvcik7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlQ3VzdG9tQWN0aW9uc09wdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGN1c3RvbUFjdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jdXN0b21BY3Rpb25zKTtcblxuICAgICAgICBpZiAoIWN1c3RvbUFjdGlvbnMpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjdXN0b21BY3Rpb25zICE9PSAnb2JqZWN0JylcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZEN1c3RvbUFjdGlvbnNPcHRpb25UeXBlKTtcblxuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgaW4gY3VzdG9tQWN0aW9ucykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXN0b21BY3Rpb25zW25hbWVdICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZEN1c3RvbUFjdGlvblR5cGUsIG5hbWUsIHR5cGVvZiBjdXN0b21BY3Rpb25zW25hbWVdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIF92YWxpZGF0ZUJyb3dzZXJzICgpIHtcbiAgICAgICAgY29uc3QgYnJvd3NlcnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5icm93c2Vycyk7XG5cbiAgICAgICAgaWYgKCFicm93c2VycyB8fCBBcnJheS5pc0FycmF5KGJyb3dzZXJzKSAmJiAhYnJvd3NlcnMubGVuZ3RoKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5icm93c2VyTm90U2V0KTtcblxuICAgICAgICBpZiAoT1MubWFjKVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fY2hlY2tSZXF1aXJlZFBlcm1pc3Npb25zKGJyb3dzZXJzKTtcblxuICAgICAgICBpZiAoT1MubGludXggJiYgIWRldGVjdERpc3BsYXkoKSlcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2NoZWNrVGhhdFRlc3RzQ2FuUnVuV2l0aG91dERpc3BsYXkoYnJvd3NlcnMpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVJlcXVlc3RUaW1lb3V0T3B0aW9uIChvcHRpb25OYW1lKSB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RUaW1lb3V0ID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihvcHRpb25OYW1lKTtcblxuICAgICAgICBpZiAocmVxdWVzdFRpbWVvdXQgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhc3NlcnRUeXBlKGlzLm5vbk5lZ2F0aXZlTnVtYmVyLCBudWxsLCBgXCIke29wdGlvbk5hbWV9XCIgb3B0aW9uYCwgcmVxdWVzdFRpbWVvdXQpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVByb3h5QnlwYXNzT3B0aW9uICgpIHtcbiAgICAgICAgbGV0IHByb3h5QnlwYXNzID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMucHJveHlCeXBhc3MpO1xuXG4gICAgICAgIGlmIChwcm94eUJ5cGFzcyA9PT0gdm9pZCAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGFzc2VydFR5cGUoWyBpcy5zdHJpbmcsIGlzLmFycmF5IF0sIG51bGwsICdUaGUgXCJwcm94eUJ5cGFzc1wiIGFyZ3VtZW50JywgcHJveHlCeXBhc3MpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcHJveHlCeXBhc3MgPT09ICdzdHJpbmcnKVxuICAgICAgICAgICAgcHJveHlCeXBhc3MgPSBbcHJveHlCeXBhc3NdO1xuXG4gICAgICAgIHByb3h5QnlwYXNzID0gcHJveHlCeXBhc3MucmVkdWNlKChhcnIsIHJ1bGVzKSA9PiB7XG4gICAgICAgICAgICBhc3NlcnRUeXBlKGlzLnN0cmluZywgbnVsbCwgJ1RoZSBcInByb3h5QnlwYXNzXCIgYXJndW1lbnQnLCBydWxlcyk7XG5cbiAgICAgICAgICAgIHJldHVybiBhcnIuY29uY2F0KHJ1bGVzLnNwbGl0KCcsJykpO1xuICAgICAgICB9LCBbXSk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IHByb3h5QnlwYXNzIH0pO1xuICAgIH1cblxuICAgIF9nZXRTY3JlZW5zaG90T3B0aW9ucyAoKSB7XG4gICAgICAgIGxldCB7IHBhdGgsIHBhdGhQYXR0ZXJuLCB0YWtlT25GYWlscyB9ID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2NyZWVuc2hvdHMpIHx8IHt9O1xuXG4gICAgICAgIGlmICghcGF0aClcbiAgICAgICAgICAgIHBhdGggPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5zY3JlZW5zaG90UGF0aCk7XG5cbiAgICAgICAgaWYgKCFwYXRoUGF0dGVybilcbiAgICAgICAgICAgIHBhdGhQYXR0ZXJuID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2NyZWVuc2hvdFBhdGhQYXR0ZXJuKTtcblxuICAgICAgICBpZiAoIXRha2VPbkZhaWxzKVxuICAgICAgICAgICAgdGFrZU9uRmFpbHMgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4geyBwYXRoLCBwYXRoUGF0dGVybiwgdGFrZU9uRmFpbHMgfTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVTY3JlZW5zaG90T3B0aW9ucyAoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF0aCwgcGF0aFBhdHRlcm4gfSA9IHRoaXMuX2dldFNjcmVlbnNob3RPcHRpb25zKCk7XG5cbiAgICAgICAgY29uc3QgZGlzYWJsZVNjcmVlbnNob3RzID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuZGlzYWJsZVNjcmVlbnNob3RzKSB8fCAhcGF0aDtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5kaXNhYmxlU2NyZWVuc2hvdHNdOiBkaXNhYmxlU2NyZWVuc2hvdHMgfSk7XG5cbiAgICAgICAgaWYgKGRpc2FibGVTY3JlZW5zaG90cylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAocGF0aCkge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVTY3JlZW5zaG90UGF0aChwYXRoLCAnc2NyZWVuc2hvdHMgYmFzZSBkaXJlY3RvcnkgcGF0aCcpO1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5zY3JlZW5zaG90c106IHsgcGF0aDogcmVzb2x2ZVBhdGgocGF0aCkgfSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXRoUGF0dGVybikge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVTY3JlZW5zaG90UGF0aChwYXRoUGF0dGVybiwgJ3NjcmVlbnNob3RzIHBhdGggcGF0dGVybicpO1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5zY3JlZW5zaG90c106IHsgcGF0aFBhdHRlcm4gfSB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIF92YWxpZGF0ZVZpZGVvT3B0aW9ucyAoKSB7XG4gICAgICAgIGNvbnN0IHZpZGVvUGF0aCAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMudmlkZW9QYXRoKTtcbiAgICAgICAgY29uc3QgdmlkZW9FbmNvZGluZ09wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy52aWRlb0VuY29kaW5nT3B0aW9ucyk7XG5cbiAgICAgICAgbGV0IHZpZGVvT3B0aW9ucyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnZpZGVvT3B0aW9ucyk7XG5cbiAgICAgICAgaWYgKCF2aWRlb1BhdGgpIHtcbiAgICAgICAgICAgIGlmICh2aWRlb09wdGlvbnMgfHwgdmlkZW9FbmNvZGluZ09wdGlvbnMpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5jYW5ub3RTZXRWaWRlb09wdGlvbnNXaXRob3V0QmFzZVZpZGVvUGF0aFNwZWNpZmllZCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLnZpZGVvUGF0aF06IHJlc29sdmVQYXRoKHZpZGVvUGF0aCkgfSk7XG5cbiAgICAgICAgaWYgKCF2aWRlb09wdGlvbnMpIHtcbiAgICAgICAgICAgIHZpZGVvT3B0aW9ucyA9IHt9O1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy52aWRlb09wdGlvbnNdOiB2aWRlb09wdGlvbnMgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmlkZW9PcHRpb25zLmZmbXBlZ1BhdGgpXG4gICAgICAgICAgICB2aWRlb09wdGlvbnMuZmZtcGVnUGF0aCA9IHJlc29sdmVQYXRoKHZpZGVvT3B0aW9ucy5mZm1wZWdQYXRoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdmlkZW9PcHRpb25zLmZmbXBlZ1BhdGggPSBhd2FpdCBkZXRlY3RGRk1QRUcoKTtcblxuICAgICAgICBpZiAoIXZpZGVvT3B0aW9ucy5mZm1wZWdQYXRoKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5jYW5ub3RGaW5kRkZNUEVHKTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVDb21waWxlck9wdGlvbnMgKCkge1xuICAgICAgICBjb25zdCBjb21waWxlck9wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jb21waWxlck9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghY29tcGlsZXJPcHRpb25zKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHNwZWNpZmllZENvbXBpbGVycyAgPSBPYmplY3Qua2V5cyhjb21waWxlck9wdGlvbnMpO1xuICAgICAgICBjb25zdCBjdXN0b21pemVkQ29tcGlsZXJzID0gT2JqZWN0LmtleXMoQ3VzdG9taXphYmxlQ29tcGlsZXJzKTtcbiAgICAgICAgY29uc3Qgd3JvbmdDb21waWxlcnMgICAgICA9IHNwZWNpZmllZENvbXBpbGVycy5maWx0ZXIoY29tcGlsZXIgPT4gIWN1c3RvbWl6ZWRDb21waWxlcnMuaW5jbHVkZXMoY29tcGlsZXIpKTtcblxuICAgICAgICBpZiAoIXdyb25nQ29tcGlsZXJzLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBjb21waWxlckxpc3RTdHIgPSBnZXRDb25jYXRlbmF0ZWRWYWx1ZXNTdHJpbmcod3JvbmdDb21waWxlcnMsIHZvaWQgMCwgXCInXCIpO1xuICAgICAgICBjb25zdCBwbHVyYWxTdWZmaXggICAgPSBnZXRQbHVyYWxTdWZmaXgod3JvbmdDb21waWxlcnMpO1xuXG4gICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuY2Fubm90Q3VzdG9taXplU3BlY2lmaWVkQ29tcGlsZXJzLCBjb21waWxlckxpc3RTdHIsIHBsdXJhbFN1ZmZpeCk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlUmV0cnlUZXN0UGFnZXNPcHRpb24gKCkge1xuICAgICAgICBjb25zdCByZXRyeVRlc3RQYWdlc09wdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJldHJ5VGVzdFBhZ2VzKTtcblxuICAgICAgICBpZiAoIXJldHJ5VGVzdFBhZ2VzT3B0aW9uKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHNzbCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNzbCk7XG5cbiAgICAgICAgaWYgKHNzbClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBob3N0bmFtZSA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmhvc3RuYW1lKTtcblxuICAgICAgICBpZiAoaXNMb2NhbGhvc3QoaG9zdG5hbWUpKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuY2Fubm90RW5hYmxlUmV0cnlUZXN0UGFnZXNPcHRpb24pO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVF1YXJhbnRpbmVPcHRpb25zICgpIHtcbiAgICAgICAgY29uc3QgcXVhcmFudGluZU1vZGUgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5xdWFyYW50aW5lTW9kZSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBxdWFyYW50aW5lTW9kZSA9PT0gJ29iamVjdCcpXG4gICAgICAgICAgICB2YWxpZGF0ZVF1YXJhbnRpbmVPcHRpb25zKHF1YXJhbnRpbmVNb2RlKTtcbiAgICB9XG5cbiAgICBhc3luYyBfdmFsaWRhdGVSdW5PcHRpb25zICgpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVEZWJ1Z0xvZ2dlcigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZVNjcmVlbnNob3RPcHRpb25zKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3ZhbGlkYXRlVmlkZW9PcHRpb25zKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlU3BlZWRPcHRpb24oKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVQcm94eUJ5cGFzc09wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUNvbXBpbGVyT3B0aW9ucygpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZVJldHJ5VGVzdFBhZ2VzT3B0aW9uKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlUmVxdWVzdFRpbWVvdXRPcHRpb24oT1BUSU9OX05BTUVTLnBhZ2VSZXF1ZXN0VGltZW91dCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlUmVxdWVzdFRpbWVvdXRPcHRpb24oT1BUSU9OX05BTUVTLmFqYXhSZXF1ZXN0VGltZW91dCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlUXVhcmFudGluZU9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVDb25jdXJyZW5jeU9wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZVNraXBKc0Vycm9yc09wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUN1c3RvbUFjdGlvbnNPcHRpb24oKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fdmFsaWRhdGVCcm93c2VycygpO1xuICAgIH1cblxuICAgIF9jcmVhdGVSdW5uYWJsZUNvbmZpZ3VyYXRpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ib290c3RyYXBwZXJcbiAgICAgICAgICAgIC5jcmVhdGVSdW5uYWJsZUNvbmZpZ3VyYXRpb24oKVxuICAgICAgICAgICAgLnRoZW4ocnVubmFibGVDb25maWd1cmF0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2RvbmUtYm9vdHN0cmFwcGluZycpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJ1bm5hYmxlQ29uZmlndXJhdGlvbjtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVNjcmVlbnNob3RQYXRoIChzY3JlZW5zaG90UGF0aCwgcGF0aFR5cGUpIHtcbiAgICAgICAgY29uc3QgZm9yYmlkZGVuQ2hhcnNMaXN0ID0gY2hlY2tGaWxlUGF0aChzY3JlZW5zaG90UGF0aCk7XG5cbiAgICAgICAgaWYgKGZvcmJpZGRlbkNoYXJzTGlzdC5sZW5ndGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmZvcmJpZGRlbkNoYXJhdGVyc0luU2NyZWVuc2hvdFBhdGgsIHNjcmVlbnNob3RQYXRoLCBwYXRoVHlwZSwgcmVuZGVyRm9yYmlkZGVuQ2hhcnNMaXN0KGZvcmJpZGRlbkNoYXJzTGlzdCkpO1xuICAgIH1cblxuICAgIF9zZXRCb290c3RyYXBwZXJPcHRpb25zICgpIHtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnByZXBhcmUoKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm5vdGlmeUFib3V0T3ZlcnJpZGRlbk9wdGlvbnModGhpcy53YXJuaW5nTG9nKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm5vdGlmeUFib3V0RGVwcmVjYXRlZE9wdGlvbnModGhpcy53YXJuaW5nTG9nKTtcblxuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5zb3VyY2VzICAgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc3JjKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5zb3VyY2VzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5icm93c2VycyAgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYnJvd3NlcnMpIHx8IHRoaXMuYm9vdHN0cmFwcGVyLmJyb3dzZXJzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jb25jdXJyZW5jeSAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuY29uY3VycmVuY3kpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5hcHBDb21tYW5kICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYXBwQ29tbWFuZCkgfHwgdGhpcy5ib290c3RyYXBwZXIuYXBwQ29tbWFuZDtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuYXBwSW5pdERlbGF5ICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmFwcEluaXREZWxheSk7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLmZpbHRlciAgICAgICAgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5maWx0ZXIpIHx8IHRoaXMuYm9vdHN0cmFwcGVyLmZpbHRlcjtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIucmVwb3J0ZXJzICAgICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJlcG9ydGVyKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5yZXBvcnRlcnM7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLnRzQ29uZmlnUGF0aCAgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy50c0NvbmZpZ1BhdGgpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jbGllbnRTY3JpcHRzICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0cykgfHwgdGhpcy5ib290c3RyYXBwZXIuY2xpZW50U2NyaXB0cztcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuZGlzYWJsZU11bHRpcGxlV2luZG93cyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmRpc2FibGVNdWx0aXBsZVdpbmRvd3MpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5wcm94eWxlc3MgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuZXhwZXJpbWVudGFsUHJveHlsZXNzKTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuY29tcGlsZXJPcHRpb25zICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmNvbXBpbGVyT3B0aW9ucyk7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLmJyb3dzZXJJbml0VGltZW91dCAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5icm93c2VySW5pdFRpbWVvdXQpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5ob29rcyAgICAgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuaG9va3MpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jb25maWd1cmF0aW9uICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uO1xuICAgIH1cblxuICAgIGFzeW5jIF9hZGREYXNoYm9hcmRSZXBvcnRlcklmTmVlZGVkICgpIHtcbiAgICAgICAgY29uc3QgZGFzaGJvYXJkT3B0aW9ucyA9IGF3YWl0IHRoaXMuX2dldERhc2hib2FyZE9wdGlvbnMoKTtcbiAgICAgICAgbGV0IHJlcG9ydGVyT3B0aW9ucyAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJlcG9ydGVyKTtcblxuICAgICAgICAvLyBOT1RFOiB3ZSBzaG91bGQgc2VuZCByZXBvcnRzIHdoZW4gc2VuZFJlcG9ydCBpcyB1bmRlZmluZWRcbiAgICAgICAgLy8gVE9ETzogbWFrZSB0aGlzIG9wdGlvbiBiaW5hcnkgaW5zdGVhZCBvZiB0cmktc3RhdGVcbiAgICAgICAgaWYgKCFkYXNoYm9hcmRPcHRpb25zLnRva2VuIHx8IGRhc2hib2FyZE9wdGlvbnMuc2VuZFJlcG9ydCA9PT0gZmFsc2UpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKCFyZXBvcnRlck9wdGlvbnMpXG4gICAgICAgICAgICByZXBvcnRlck9wdGlvbnMgPSBbXTtcblxuICAgICAgICBjb25zdCBkYXNoYm9hcmRSZXBvcnRlciA9IHJlcG9ydGVyT3B0aW9ucy5maW5kKHJlcG9ydGVyID0+IHJlcG9ydGVyLm5hbWUgPT09IERBU0hCT0FSRF9SRVBPUlRFUl9OQU1FKTtcblxuICAgICAgICBpZiAoIWRhc2hib2FyZFJlcG9ydGVyKVxuICAgICAgICAgICAgcmVwb3J0ZXJPcHRpb25zLnB1c2goeyBuYW1lOiBEQVNIQk9BUkRfUkVQT1JURVJfTkFNRSwgb3B0aW9uczogZGFzaGJvYXJkT3B0aW9ucyB9KTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgZGFzaGJvYXJkUmVwb3J0ZXIub3B0aW9ucyA9IGRhc2hib2FyZE9wdGlvbnM7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMucmVwb3J0ZXJdOiByZXBvcnRlck9wdGlvbnMgfSk7XG4gICAgfVxuXG4gICAgX3R1cm5PblNjcmVlbnNob3RzSWZOZWVkZWQgKCkge1xuICAgICAgICBjb25zdCB7IHRha2VPbkZhaWxzIH0gPSB0aGlzLl9nZXRTY3JlZW5zaG90T3B0aW9ucygpO1xuICAgICAgICBjb25zdCByZXBvcnRlck9wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5yZXBvcnRlcik7XG5cbiAgICAgICAgaWYgKCF0YWtlT25GYWlscyAmJiByZXBvcnRlck9wdGlvbnMgJiYgY2FzdEFycmF5KHJlcG9ydGVyT3B0aW9ucykuc29tZShyZXBvcnRlciA9PiByZXBvcnRlci5uYW1lID09PSBEQVNIQk9BUkRfUkVQT1JURVJfTkFNRSkpXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5zY3JlZW5zaG90c106IHsgdGFrZU9uRmFpbHM6IHRydWUsIGF1dG9UYWtlT25GYWlsczogdHJ1ZSB9IH0pO1xuICAgIH1cblxuICAgIGFzeW5jIF9nZXREYXNoYm9hcmRPcHRpb25zICgpIHtcbiAgICAgICAgY29uc3Qgc3RvcmFnZU9wdGlvbnMgPSBhd2FpdCB0aGlzLl9sb2FkRGFzaGJvYXJkT3B0aW9uc0Zyb21TdG9yYWdlKCk7XG4gICAgICAgIGNvbnN0IGNvbmZpZ09wdGlvbnMgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuZGFzaGJvYXJkKTtcbiAgICAgICAgY29uc3QgZW52T3B0aW9ucyAgICAgPSBnZXRFbnZPcHRpb25zKCk7XG5cbiAgICAgICAgcmV0dXJuIG1lcmdlKHt9LCBzdG9yYWdlT3B0aW9ucywgY29uZmlnT3B0aW9ucywgZW52T3B0aW9ucyk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2xvYWREYXNoYm9hcmRPcHRpb25zRnJvbVN0b3JhZ2UgKCkge1xuICAgICAgICBjb25zdCBzdG9yYWdlID0gbmV3IERhc2hib2FyZENvbmZpZ1N0b3JhZ2UoKTtcblxuICAgICAgICBhd2FpdCBzdG9yYWdlLmxvYWQoKTtcblxuICAgICAgICByZXR1cm4gc3RvcmFnZS5vcHRpb25zO1xuICAgIH1cblxuICAgIGFzeW5jIF9wcmVwYXJlQ2xpZW50U2NyaXB0cyAodGVzdHMsIGNsaWVudFNjcmlwdHMpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHRlc3RzLm1hcChhc3luYyB0ZXN0ID0+IHtcbiAgICAgICAgICAgIGlmICh0ZXN0LmlzTGVnYWN5KVxuICAgICAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAgICAgbGV0IGxvYWRlZFRlc3RDbGllbnRTY3JpcHRzID0gYXdhaXQgbG9hZENsaWVudFNjcmlwdHModGVzdC5jbGllbnRTY3JpcHRzLCBkaXJuYW1lKHRlc3QudGVzdEZpbGUuZmlsZW5hbWUpKTtcblxuICAgICAgICAgICAgbG9hZGVkVGVzdENsaWVudFNjcmlwdHMgPSBjbGllbnRTY3JpcHRzLmNvbmNhdChsb2FkZWRUZXN0Q2xpZW50U2NyaXB0cyk7XG5cbiAgICAgICAgICAgIHRlc3QuY2xpZW50U2NyaXB0cyA9IHNldFVuaXF1ZVVybHMobG9hZGVkVGVzdENsaWVudFNjcmlwdHMpO1xuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2hhc0xvY2FsQnJvd3NlcnMgKGJyb3dzZXJJbmZvKSB7XG4gICAgICAgIGZvciAoY29uc3QgYnJvd3NlciBvZiBicm93c2VySW5mbykge1xuICAgICAgICAgICAgaWYgKGJyb3dzZXIgaW5zdGFuY2VvZiBCcm93c2VyQ29ubmVjdGlvbilcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcblxuICAgICAgICAgICAgaWYgKGF3YWl0IGJyb3dzZXIucHJvdmlkZXIuaXNMb2NhbEJyb3dzZXIodm9pZCAwLCBicm93c2VyLmJyb3dzZXJOYW1lKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBhc3luYyBfY2hlY2tSZXF1aXJlZFBlcm1pc3Npb25zIChicm93c2VySW5mbykge1xuICAgICAgICBjb25zdCBoYXNMb2NhbEJyb3dzZXJzID0gYXdhaXQgdGhpcy5faGFzTG9jYWxCcm93c2Vycyhicm93c2VySW5mbyk7XG5cbiAgICAgICAgY29uc3QgeyBlcnJvciB9ID0gYXdhaXQgYXV0aGVudGljYXRpb25IZWxwZXIoXG4gICAgICAgICAgICAoKSA9PiBmaW5kV2luZG93KCcnKSxcbiAgICAgICAgICAgIGVycm9ycy5VbmFibGVUb0FjY2Vzc1NjcmVlblJlY29yZGluZ0FQSUVycm9yLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGludGVyYWN0aXZlOiBoYXNMb2NhbEJyb3dzZXJzICYmICFpc0NJLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWVycm9yKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChoYXNMb2NhbEJyb3dzZXJzKVxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG5cbiAgICAgICAgUmVtb3RlQnJvd3NlclByb3ZpZGVyLmNhbkRldGVjdExvY2FsQnJvd3NlcnMgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBhc3luYyBfY2hlY2tUaGF0VGVzdHNDYW5SdW5XaXRob3V0RGlzcGxheSAoYnJvd3NlckluZm9Tb3VyY2UpIHtcbiAgICAgICAgZm9yIChsZXQgYnJvd3NlckluZm8gb2YgYnJvd3NlckluZm9Tb3VyY2UpIHtcbiAgICAgICAgICAgIGlmIChicm93c2VySW5mbyBpbnN0YW5jZW9mIEJyb3dzZXJDb25uZWN0aW9uKVxuICAgICAgICAgICAgICAgIGJyb3dzZXJJbmZvID0gYnJvd3NlckluZm8uYnJvd3NlckluZm87XG5cbiAgICAgICAgICAgIGNvbnN0IGlzTG9jYWxCcm93c2VyICAgID0gYXdhaXQgYnJvd3NlckluZm8ucHJvdmlkZXIuaXNMb2NhbEJyb3dzZXIodm9pZCAwLCBicm93c2VySW5mby5icm93c2VyTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpc0hlYWRsZXNzQnJvd3NlciA9IGF3YWl0IGJyb3dzZXJJbmZvLnByb3ZpZGVyLmlzSGVhZGxlc3NCcm93c2VyKHZvaWQgMCwgYnJvd3NlckluZm8uYnJvd3Nlck5hbWUpO1xuXG4gICAgICAgICAgICBpZiAoaXNMb2NhbEJyb3dzZXIgJiYgIWlzSGVhZGxlc3NCcm93c2VyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgUlVOVElNRV9FUlJPUlMuY2Fubm90UnVuTG9jYWxOb25IZWFkbGVzc0Jyb3dzZXJXaXRob3V0RGlzcGxheSxcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlckluZm8uYWxpYXMsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIF9zZXRDb25maWd1cmF0aW9uT3B0aW9ucyAoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuY29uZmlndXJhdGlvbi5hc3luY01lcmdlT3B0aW9ucyh0aGlzLl9vcHRpb25zKTtcbiAgICB9XG5cbiAgICAvLyBBUElcbiAgICBlbWJlZGRpbmdPcHRpb25zIChvcHRzKSB7XG4gICAgICAgIGNvbnN0IHsgYXNzZXRzLCBUZXN0UnVuQ3RvciB9ID0gb3B0cztcblxuICAgICAgICB0aGlzLl9yZWdpc3RlckFzc2V0cyhhc3NldHMpO1xuICAgICAgICB0aGlzLl9vcHRpb25zLlRlc3RSdW5DdG9yID0gVGVzdFJ1bkN0b3I7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgc3JjICguLi5zb3VyY2VzKSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5zcmMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLnNyYyk7XG5cbiAgICAgICAgdGhpcy5fb3B0aW9uc1tPUFRJT05fTkFNRVMuc3JjXSA9IHRoaXMuX3ByZXBhcmVBcnJheVBhcmFtZXRlcihzb3VyY2VzKTtcbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuc3JjICAgICA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgYnJvd3NlcnMgKC4uLmJyb3dzZXJzKSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5icm93c2VycylcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMubXVsdGlwbGVBUElNZXRob2RDYWxsRm9yYmlkZGVuLCBPUFRJT05fTkFNRVMuYnJvd3NlcnMpO1xuXG4gICAgICAgIHRoaXMuX29wdGlvbnMuYnJvd3NlcnMgICAgICAgICAgID0gdGhpcy5fcHJlcGFyZUFycmF5UGFyYW1ldGVyKGJyb3dzZXJzKTtcbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuYnJvd3NlcnMgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNvbmN1cnJlbmN5IChjb25jdXJyZW5jeSkge1xuICAgICAgICB0aGlzLl9vcHRpb25zLmNvbmN1cnJlbmN5ID0gY29uY3VycmVuY3k7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgcmVwb3J0ZXIgKG5hbWUsIG91dHB1dCkge1xuICAgICAgICBpZiAodGhpcy5hcGlNZXRob2RXYXNDYWxsZWQucmVwb3J0ZXIpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLnJlcG9ydGVyKTtcblxuICAgICAgICB0aGlzLl9vcHRpb25zW09QVElPTl9OQU1FUy5yZXBvcnRlcl0gPSB0aGlzLl9wcmVwYXJlQXJyYXlQYXJhbWV0ZXIocHJlcGFyZVJlcG9ydGVycyhuYW1lLCBvdXRwdXQpKTtcbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQucmVwb3J0ZXIgICAgID0gdHJ1ZTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmaWx0ZXIgKGZpbHRlcikge1xuICAgICAgICB0aGlzLl9vcHRpb25zLmZpbHRlciA9IGZpbHRlcjtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB1c2VQcm94eSAocHJveHksIHByb3h5QnlwYXNzKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnMucHJveHkgICAgICAgPSBwcm94eTtcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5wcm94eUJ5cGFzcyA9IHByb3h5QnlwYXNzO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHNjcmVlbnNob3RzICguLi5vcHRpb25zKSB7XG4gICAgICAgIGxldCBmdWxsUGFnZTtcbiAgICAgICAgbGV0IHRodW1ibmFpbHM7XG4gICAgICAgIGxldCBbcGF0aCwgdGFrZU9uRmFpbHMsIHBhdGhQYXR0ZXJuXSA9IG9wdGlvbnM7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMubGVuZ3RoID09PSAxICYmIG9wdGlvbnNbMF0gJiYgdHlwZW9mIG9wdGlvbnNbMF0gPT09ICdvYmplY3QnKVxuICAgICAgICAgICAgKHsgcGF0aCwgdGFrZU9uRmFpbHMsIHBhdGhQYXR0ZXJuLCBmdWxsUGFnZSwgdGh1bWJuYWlscyB9ID0gb3B0aW9uc1swXSk7XG5cbiAgICAgICAgdGhpcy5fb3B0aW9ucy5zY3JlZW5zaG90cyA9IHsgcGF0aCwgdGFrZU9uRmFpbHMsIHBhdGhQYXR0ZXJuLCBmdWxsUGFnZSwgdGh1bWJuYWlscyB9O1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZpZGVvIChwYXRoLCBvcHRpb25zLCBlbmNvZGluZ09wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5fb3B0aW9uc1tPUFRJT05fTkFNRVMudmlkZW9QYXRoXSAgICAgICAgICAgID0gcGF0aDtcbiAgICAgICAgdGhpcy5fb3B0aW9uc1tPUFRJT05fTkFNRVMudmlkZW9PcHRpb25zXSAgICAgICAgID0gb3B0aW9ucztcbiAgICAgICAgdGhpcy5fb3B0aW9uc1tPUFRJT05fTkFNRVMudmlkZW9FbmNvZGluZ09wdGlvbnNdID0gZW5jb2RpbmdPcHRpb25zO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHN0YXJ0QXBwIChjb21tYW5kLCBpbml0RGVsYXkpIHtcbiAgICAgICAgdGhpcy5fb3B0aW9uc1tPUFRJT05fTkFNRVMuYXBwQ29tbWFuZF0gICA9IGNvbW1hbmQ7XG4gICAgICAgIHRoaXMuX29wdGlvbnNbT1BUSU9OX05BTUVTLmFwcEluaXREZWxheV0gPSBpbml0RGVsYXk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdHNDb25maWdQYXRoIChwYXRoKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnNbT1BUSU9OX05BTUVTLnRzQ29uZmlnUGF0aF0gPSBwYXRoO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNsaWVudFNjcmlwdHMgKC4uLnNjcmlwdHMpIHtcbiAgICAgICAgaWYgKHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkLmNsaWVudFNjcmlwdHMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHMpO1xuXG4gICAgICAgIHRoaXMuX29wdGlvbnNbT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHNdID0gdGhpcy5fcHJlcGFyZUFycmF5UGFyYW1ldGVyKHNjcmlwdHMpO1xuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5jbGllbnRTY3JpcHRzICAgICA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgY29tcGlsZXJPcHRpb25zIChvcHRzKSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnNbT1BUSU9OX05BTUVTLmNvbXBpbGVyT3B0aW9uc10gPSBvcHRzO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHJ1biAob3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGxldCByZXBvcnRlcnM7XG5cbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQucmVzZXQoKTtcbiAgICAgICAgdGhpcy5fbWVzc2FnZUJ1cy5jbGVhckxpc3RlbmVycygpO1xuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VCdXNFcnJvclByb21pc2UgPSBwcm9taXNpZnlFdmVudCh0aGlzLl9tZXNzYWdlQnVzLCAnZXJyb3InKTtcblxuICAgICAgICB0aGlzLl9vcHRpb25zID0gT2JqZWN0LmFzc2lnbih0aGlzLl9vcHRpb25zLCBvcHRpb25zKTtcblxuICAgICAgICBjb25zdCBydW5UYXNrUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLl9zZXRDb25maWd1cmF0aW9uT3B0aW9ucygpKVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX2FkZERhc2hib2FyZFJlcG9ydGVySWZOZWVkZWQoKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl90dXJuT25TY3JlZW5zaG90c0lmTmVlZGVkKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gUmVwb3J0ZXIuZ2V0UmVwb3J0ZXJQbHVnaW5zKHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJlcG9ydGVyKSkpXG4gICAgICAgICAgICAudGhlbihyZXBvcnRlclBsdWdpbnMgPT4ge1xuICAgICAgICAgICAgICAgIHJlcG9ydGVycyA9IHJlcG9ydGVyUGx1Z2lucy5tYXAocmVwb3J0ZXIgPT4gbmV3IFJlcG9ydGVyKHJlcG9ydGVyLnBsdWdpbiwgdGhpcy5fbWVzc2FnZUJ1cywgcmVwb3J0ZXIub3V0U3RyZWFtLCByZXBvcnRlci5uYW1lKSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5pbml0KCkpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLl9zZXRCb290c3RyYXBwZXJPcHRpb25zKCkpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nRW50cnkoREVCVUdfTE9HR0VSLCB0aGlzLmNvbmZpZ3VyYXRpb24pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRlUnVuT3B0aW9ucygpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2NyZWF0ZVJ1bm5hYmxlQ29uZmlndXJhdGlvbigpKVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgKHsgYnJvd3NlclNldCwgdGVzdHMsIHRlc3RlZEFwcCwgY29tbW9uQ2xpZW50U2NyaXB0cywgaWQgfSkgPT4ge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX3ByZXBhcmVDbGllbnRTY3JpcHRzKHRlc3RzLCBjb21tb25DbGllbnRTY3JpcHRzKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGRhc2hib2FyZFJlcG9ydGVyID0gcmVwb3J0ZXJzLmZpbmQociA9PiByLnBsdWdpbi5uYW1lID09PSAnZGFzaGJvYXJkJyk/LnBsdWdpbjtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXNoYm9hcmRVcmwgICAgICA9IGRhc2hib2FyZFJlcG9ydGVyPy5nZXRSZXBvcnRVcmwgPyBkYXNoYm9hcmRSZXBvcnRlci5nZXRSZXBvcnRVcmwoKSA6ICcnO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgLi4udGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbnMoKSxcblxuICAgICAgICAgICAgICAgICAgICBkYXNoYm9hcmRVcmwsXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuYm9vdHN0cmFwcGVyLmNvbXBpbGVyU2VydmljZT8uc2V0T3B0aW9ucyh7IHZhbHVlOiByZXN1bHRPcHRpb25zIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3J1blRhc2soe1xuICAgICAgICAgICAgICAgICAgICByZXBvcnRlcnMsXG4gICAgICAgICAgICAgICAgICAgIGJyb3dzZXJTZXQsXG4gICAgICAgICAgICAgICAgICAgIHRlc3RzLFxuICAgICAgICAgICAgICAgICAgICB0ZXN0ZWRBcHAsXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6ICAgICAgICAgICAgICAgICByZXN1bHRPcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICBydW5uYWJsZUNvbmZpZ3VyYXRpb25JZDogaWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtcbiAgICAgICAgICAgIHJ1blRhc2tQcm9taXNlLFxuICAgICAgICAgICAgbWVzc2FnZUJ1c0Vycm9yUHJvbWlzZSxcbiAgICAgICAgXTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlQ2FuY2VsYWJsZVByb21pc2UoUHJvbWlzZS5yYWNlKHByb21pc2VzKSk7XG4gICAgfVxuXG4gICAgYXN5bmMgc3RvcCAoKSB7XG4gICAgICAgIC8vIE5PVEU6IFdoZW4gdGFza1Byb21pc2UgaXMgY2FuY2VsbGVkLCBpdCBpcyByZW1vdmVkIGZyb21cbiAgICAgICAgLy8gdGhlIHBlbmRpbmdUYXNrUHJvbWlzZXMgYXJyYXksIHdoaWNoIGxlYWRzIHRvIHNoaWZ0aW5nIGluZGV4ZXNcbiAgICAgICAgLy8gdG93YXJkcyB0aGUgYmVnaW5uaW5nLiBTbywgd2UgbXVzdCBjb3B5IHRoZSBhcnJheSBpbiBvcmRlciB0byBpdGVyYXRlIGl0LFxuICAgICAgICAvLyBvciB3ZSBjYW4gcGVyZm9ybSBpdGVyYXRpb24gZnJvbSB0aGUgZW5kIHRvIHRoZSBiZWdpbm5pbmcuXG4gICAgICAgIGNvbnN0IGNhbmNlbGxhdGlvblByb21pc2VzID0gdGhpcy5wZW5kaW5nVGFza1Byb21pc2VzLnJlZHVjZVJpZ2h0KChyZXN1bHQsIHRhc2tQcm9taXNlKSA9PiB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh0YXNrUHJvbWlzZS5jYW5jZWwoKSk7XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0sIFtdKTtcblxuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChjYW5jZWxsYXRpb25Qcm9taXNlcyk7XG4gICAgfVxufVxuIl19