UNPKG

meteor-desktop

Version:

Build a Meteor's desktop client with hot code push.

876 lines (695 loc) 110 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _runtime = _interopRequireDefault(require("regenerator-runtime/runtime")); var _asar = _interopRequireDefault(require("asar")); var _assignIn = _interopRequireDefault(require("lodash/assignIn")); var _lodash = _interopRequireDefault(require("lodash")); var _installLocal = require("install-local"); var _core = require("@babel/core"); var _crypto = _interopRequireDefault(require("crypto")); var _del = _interopRequireDefault(require("del")); var _presetEnv = _interopRequireDefault(require("@babel/preset-env")); var _fs = _interopRequireDefault(require("fs")); var _path = _interopRequireDefault(require("path")); var _shelljs = _interopRequireDefault(require("shelljs")); var _semver = _interopRequireDefault(require("semver")); var _terser = _interopRequireDefault(require("terser")); var _log = _interopRequireDefault(require("./log")); var _electronAppScaffold = _interopRequireDefault(require("./electronAppScaffold")); var _dependenciesManager = _interopRequireDefault(require("./dependenciesManager")); var _binaryModulesDetector = _interopRequireDefault(require("./binaryModulesDetector")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // eslint-disable-next-line no-unused-vars _shelljs.default.config.fatal = true; /** * Represents the .desktop dir scaffold. * @class */ class ElectronApp { /** * @param {MeteorDesktop} $ - context * @constructor */ constructor($) { this.log = new _log.default('electronApp'); this.scaffold = new _electronAppScaffold.default($); this.depsManager = new _dependenciesManager.default($, this.scaffold.getDefaultPackageJson().dependencies); this.$ = $; this.meteorApp = this.$.meteorApp; this.packageJson = null; this.version = null; this.compatibilityVersion = null; this.deprectatedPlugins = ['meteor-desktop-localstorage']; } /** * Makes an app.asar from the skeleton app. * @property {Array} excludeFromDel - list of paths to exclude from deleting * @returns {Promise} */ packSkeletonToAsar(excludeFromDel = []) { this.log.info('packing skeleton app and node_modules to asar archive'); return new Promise(resolve => { const extract = this.getModulesToExtract(); // We want to pack skeleton app and node_modules together, so we need to temporarily // move node_modules to app dir. this.log.debug('moving node_modules to app dir'); _fs.default.renameSync(this.$.env.paths.electronApp.nodeModules, _path.default.join(this.$.env.paths.electronApp.appRoot, 'node_modules')); let extracted = false; extracted = this.extractModules(extract); this.log.debug('packing'); _asar.default.createPackage(this.$.env.paths.electronApp.appRoot, this.$.env.paths.electronApp.appAsar, () => { // Lets move the node_modules back. this.log.debug('moving node_modules back from app dir'); _shelljs.default.mv(_path.default.join(this.$.env.paths.electronApp.appRoot, 'node_modules'), this.$.env.paths.electronApp.nodeModules); if (extracted) { // We need to create a full node modules back. In other words we want // the extracted modules back. extract.forEach(module => _shelljs.default.cp('-rf', _path.default.join(this.$.env.paths.electronApp.extractedNodeModules, module), _path.default.join(this.$.env.paths.electronApp.nodeModules, module))); // Get the .bin back. if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModulesBin)) { _shelljs.default.cp(_path.default.join(this.$.env.paths.electronApp.extractedNodeModulesBin, '*'), _path.default.join(this.$.env.paths.electronApp.nodeModules, '.bin')); } } this.log.debug('deleting source files'); const exclude = [this.$.env.paths.electronApp.nodeModules].concat([this.$.env.paths.electronApp.appAsar, this.$.env.paths.electronApp.packageJson], excludeFromDel); _del.default.sync([`${this.$.env.paths.electronApp.root}${_path.default.sep}*`].concat(exclude.map(pathToExclude => `!${pathToExclude}`)), { force: true }); resolve(); }); }); } /** * Moves specified node modules to a separate directory. * @param {Array} extract * @returns {boolean} */ extractModules(extract) { const ext = ['.js', '.bat', '.sh', '.cmd', '']; if (extract.length > 0) { if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModules)) { _shelljs.default.rm('-rf', this.$.env.paths.electronApp.extractedNodeModules); } _fs.default.mkdirSync(this.$.env.paths.electronApp.extractedNodeModules); _fs.default.mkdirSync(this.$.env.paths.electronApp.extractedNodeModulesBin); extract.forEach(module => { _fs.default.renameSync(_path.default.join(this.$.env.paths.electronApp.appRoot, 'node_modules', module), _path.default.join(this.$.env.paths.electronApp.extractedNodeModules, module)); // Move bins. this.extractBin(module, ext); }); return true; } return false; } /** * Extracts the bin files associated with a certain node modules. * * @param module * @param ext */ extractBin(module, ext) { let packageJson; try { packageJson = JSON.parse(_fs.default.readFileSync(_path.default.join(this.$.env.paths.electronApp.extractedNodeModules, module, 'package.json'), 'utf8')); } catch (e) { packageJson = {}; } const bins = 'bin' in packageJson && typeof packageJson.bin === 'object' ? Object.keys(packageJson.bin) : []; if (bins.length > 0) { bins.forEach(bin => { ext.forEach(extension => { const binFilePath = _path.default.join(this.$.env.paths.electronApp.appRoot, 'node_modules', '.bin', `${bin}${extension}`); if (this.$.utils.exists(binFilePath) || this.$.utils.symlinkExists(binFilePath)) { _fs.default.renameSync(binFilePath, _path.default.join(this.$.env.paths.electronApp.extractedNodeModulesBin, `${bin}${extension}`)); } }); }); } } /** * Merges the `extract` field with automatically detected modules. */ getModulesToExtract() { const binaryModulesDetector = new _binaryModulesDetector.default(this.$.env.paths.electronApp.nodeModules); const toBeExtracted = binaryModulesDetector.detect(); let { extract } = this.$.desktop.getSettings(); if (!Array.isArray(extract)) { extract = []; } const merge = {}; toBeExtracted.concat(extract).forEach(module => { merge[module] = true; }); extract = Object.keys(merge); if (extract.length > 0) { this.log.verbose(`resultant modules to extract list is: ${extract.join(', ')}`); } return extract; } /** * Calculates a md5 from all dependencies. */ calculateCompatibilityVersion() { this.log.verbose('calculating compatibility version'); const settings = this.$.desktop.getSettings(); if ('desktopHCPCompatibilityVersion' in settings) { this.compatibilityVersion = `${settings.desktopHCPCompatibilityVersion}`; this.log.warn(`compatibility version overridden to ${this.compatibilityVersion}`); return; } const md5 = _crypto.default.createHash('md5'); let dependencies = this.depsManager.getDependencies(); const dependenciesSorted = Object.keys(dependencies).sort(); dependencies = dependenciesSorted.map(dependency => `${dependency}:${dependencies[dependency]}`); const mainCompatibilityVersion = this.$.getVersion().split('.'); this.log.debug('meteor-desktop compatibility version is ', `${mainCompatibilityVersion[0]}`); dependencies.push(`meteor-desktop:${mainCompatibilityVersion[0]}`); const desktopCompatibilityVersion = settings.version.split('.')[0]; this.log.debug('.desktop compatibility version is ', desktopCompatibilityVersion); dependencies.push(`desktop-app:${desktopCompatibilityVersion}`); if (process.env.METEOR_DESKTOP_DEBUG_DESKTOP_COMPATIBILITY_VERSION || process.env.METEOR_DESKTOP_DEBUG) { this.log.debug(`compatibility version calculated from ${JSON.stringify(dependencies)}`); } md5.update(JSON.stringify(dependencies)); this.compatibilityVersion = md5.digest('hex'); } async init() { try { await this.$.electron.init(); await this.$.electronBuilder.init(); } catch (e) { this.log.warn('error occurred while initialising electron and electron-builder integration', e); process.exit(1); } } /** * Runs all necessary tasks to build the desktopified app. */ async build(run = false) { // TODO: refactor to a task runner this.log.info('scaffolding'); if (!this.$.desktop.check()) { if (!this.$.env.options.scaffold) { this.log.error('seems that you do not have a .desktop dir in your project or it is' + ' corrupted. Run \'npm run desktop -- init\' to get a new one.'); // Do not fail, so that npm will not print his error stuff to console. process.exit(0); } else { this.$.desktop.scaffold(); this.$.meteorApp.updateGitIgnore(); } } await this.init(); try { this.$.meteorApp.updateGitIgnore(); } catch (e) { this.log.warn(`error occurred while adding ${this.$.env.paths.electronApp.rootName}` + 'to .gitignore: ', e); } try { await this.$.meteorApp.removeDeprecatedPackages(); } catch (e) { this.log.error('error while removing deprecated packages: ', e); process.exit(1); } try { await this.$.meteorApp.ensureDesktopHCPPackages(); } catch (e) { this.log.error('error while checking for required packages: ', e); process.exit(1); } try { await this.scaffold.make(); } catch (e) { this.log.error('error while scaffolding: ', e); process.exit(1); } try { const fileName = '.npmrc'; const dirName = '.meteor/desktop-build'; if (_fs.default.existsSync(dirName) && _fs.default.existsSync(fileName)) { _fs.default.copyFileSync(fileName, `${dirName}/${fileName}`); } } catch (e) { this.log.warn('error while copying .npmrc', e); } try { await this.exposeElectronModules(); } catch (e) { this.log.error('error while exposing electron modules: ', e); process.exit(1); } try { this.updatePackageJsonFields(); } catch (e) { this.log.error('error while updating package.json: ', e); } try { this.updateDependenciesList(); } catch (e) { this.log.error('error while merging dependencies list: ', e); } try { this.calculateCompatibilityVersion(); } catch (e) { this.log.error('error while calculating compatibility version: ', e); process.exit(1); } try { await this.handleTemporaryNodeModules(); } catch (e) { this.log.error('error occurred while handling temporary node_modules: ', e); process.exit(1); } let nodeModulesRemoved; try { nodeModulesRemoved = await this.handleStateOfNodeModules(); } catch (e) { this.log.error('error occurred while clearing node_modules: ', e); process.exit(1); } try { await this.rebuildDeps(true); } catch (e) { this.log.error('error occurred while installing node_modules: ', e); process.exit(1); } if (!nodeModulesRemoved) { try { await this.rebuildDeps(); } catch (e) { this.log.error('error occurred while rebuilding native node modules: ', e); process.exit(1); } } try { await this.linkNpmPackages(); } catch (e) { this.log.error(`linking packages failed: ${e}`); process.exit(1); } try { await this.installLocalNodeModules(); } catch (e) { this.log.error('error occurred while installing local node modules: ', e); process.exit(1); } try { await this.ensureMeteorDependencies(); } catch (e) { this.log.error('error occurred while ensuring meteor dependencies are installed: ', e); process.exit(1); } if (this.$.env.isProductionBuild()) { try { await this.packSkeletonToAsar(); } catch (e) { this.log.error('error while packing skeleton to asar: ', e); process.exit(1); } } // TODO: find a way to avoid copying .desktop to a temp location try { this.copyDesktopToDesktopTemp(); } catch (e) { this.log.error('error while copying .desktop to a temporary location: ', e); process.exit(1); } try { await this.updateSettingsJsonFields(); } catch (e) { this.log.error('error while updating settings.json: ', e); process.exit(1); } try { await this.excludeFilesFromArchive(); } catch (e) { this.log.error('error while excluding files from packing to asar: ', e); process.exit(1); } try { await this.transpileAndMinify(); } catch (e) { this.log.error('error while transpiling or minifying: ', e); } try { await this.packDesktopToAsar(); } catch (e) { this.log.error('error occurred while packing .desktop to asar: ', e); process.exit(1); } try { await this.getMeteorClientBuild(); } catch (e) { this.log.error('error occurred during getting meteor mobile build: ', e); } if (run) { this.log.info('running'); this.$.electron.run(); } else { this.log.info('built'); } } /** * Copies the `exposedModules` setting from `settings.json` into `preload.js` modifying its code * so that the script will have it hardcoded. */ exposeElectronModules() { const { exposedModules } = this.$.desktop.getSettings(); if (exposedModules && Array.isArray(exposedModules) && exposedModules.length > 0) { let preload = _fs.default.readFileSync(this.$.env.paths.electronApp.preload, 'utf8'); const modules = this.$.desktop.getSettings().exposedModules.reduce( // eslint-disable-next-line no-return-assign,no-param-reassign (prev, module) => (prev += `'${module}', `, prev), ''); preload = preload.replace('const exposedModules = [', `const exposedModules = [${modules}`); _fs.default.writeFileSync(this.$.env.paths.electronApp.preload, preload); } } /** * Ensures all required dependencies are added to the Meteor project. * @returns {Promise.<void>} */ async ensureMeteorDependencies() { let packages = []; const packagesWithVersion = []; let plugins = 'plugins ['; Object.keys(this.$.desktop.getDependencies().plugins).forEach(plugin => { // Read package.json of the plugin. const packageJson = JSON.parse(_fs.default.readFileSync(_path.default.join(this.$.env.paths.electronApp.nodeModules, plugin, 'package.json'), 'utf8')); if ('meteorDependencies' in packageJson && typeof packageJson.meteorDependencies === 'object') { plugins += `${plugin}, `; packages.unshift(...Object.keys(packageJson.meteorDependencies)); packagesWithVersion.unshift(...packages.map(packageName => { if (packageJson.meteorDependencies[packageName] === '@version') { return `${packageName}@${packageJson.version}`; } return `${packageName}@${packageJson.meteorDependencies[packageName]}`; })); } }); const packagesCount = packages.length; packages = packages.filter(value => !this.deprectatedPlugins.includes(value)); if (packagesCount !== packages.length) { this.log.warn('you have some deprecated meteor desktop plugins in your settings, please remove ' + `them (deprecated plugins: ${this.deprectatedPlugins.join(', ')})`); } if (packages.length > 0) { plugins = `${plugins.substr(0, plugins.length - 2)}]`; try { await this.$.meteorApp.meteorManager.ensurePackages(packages, packagesWithVersion, plugins); } catch (e) { throw new Error(e); } } } /** * Builds meteor app. */ async getMeteorClientBuild() { await this.$.meteorApp.build(); } /** * Removes node_modules if needed. * @returns {Promise<void>} */ async handleStateOfNodeModules() { if (this.$.env.isProductionBuild() || this.$.env.options.ia32) { if (!this.$.env.isProductionBuild()) { this.log.info('clearing node_modules because we need to have it clear for ia32 rebuild'); } else { this.log.info('clearing node_modules because this is a production build'); } try { await this.$.utils.rmWithRetries('-rf', this.$.env.paths.electronApp.nodeModules); } catch (e) { throw new Error(e); } return true; } return false; } /** * If there is a temporary node_modules folder and no node_modules folder, we will * restore it, as it might be a leftover from an interrupted flow. * @returns {Promise<void>} */ async handleTemporaryNodeModules() { if (this.$.utils.exists(this.$.env.paths.electronApp.tmpNodeModules)) { if (!this.$.utils.exists(this.$.env.paths.electronApp.nodeModules)) { this.log.debug('moving temp node_modules back'); _shelljs.default.mv(this.$.env.paths.electronApp.tmpNodeModules, this.$.env.paths.electronApp.nodeModules); } else { // If there is a node_modules folder, we should clear the temporary one. this.log.debug('clearing temp node_modules because new one is already created'); try { await this.$.utils.rmWithRetries('-rf', this.$.env.paths.electronApp.tmpNodeModules); } catch (e) { throw new Error(e); } } } } /** * Runs npm link for every package specified in settings.json->linkPackages. */ async linkNpmPackages() { if (this.$.env.isProductionBuild()) { return; } const settings = this.$.desktop.getSettings(); const promises = []; if ('linkPackages' in this.$.desktop.getSettings()) { if (Array.isArray(settings.linkPackages)) { settings.linkPackages.forEach(packageName => promises.push(this.$.meteorApp.runNpm(['link', packageName], undefined, this.$.env.paths.electronApp.root))); } } await Promise.all(promises); } /** * Runs npm in the electron app to get the dependencies installed. * @returns {Promise} */ async ensureDeps() { this.log.info('installing dependencies'); if (this.$.utils.exists(this.$.env.paths.electronApp.nodeModules)) { this.log.debug('running npm prune to wipe unneeded dependencies'); try { await this.runNpm(['prune']); } catch (e) { throw new Error(e); } } try { await this.runNpm(['install'], this.$.env.stdio); } catch (e) { throw new Error(e); } } /** * Warns if plugins version are outdated in compare to the newest scaffold. * @param {Object} pluginsVersions - current plugins versions from settings.json */ checkPluginsVersion(pluginsVersions) { const settingsJson = JSON.parse(_fs.default.readFileSync(_path.default.join(this.$.env.paths.scaffold, 'settings.json'))); const scaffoldPluginsVersion = this.$.desktop.getDependencies(settingsJson, false).plugins; Object.keys(pluginsVersions).forEach(pluginName => { if (pluginName in scaffoldPluginsVersion && scaffoldPluginsVersion[pluginName] !== pluginsVersions[pluginName] && _semver.default.lt(pluginsVersions[pluginName], scaffoldPluginsVersion[pluginName])) { this.log.warn(`you are using outdated version ${pluginsVersions[pluginName]} of ` + `${pluginName}, the suggested version to use is ` + `${scaffoldPluginsVersion[pluginName]}`); } }); } /** * Merges core dependency list with the dependencies from .desktop. */ updateDependenciesList() { this.log.info('updating list of package.json\'s dependencies'); const desktopDependencies = this.$.desktop.getDependencies(); this.checkPluginsVersion(desktopDependencies.plugins); this.log.debug('merging settings.json[dependencies]'); this.depsManager.mergeDependencies('settings.json[dependencies]', desktopDependencies.fromSettings); this.log.debug('merging settings.json[plugins]'); this.depsManager.mergeDependencies('settings.json[plugins]', desktopDependencies.plugins); this.log.debug('merging dependencies from modules'); Object.keys(desktopDependencies.modules).forEach(module => this.depsManager.mergeDependencies(`module[${module}]`, desktopDependencies.modules[module])); this.packageJson.dependencies = this.depsManager.getRemoteDependencies(); this.packageJson.localDependencies = this.depsManager.getLocalDependencies(); this.log.debug('writing updated package.json'); _fs.default.writeFileSync(this.$.env.paths.electronApp.packageJson, JSON.stringify(this.packageJson, null, 2)); } /** * Install node modules from local paths using local-install. * * @param {string} arch * @returns {Promise} */ installLocalNodeModules(arch = this.$.env.options.ia32 || process.arch === 'ia32' ? 'ia32' : 'x64') { const localDependencies = _lodash.default.values(this.packageJson.localDependencies); if (localDependencies.length === 0) { return Promise.resolve(); } this.log.info('installing local node modules'); const lastRebuild = this.$.electronBuilder.prepareLastRebuildObject(arch); const env = this.$.electronBuilder.getGypEnv(lastRebuild.frameworkInfo, lastRebuild.platform, lastRebuild.arch); const installer = new _installLocal.LocalInstaller({ [this.$.env.paths.electronApp.root]: localDependencies }, { npmEnv: env }); (0, _installLocal.progress)(installer); return installer.install(); } /** * Rebuild binary dependencies against Electron's node headers. * @returns {Promise} */ rebuildDeps(install = false) { if (install) { this.log.info('issuing node_modules install from electron-builder'); } else { this.log.info('issuing native modules rebuild from electron-builder'); } const arch = this.$.env.options.ia32 || process.arch === 'ia32' ? 'ia32' : 'x64'; if (this.$.env.options.ia32) { this.log.verbose('forcing rebuild for 32bit'); } else { this.log.verbose(`rebuilding for ${arch}`); } return this.$.electronBuilder.installOrRebuild(arch, undefined, install); } /** * Update package.json fields accordingly to what is set in settings.json. * * packageJson.name = settings.projectName * packageJson.version = settings.version * packageJson.* = settings.packageJsonFields */ updatePackageJsonFields() { this.log.verbose('updating package.json fields'); const settings = this.$.desktop.getSettings(); /** @type {desktopSettings} */ const packageJson = this.scaffold.getDefaultPackageJson(); packageJson.version = settings.version; if ('packageJsonFields' in settings) { (0, _assignIn.default)(packageJson, settings.packageJsonFields); } (0, _assignIn.default)(packageJson, { name: settings.projectName }); this.log.debug('writing updated package.json'); _fs.default.writeFileSync(this.$.env.paths.electronApp.packageJson, JSON.stringify(packageJson, null, 4)); this.packageJson = packageJson; } /** * Updates settings.json with env (prod/dev) information and versions. */ async updateSettingsJsonFields() { this.log.debug('updating settings.json fields'); const settings = this.$.desktop.getSettings(); // Save versions. settings.compatibilityVersion = this.compatibilityVersion; // Pass information about build type to the settings.json. settings.env = this.$.env.isProductionBuild() ? 'prod' : 'dev'; const version = await this.$.desktop.getHashVersion(); settings.desktopVersion = `${version}_${settings.env}`; settings.meteorDesktopVersion = this.$.getVersion(); if (this.$.env.options.prodDebug) { settings.prodDebug = true; } _fs.default.writeFileSync(this.$.env.paths.desktopTmp.settings, JSON.stringify(settings, null, 4)); } /** * Copies files from prepared .desktop to desktop.asar in electron app. */ packDesktopToAsar() { this.log.info('packing .desktop to asar'); return new Promise((resolve, reject) => { _asar.default.createPackage(this.$.env.paths.desktopTmp.root, this.$.env.paths.electronApp.desktopAsar, () => { this.log.verbose('clearing temporary .desktop'); this.$.utils.rmWithRetries('-rf', this.$.env.paths.desktopTmp.root).then(() => { resolve(); }).catch(e => { reject(e); }); resolve(); }); }); } /** * Makes a temporary copy of .desktop. */ copyDesktopToDesktopTemp() { this.log.verbose('copying .desktop to temporary location'); _shelljs.default.cp('-rf', this.$.env.paths.desktop.root, this.$.env.paths.desktopTmp.root); // Remove test files. _del.default.sync([_path.default.join(this.$.env.paths.desktopTmp.root, '**', '*.test.js')], { force: true }); } /** * Runs babel and uglify over .desktop if requested. */ async transpileAndMinify() { this.log.info('transpiling and uglifying'); const settings = this.$.desktop.getSettings(); const options = 'uglifyOptions' in settings ? settings.uglifyOptions : {}; const uglifyingEnabled = 'uglify' in settings && !!settings.uglify; const preset = (0, _presetEnv.default)({ assertVersion: () => {} }, { targets: { node: '12' } }); const { data: files } = await this.$.utils.readDir(this.$.env.paths.desktopTmp.root); files.forEach(file => { if (file.endsWith('.js')) { let { code } = (0, _core.transformFileSync)(file, { presets: [preset] }); let error; if (settings.env === 'prod' && uglifyingEnabled) { ({ code, error } = _terser.default.minify(code, options)); } if (error) { throw new Error(error); } _fs.default.writeFileSync(file, code); } }); } /** * Moves all the files that should not be packed into asar into a safe location which is the * 'extracted' dir in the electron app. */ async excludeFilesFromArchive() { this.log.info('excluding files from packing'); // Ensure empty `extracted` dir try { await this.$.utils.rmWithRetries('-rf', this.$.env.paths.electronApp.extracted); } catch (e) { throw new Error(e); } _shelljs.default.mkdir(this.$.env.paths.electronApp.extracted); const configs = this.$.desktop.gatherModuleConfigs(); // Move files that should not be asar'ed. configs.forEach(config => { const moduleConfig = config; if ('extract' in moduleConfig) { if (!Array.isArray(moduleConfig.extract)) { moduleConfig.extract = [moduleConfig.extract]; } moduleConfig.extract.forEach(file => { this.log.debug(`excluding ${file} from ${config.name}`); const filePath = _path.default.join(this.$.env.paths.desktopTmp.modules, moduleConfig.dirName, file); const destinationPath = _path.default.join(this.$.env.paths.electronApp.extracted, moduleConfig.dirName); if (!this.$.utils.exists(destinationPath)) { _shelljs.default.mkdir(destinationPath); } _shelljs.default.mv(filePath, destinationPath); }); } }); } } exports.default = ElectronApp; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9lbGVjdHJvbkFwcC5qcyJdLCJuYW1lcyI6WyJzaGVsbCIsImNvbmZpZyIsImZhdGFsIiwiRWxlY3Ryb25BcHAiLCJjb25zdHJ1Y3RvciIsIiQiLCJsb2ciLCJMb2ciLCJzY2FmZm9sZCIsIkVsZWN0cm9uQXBwU2NhZmZvbGQiLCJkZXBzTWFuYWdlciIsIkRlcGVuZGVuY2llc01hbmFnZXIiLCJnZXREZWZhdWx0UGFja2FnZUpzb24iLCJkZXBlbmRlbmNpZXMiLCJtZXRlb3JBcHAiLCJwYWNrYWdlSnNvbiIsInZlcnNpb24iLCJjb21wYXRpYmlsaXR5VmVyc2lvbiIsImRlcHJlY3RhdGVkUGx1Z2lucyIsInBhY2tTa2VsZXRvblRvQXNhciIsImV4Y2x1ZGVGcm9tRGVsIiwiaW5mbyIsIlByb21pc2UiLCJyZXNvbHZlIiwiZXh0cmFjdCIsImdldE1vZHVsZXNUb0V4dHJhY3QiLCJkZWJ1ZyIsImZzIiwicmVuYW1lU3luYyIsImVudiIsInBhdGhzIiwiZWxlY3Ryb25BcHAiLCJub2RlTW9kdWxlcyIsInBhdGgiLCJqb2luIiwiYXBwUm9vdCIsImV4dHJhY3RlZCIsImV4dHJhY3RNb2R1bGVzIiwiYXNhciIsImNyZWF0ZVBhY2thZ2UiLCJhcHBBc2FyIiwibXYiLCJmb3JFYWNoIiwibW9kdWxlIiwiY3AiLCJleHRyYWN0ZWROb2RlTW9kdWxlcyIsInV0aWxzIiwiZXhpc3RzIiwiZXh0cmFjdGVkTm9kZU1vZHVsZXNCaW4iLCJleGNsdWRlIiwiY29uY2F0IiwiZGVsIiwic3luYyIsInJvb3QiLCJzZXAiLCJtYXAiLCJwYXRoVG9FeGNsdWRlIiwiZm9yY2UiLCJleHQiLCJsZW5ndGgiLCJybSIsIm1rZGlyU3luYyIsImV4dHJhY3RCaW4iLCJKU09OIiwicGFyc2UiLCJyZWFkRmlsZVN5bmMiLCJlIiwiYmlucyIsImJpbiIsIk9iamVjdCIsImtleXMiLCJleHRlbnNpb24iLCJiaW5GaWxlUGF0aCIsInN5bWxpbmtFeGlzdHMiLCJiaW5hcnlNb2R1bGVzRGV0ZWN0b3IiLCJCaW5hcnlNb2R1bGVEZXRlY3RvciIsInRvQmVFeHRyYWN0ZWQiLCJkZXRlY3QiLCJkZXNrdG9wIiwiZ2V0U2V0dGluZ3MiLCJBcnJheSIsImlzQXJyYXkiLCJtZXJnZSIsInZlcmJvc2UiLCJjYWxjdWxhdGVDb21wYXRpYmlsaXR5VmVyc2lvbiIsInNldHRpbmdzIiwiZGVza3RvcEhDUENvbXBhdGliaWxpdHlWZXJzaW9uIiwid2FybiIsIm1kNSIsImNyeXB0byIsImNyZWF0ZUhhc2giLCJnZXREZXBlbmRlbmNpZXMiLCJkZXBlbmRlbmNpZXNTb3J0ZWQiLCJzb3J0IiwiZGVwZW5kZW5jeSIsIm1haW5Db21wYXRpYmlsaXR5VmVyc2lvbiIsImdldFZlcnNpb24iLCJzcGxpdCIsInB1c2giLCJkZXNrdG9wQ29tcGF0aWJpbGl0eVZlcnNpb24iLCJwcm9jZXNzIiwiTUVURU9SX0RFU0tUT1BfREVCVUdfREVTS1RPUF9DT01QQVRJQklMSVRZX1ZFUlNJT04iLCJNRVRFT1JfREVTS1RPUF9ERUJVRyIsInN0cmluZ2lmeSIsInVwZGF0ZSIsImRpZ2VzdCIsImluaXQiLCJlbGVjdHJvbiIsImVsZWN0cm9uQnVpbGRlciIsImV4aXQiLCJidWlsZCIsInJ1biIsImNoZWNrIiwib3B0aW9ucyIsImVycm9yIiwidXBkYXRlR2l0SWdub3JlIiwicm9vdE5hbWUiLCJyZW1vdmVEZXByZWNhdGVkUGFja2FnZXMiLCJlbnN1cmVEZXNrdG9wSENQUGFja2FnZXMiLCJtYWtlIiwiZmlsZU5hbWUiLCJkaXJOYW1lIiwiZXhpc3RzU3luYyIsImNvcHlGaWxlU3luYyIsImV4cG9zZUVsZWN0cm9uTW9kdWxlcyIsInVwZGF0ZVBhY2thZ2VKc29uRmllbGRzIiwidXBkYXRlRGVwZW5kZW5jaWVzTGlzdCIsImhhbmRsZVRlbXBvcmFyeU5vZGVNb2R1bGVzIiwibm9kZU1vZHVsZXNSZW1vdmVkIiwiaGFuZGxlU3RhdGVPZk5vZGVNb2R1bGVzIiwicmVidWlsZERlcHMiLCJsaW5rTnBtUGFja2FnZXMiLCJpbnN0YWxsTG9jYWxOb2RlTW9kdWxlcyIsImVuc3VyZU1ldGVvckRlcGVuZGVuY2llcyIsImlzUHJvZHVjdGlvbkJ1aWxkIiwiY29weURlc2t0b3BUb0Rlc2t0b3BUZW1wIiwidXBkYXRlU2V0dGluZ3NKc29uRmllbGRzIiwiZXhjbHVkZUZpbGVzRnJvbUFyY2hpdmUiLCJ0cmFuc3BpbGVBbmRNaW5pZnkiLCJwYWNrRGVza3RvcFRvQXNhciIsImdldE1ldGVvckNsaWVudEJ1aWxkIiwiZXhwb3NlZE1vZHVsZXMiLCJwcmVsb2FkIiwibW9kdWxlcyIsInJlZHVjZSIsInByZXYiLCJyZXBsYWNlIiwid3JpdGVGaWxlU3luYyIsInBhY2thZ2VzIiwicGFja2FnZXNXaXRoVmVyc2lvbiIsInBsdWdpbnMiLCJwbHVnaW4iLCJtZXRlb3JEZXBlbmRlbmNpZXMiLCJ1bnNoaWZ0IiwicGFja2FnZU5hbWUiLCJwYWNrYWdlc0NvdW50IiwiZmlsdGVyIiwidmFsdWUiLCJpbmNsdWRlcyIsInN1YnN0ciIsIm1ldGVvck1hbmFnZXIiLCJlbnN1cmVQYWNrYWdlcyIsIkVycm9yIiwiaWEzMiIsInJtV2l0aFJldHJpZXMiLCJ0bXBOb2RlTW9kdWxlcyIsInByb21pc2VzIiwibGlua1BhY2thZ2VzIiwicnVuTnBtIiwidW5kZWZpbmVkIiwiYWxsIiwiZW5zdXJlRGVwcyIsInN0ZGlvIiwiY2hlY2tQbHVnaW5zVmVyc2lvbiIsInBsdWdpbnNWZXJzaW9ucyIsInNldHRpbmdzSnNvbiIsInNjYWZmb2xkUGx1Z2luc1ZlcnNpb24iLCJwbHVnaW5OYW1lIiwic2VtdmVyIiwibHQiLCJkZXNrdG9wRGVwZW5kZW5jaWVzIiwibWVyZ2VEZXBlbmRlbmNpZXMiLCJmcm9tU2V0dGluZ3MiLCJnZXRSZW1vdGVEZXBlbmRlbmNpZXMiLCJsb2NhbERlcGVuZGVuY2llcyIsImdldExvY2FsRGVwZW5kZW5jaWVzIiwiYXJjaCIsIl8iLCJ2YWx1ZXMiLCJsYXN0UmVidWlsZCIsInByZXBhcmVMYXN0UmVidWlsZE9iamVjdCIsImdldEd5cEVudiIsImZyYW1ld29ya0luZm8iLCJwbGF0Zm9ybSIsImluc3RhbGxlciIsIkxvY2FsSW5zdGFsbGVyIiwibnBtRW52IiwiaW5zdGFsbCIsImluc3RhbGxPclJlYnVpbGQiLCJwYWNrYWdlSnNvbkZpZWxkcyIsIm5hbWUiLCJwcm9qZWN0TmFtZSIsImdldEhhc2hWZXJzaW9uIiwiZGVza3RvcFZlcnNpb24iLCJtZXRlb3JEZXNrdG9wVmVyc2lvbiIsInByb2REZWJ1ZyIsImRlc2t0b3BUbXAiLCJyZWplY3QiLCJkZXNrdG9wQXNhciIsInRoZW4iLCJjYXRjaCIsInVnbGlmeU9wdGlvbnMiLCJ1Z2xpZnlpbmdFbmFibGVkIiwidWdsaWZ5IiwicHJlc2V0IiwiYXNzZXJ0VmVyc2lvbiIsInRhcmdldHMiLCJub2RlIiwiZGF0YSIsImZpbGVzIiwicmVhZERpciIsImZpbGUiLCJlbmRzV2l0aCIsImNvZGUiLCJwcmVzZXRzIiwibWluaWZ5IiwibWtkaXIiLCJjb25maWdzIiwiZ2F0aGVyTW9kdWxlQ29uZmlncyIsIm1vZHVsZUNvbmZpZyIsImZpbGVQYXRoIiwiZGVzdGluYXRpb25QYXRoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFuQkE7QUFxQkFBLGlCQUFNQyxNQUFOLENBQWFDLEtBQWIsR0FBcUIsSUFBckI7QUFFQTs7Ozs7QUFJZSxNQUFNQyxXQUFOLENBQWtCO0FBQzdCOzs7O0FBSUFDLEVBQUFBLFdBQVcsQ0FBQ0MsQ0FBRCxFQUFJO0FBQ1gsU0FBS0MsR0FBTCxHQUFXLElBQUlDLFlBQUosQ0FBUSxhQUFSLENBQVg7QUFDQSxTQUFLQyxRQUFMLEdBQWdCLElBQUlDLDRCQUFKLENBQXdCSixDQUF4QixDQUFoQjtBQUNBLFNBQUtLLFdBQUwsR0FBbUIsSUFBSUMsNEJBQUosQ0FDZk4sQ0FEZSxFQUVmLEtBQUtHLFFBQUwsQ0FBY0kscUJBQWQsR0FBc0NDLFlBRnZCLENBQW5CO0FBSUEsU0FBS1IsQ0FBTCxHQUFTQSxDQUFUO0FBQ0EsU0FBS1MsU0FBTCxHQUFpQixLQUFLVCxDQUFMLENBQU9TLFNBQXhCO0FBQ0EsU0FBS0MsV0FBTCxHQUFtQixJQUFuQjtBQUNBLFNBQUtDLE9BQUwsR0FBZSxJQUFmO0FBQ0EsU0FBS0Msb0JBQUwsR0FBNEIsSUFBNUI7QUFDQSxTQUFLQyxrQkFBTCxHQUEwQixDQUFDLDZCQUFELENBQTFCO0FBQ0g7QUFFRDs7Ozs7OztBQUtBQyxFQUFBQSxrQkFBa0IsQ0FBQ0MsY0FBYyxHQUFHLEVBQWxCLEVBQXNCO0FBQ3BDLFNBQUtkLEdBQUwsQ0FBU2UsSUFBVCxDQUFjLHVEQUFkO0FBQ0EsV0FBTyxJQUFJQyxPQUFKLENBQWFDLE9BQUQsSUFBYTtBQUM1QixZQUFNQyxPQUFPLEdBQUcsS0FBS0MsbUJBQUwsRUFBaEIsQ0FENEIsQ0FHNUI7QUFDQTs7QUFDQSxXQUFLbkIsR0FBTCxDQUFTb0IsS0FBVCxDQUFlLGdDQUFmOztBQUVBQyxrQkFBR0MsVUFBSCxDQUNJLEtBQUt2QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCQyxXQURqQyxFQUVJQyxjQUFLQyxJQUFMLENBQVUsS0FBSzdCLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJJLE9BQXZDLEVBQWdELGNBQWhELENBRko7O0FBS0EsVUFBSUMsU0FBUyxHQUFHLEtBQWhCO0FBQ0FBLE1BQUFBLFNBQVMsR0FBRyxLQUFLQyxjQUFMLENBQW9CYixPQUFwQixDQUFaO0FBRUEsV0FBS2xCLEdBQUwsQ0FBU29CLEtBQVQsQ0FBZSxTQUFmOztBQUNBWSxvQkFBS0MsYUFBTCxDQUNJLEtBQUtsQyxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCSSxPQURqQyxFQUVJLEtBQUs5QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCUyxPQUZqQyxFQUdJLE1BQU07QUFDRjtBQUNBLGFBQUtsQyxHQUFMLENBQVNvQixLQUFULENBQWUsdUNBQWY7O0FBRUExQix5QkFBTXlDLEVBQU4sQ0FDSVIsY0FBS0MsSUFBTCxDQUFVLEtBQUs3QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCSSxPQUF2QyxFQUFnRCxjQUFoRCxDQURKLEVBRUksS0FBSzlCLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJDLFdBRmpDOztBQUtBLFlBQUlJLFNBQUosRUFBZTtBQUNYO0FBQ0E7QUFDQVosVUFBQUEsT0FBTyxDQUFDa0IsT0FBUixDQUFnQkMsTUFBTSxJQUFJM0MsaUJBQU00QyxFQUFOLENBQ3RCLEtBRHNCLEVBRXRCWCxjQUFLQyxJQUFMLENBQVUsS0FBSzdCLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJjLG9CQUF2QyxFQUE2REYsTUFBN0QsQ0FGc0IsRUFHdEJWLGNBQUtDLElBQUwsQ0FBVSxLQUFLN0IsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QkMsV0FBdkMsRUFBb0RXLE1BQXBELENBSHNCLENBQTFCLEVBSFcsQ0FTWDs7QUFDQSxjQUFJLEtBQUt0QyxDQUFMLENBQU95QyxLQUFQLENBQWFDLE1BQWIsQ0FDQSxLQUFLMUMsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QmlCLHVCQUQ3QixDQUFKLEVBRUc7QUFDQ2hELDZCQUFNNEMsRUFBTixDQUNJWCxjQUFLQyxJQUFMLENBQVUsS0FBSzdCLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJpQix1QkFBdkMsRUFBZ0UsR0FBaEUsQ0FESixFQUVJZixjQUFLQyxJQUFMLENBQVUsS0FBSzdCLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJDLFdBQXZDLEVBQW9ELE1BQXBELENBRko7QUFJSDtBQUNKOztBQUVELGFBQUsxQixHQUFMLENBQVNvQixLQUFULENBQWUsdUJBQWY7QUFDQSxjQUFNdUIsT0FBTyxHQUFHLENBQUMsS0FBSzVDLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJDLFdBQTlCLEVBQTJDa0IsTUFBM0MsQ0FDWixDQUNJLEtBQUs3QyxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCUyxPQURqQyxFQUVJLEtBQUtuQyxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCaEIsV0FGakMsQ0FEWSxFQUtaSyxjQUxZLENBQWhCOztBQVFBK0IscUJBQUlDLElBQUosQ0FDSSxDQUFFLEdBQUUsS0FBSy9DLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJzQixJQUFLLEdBQUVwQixjQUFLcUIsR0FBSSxHQUFqRCxFQUFxREosTUFBckQsQ0FDSUQsT0FBTyxDQUFDTSxHQUFSLENBQVlDLGFBQWEsSUFBSyxJQUFHQSxhQUFjLEVBQS9DLENBREosQ0FESixFQUlJO0FBQUVDLFVBQUFBLEtBQUssRUFBRTtBQUFULFNBSko7O0FBTUFsQyxRQUFBQSxPQUFPO0FBQ1YsT0FoREw7QUFrREgsS0FsRU0sQ0FBUDtBQW1FSDtBQUVEOzs7Ozs7O0FBS0FjLEVBQUFBLGNBQWMsQ0FBQ2IsT0FBRCxFQUFVO0FBQ3BCLFVBQU1rQyxHQUFHLEdBQUcsQ0FBQyxLQUFELEVBQVEsTUFBUixFQUFnQixLQUFoQixFQUF1QixNQUF2QixFQUErQixFQUEvQixDQUFaOztBQUVBLFFBQUlsQyxPQUFPLENBQUNtQyxNQUFSLEdBQWlCLENBQXJCLEVBQXdCO0FBQ3BCLFVBQUksS0FBS3RELENBQUwsQ0FBT3lDLEtBQVAsQ0FBYUMsTUFBYixDQUFvQixLQUFLMUMsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QmMsb0JBQWpELENBQUosRUFBNEU7QUFDeEU3Qyx5QkFBTTRELEVBQU4sQ0FBUyxLQUFULEVBQWdCLEtBQUt2RCxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCYyxvQkFBN0M7QUFDSDs7QUFDRGxCLGtCQUFHa0MsU0FBSCxDQUFhLEtBQUt4RCxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCYyxvQkFBMUM7O0FBQ0FsQixrQkFBR2tDLFNBQUgsQ0FBYSxLQUFLeEQsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QmlCLHVCQUExQzs7QUFFQXhCLE1BQUFBLE9BQU8sQ0FBQ2tCLE9BQVIsQ0FBaUJDLE1BQUQsSUFBWTtBQUN4QmhCLG9CQUFHQyxVQUFILENBQ0lLLGNBQUtDLElBQUwsQ0FBVSxLQUFLN0IsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QkksT0FBdkMsRUFBZ0QsY0FBaEQsRUFBZ0VRLE1BQWhFLENBREosRUFFSVYsY0FBS0MsSUFBTCxDQUFVLEtBQUs3QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCYyxvQkFBdkMsRUFBNkRGLE1BQTdELENBRkosRUFEd0IsQ0FLeEI7OztBQUNBLGFBQUttQixVQUFMLENBQWdCbkIsTUFBaEIsRUFBd0JlLEdBQXhCO0FBQ0gsT0FQRDtBQVNBLGFBQU8sSUFBUDtBQUNIOztBQUNELFdBQU8sS0FBUDtBQUNIO0FBRUQ7Ozs7Ozs7O0FBTUFJLEVBQUFBLFVBQVUsQ0FBQ25CLE1BQUQsRUFBU2UsR0FBVCxFQUFjO0FBQ3BCLFFBQUkzQyxXQUFKOztBQUNBLFFBQUk7QUFDQUEsTUFBQUEsV0FBVyxHQUFHZ0QsSUFBSSxDQUFDQyxLQUFMLENBQ1ZyQyxZQUFHc0MsWUFBSCxDQUNJaEMsY0FBS0MsSUFBTCxDQUNJLEtBQUs3QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCYyxvQkFEakMsRUFDdURGLE1BRHZELEVBQytELGNBRC9ELENBREosRUFJSSxNQUpKLENBRFUsQ0FBZDtBQVFILEtBVEQsQ0FTRSxPQUFPdUIsQ0FBUCxFQUFVO0FBQ1JuRCxNQUFBQSxXQUFXLEdBQUcsRUFBZDtBQUNIOztBQUdELFVBQU1vRCxJQUFJLEdBQUksU0FBU3BELFdBQVQsSUFBd0IsT0FBT0EsV0FBVyxDQUFDcUQsR0FBbkIsS0FBMkIsUUFBcEQsR0FBZ0VDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZdkQsV0FBVyxDQUFDcUQsR0FBeEIsQ0FBaEUsR0FBK0YsRUFBNUc7O0FBRUEsUUFBSUQsSUFBSSxDQUFDUixNQUFMLEdBQWMsQ0FBbEIsRUFBcUI7QUFDakJRLE1BQUFBLElBQUksQ0FBQ3pCLE9BQUwsQ0FBYzBCLEdBQUQsSUFBUztBQUNsQlYsUUFBQUEsR0FBRyxDQUFDaEIsT0FBSixDQUFhNkIsU0FBRCxJQUFlO0FBQ3ZCLGdCQUFNQyxXQUFXLEdBQUd2QyxjQUFLQyxJQUFMLENBQ2hCLEtBQUs3QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCSSxPQURiLEVBRWhCLGNBRmdCLEVBR2hCLE1BSGdCLEVBSWYsR0FBRWlDLEdBQUksR0FBRUcsU0FBVSxFQUpILENBQXBCOztBQU1BLGNBQUksS0FBS2xFLENBQUwsQ0FBT3lDLEtBQVAsQ0FBYUMsTUFBYixDQUFvQnlCLFdBQXBCLEtBQ0EsS0FBS25FLENBQUwsQ0FBT3lDLEtBQVAsQ0FBYTJCLGFBQWIsQ0FBMkJELFdBQTNCLENBREosRUFFRTtBQUNFN0Msd0JBQUdDLFVBQUgsQ0FDSTRDLFdBREosRUFFSXZDLGNBQUtDLElBQUwsQ0FDSSxLQUFLN0IsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QmlCLHVCQURqQyxFQUVLLEdBQUVvQixHQUFJLEdBQUVHLFNBQVUsRUFGdkIsQ0FGSjtBQU9IO0FBQ0osU0FsQkQ7QUFtQkgsT0FwQkQ7QUFxQkg7QUFDSjtBQUVEOzs7OztBQUdBOUMsRUFBQUEsbUJBQW1CLEdBQUc7QUFDbEIsVUFBTWlELHFCQUFxQixHQUN2QixJQUFJQyw4QkFBSixDQUF5QixLQUFLdEUsQ0FBTCxDQUFPd0IsR0FBUCxDQUFXQyxLQUFYLENBQWlCQyxXQUFqQixDQUE2QkMsV0FBdEQsQ0FESjtBQUVBLFVBQU00QyxhQUFhLEdBQUdGLHFCQUFxQixDQUFDRyxNQUF0QixFQUF0QjtBQUVBLFFBQUk7QUFBRXJELE1BQUFBO0FBQUYsUUFBYyxLQUFLbkIsQ0FBTCxDQUFPeUUsT0FBUCxDQUFlQyxXQUFmLEVBQWxCOztBQUVBLFFBQUksQ0FBQ0MsS0FBSyxDQUFDQyxPQUFOLENBQWN6RCxPQUFkLENBQUwsRUFBNkI7QUFDekJBLE1BQUFBLE9BQU8sR0FBRyxFQUFWO0FBQ0g7O0FBRUQsVUFBTTBELEtBQUssR0FBRyxFQUFkO0FBQ0FOLElBQUFBLGFBQWEsQ0FBQzFCLE1BQWQsQ0FBcUIxQixPQUFyQixFQUE4QmtCLE9BQTlCLENBQXVDQyxNQUFELElBQVk7QUFDOUN1QyxNQUFBQSxLQUFLLENBQUN2QyxNQUFELENBQUwsR0FBZ0IsSUFBaEI7QUFDSCxLQUZEO0FBR0FuQixJQUFBQSxPQUFPLEdBQUc2QyxNQUFNLENBQUNDLElBQVAsQ0FBWVksS0FBWixDQUFWOztBQUNBLFFBQUkxRCxPQUFPLENBQUNtQyxNQUFSLEdBQWlCLENBQXJCLEVBQXdCO0FBQ3BCLFdBQUtyRCxHQUFMLENBQVM2RSxPQUFULENBQWtCLHlDQUF3QzNELE9BQU8sQ0FBQ1UsSUFBUixDQUFhLElBQWIsQ0FBbUIsRUFBN0U7QUFDSDs7QUFDRCxXQUFPVixPQUFQO0FBQ0g7QUFFRDs7Ozs7QUFHQTRELEVBQUFBLDZCQUE2QixHQUFHO0FBQzVCLFNBQUs5RSxHQUFMLENBQVM2RSxPQUFULENBQWlCLG1DQUFqQjtBQUNBLFVBQU1FLFFBQVEsR0FBRyxLQUFLaEYsQ0FBTCxDQUFPeUUsT0FBUCxDQUFlQyxXQUFmLEVBQWpCOztBQUVBLFFBQUssb0NBQW9DTSxRQUF6QyxFQUFvRDtBQUNoRCxXQUFLcEUsb0JBQUwsR0FBNkIsR0FBRW9FLFFBQVEsQ0FBQ0MsOEJBQStCLEVBQXZFO0FBQ0EsV0FBS2hGLEdBQUwsQ0FBU2lGLElBQVQsQ0FBZSx1Q0FBc0MsS0FBS3RFLG9CQUFxQixFQUEvRTtBQUNBO0FBQ0g7O0FBRUQsVUFBTXVFLEdBQUcsR0FBR0MsZ0JBQU9DLFVBQVAsQ0FBa0IsS0FBbEIsQ0FBWjs7QUFDQSxRQUFJN0UsWUFBWSxHQUFHLEtBQUtILFdBQUwsQ0FBaUJpRixlQUFqQixFQUFuQjtBQUNBLFVBQU1DLGtCQUFrQixHQUFHdkIsTUFBTSxDQUFDQyxJQUFQLENBQVl6RCxZQUFaLEVBQTBCZ0YsSUFBMUIsRUFBM0I7QUFDQWhGLElBQUFBLFlBQVksR0FBRytFLGtCQUFrQixDQUFDckMsR0FBbkIsQ0FBdUJ1QyxVQUFVLElBQzNDLEdBQUVBLFVBQVcsSUFBR2pGLFlBQVksQ0FBQ2lGLFVBQUQsQ0FBYSxFQUQvQixDQUFmO0FBRUEsVUFBTUMsd0JBQXdCLEdBQUcsS0FBSzFGLENBQUwsQ0FBTzJGLFVBQVAsR0FBb0JDLEtBQXBCLENBQTBCLEdBQTFCLENBQWpDO0FBQ0EsU0FBSzNGLEdBQUwsQ0FBU29CLEtBQVQsQ0FBZSwwQ0FBZixFQUNLLEdBQUVxRSx3QkFBd0IsQ0FBQyxDQUFELENBQUksRUFEbkM7QUFFQWxGLElBQUFBLFlBQVksQ0FBQ3FGLElBQWIsQ0FDSyxrQkFBaUJILHdCQUF3QixDQUFDLENBQUQsQ0FBSSxFQURsRDtBQUlBLFVBQU1JLDJCQUEyQixHQUFHZCxRQUFRLENBQUNyRSxPQUFULENBQWlCaUYsS0FBakIsQ0FBdUIsR0FBdkIsRUFBNEIsQ0FBNUIsQ0FBcEM7QUFDQSxTQUFLM0YsR0FBTCxDQUFTb0IsS0FBVCxDQUFlLG9DQUFmLEVBQXFEeUUsMkJBQXJEO0FBQ0F0RixJQUFBQSxZQUFZLENBQUNxRixJQUFiLENBQ0ssZUFBY0MsMkJBQTRCLEVBRC9DOztBQUlBLFFBQUlDLE9BQU8sQ0FBQ3ZFLEdBQVIsQ0FBWXdFLGtEQUFaLElBQ0FELE9BQU8sQ0FBQ3ZFLEdBQVIsQ0FBWXlFLG9CQURoQixFQUVFO0FBQ0UsV0FBS2hHLEdBQUwsQ0FBU29CLEtBQVQsQ0FBZ0IseUNBQXdDcUMsSUFBSSxDQUFDd0MsU0FBTCxDQUFlMUYsWUFBZixDQUE2QixFQUFyRjtBQUNIOztBQUVEMkUsSUFBQUEsR0FBRyxDQUFDZ0IsTUFBSixDQUFXekMsSUFBSSxDQUFDd0MsU0FBTCxDQUFlMUYsWUFBZixDQUFYO0FBRUEsU0FBS0ksb0JBQUwsR0FBNEJ1RSxHQUFHLENBQUNpQixNQUFKLENBQVcsS0FBWCxDQUE1QjtBQUNIOztBQUVELFFBQU1DLElBQU4sR0FBYTtBQUNULFFBQUk7QUFDQSxZQUFNLEtBQUtyRyxDQUFMLENBQU9zRyxRQUFQLENBQWdCRCxJQUFoQixFQUFOO0FBQ0EsWUFBTSxLQUFLckcsQ0FBTCxDQUFPdUcsZUFBUCxDQUF1QkYsSUFBdkIsRUFBTjtBQUNILEtBSEQsQ0FHRSxPQUFPeEMsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBU2lGLElBQVQsQ0FBYyw2RUFBZCxFQUE2RnJCLENBQTdGO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7QUFDSjtBQUVEOzs7OztBQUdBLFFBQU1DLEtBQU4sQ0FBWUMsR0FBRyxHQUFHLEtBQWxCLEVBQXlCO0FBQ3JCO0FBQ0EsU0FBS3pHLEdBQUwsQ0FBU2UsSUFBVCxDQUFjLGFBQWQ7O0FBRUEsUUFBSSxDQUFDLEtBQUtoQixDQUFMLENBQU95RSxPQUFQLENBQWVrQyxLQUFmLEVBQUwsRUFBNkI7QUFDekIsVUFBSSxDQUFDLEtBQUszRyxDQUFMLENBQU93QixHQUFQLENBQVdvRixPQUFYLENBQW1CekcsUUFBeEIsRUFBa0M7QUFDOUIsYUFBS0YsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLHVFQUNYLCtEQURKLEVBRDhCLENBRzlCOztBQUNBZCxRQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0gsT0FMRCxNQUtPO0FBQ0gsYUFBS3hHLENBQUwsQ0FBT3lFLE9BQVAsQ0FBZXRFLFFBQWY7QUFDQSxhQUFLSCxDQUFMLENBQU9TLFNBQVAsQ0FBaUJxRyxlQUFqQjtBQUNIO0FBQ0o7O0FBRUQsVUFBTSxLQUFLVCxJQUFMLEVBQU47O0FBR0EsUUFBSTtBQUNBLFdBQUtyRyxDQUFMLENBQU9TLFNBQVAsQ0FBaUJxRyxlQUFqQjtBQUNILEtBRkQsQ0FFRSxPQUFPakQsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBU2lGLElBQVQsQ0FBZSwrQkFBOEIsS0FBS2xGLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkJxRixRQUFTLEVBQXJFLEdBQ1YsaUJBREosRUFDdUJsRCxDQUR2QjtBQUVIOztBQUVELFFBQUk7QUFDQSxZQUFNLEtBQUs3RCxDQUFMLENBQU9TLFNBQVAsQ0FBaUJ1Ryx3QkFBakIsRUFBTjtBQUNILEtBRkQsQ0FFRSxPQUFPbkQsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSw0Q0FBZixFQUE2RGhELENBQTdEO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFlBQU0sS0FBS3hHLENBQUwsQ0FBT1MsU0FBUCxDQUFpQndHLHdCQUFqQixFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU9wRCxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLDhDQUFmLEVBQStEaEQsQ0FBL0Q7QUFDQWtDLE1BQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDs7QUFFRCxRQUFJO0FBQ0EsWUFBTSxLQUFLckcsUUFBTCxDQUFjK0csSUFBZCxFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU9yRCxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLDJCQUFmLEVBQTRDaEQsQ0FBNUM7QUFDQWtDLE1BQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDs7QUFFRCxRQUFJO0FBQ0EsWUFBTVcsUUFBUSxHQUFHLFFBQWpCO0FBQ0EsWUFBTUMsT0FBTyxHQUFHLHVCQUFoQjs7QUFDQSxVQUFJOUYsWUFBRytGLFVBQUgsQ0FBY0QsT0FBZCxLQUEwQjlGLFlBQUcrRixVQUFILENBQWNGLFFBQWQsQ0FBOUIsRUFBdUQ7QUFDbkQ3RixvQkFBR2dHLFlBQUgsQ0FBZ0JILFFBQWhCLEVBQTJCLEdBQUVDLE9BQVEsSUFBR0QsUUFBUyxFQUFqRDtBQUNIO0FBQ0osS0FORCxDQU1FLE9BQU90RCxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTaUYsSUFBVCxDQUFjLDRCQUFkLEVBQTRDckIsQ0FBNUM7QUFDSDs7QUFFRCxRQUFJO0FBQ0EsWUFBTSxLQUFLMEQscUJBQUwsRUFBTjtBQUNILEtBRkQsQ0FFRSxPQUFPMUQsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSx5Q0FBZixFQUEwRGhELENBQTFEO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFdBQUtnQix1QkFBTDtBQUNILEtBRkQsQ0FFRSxPQUFPM0QsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSxxQ0FBZixFQUFzRGhELENBQXREO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFdBQUs0RCxzQkFBTDtBQUNILEtBRkQsQ0FFRSxPQUFPNUQsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSx5Q0FBZixFQUEwRGhELENBQTFEO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFdBQUtrQiw2QkFBTDtBQUNILEtBRkQsQ0FFRSxPQUFPbEIsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSxpREFBZixFQUFrRWhELENBQWxFO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFlBQU0sS0FBS2tCLDBCQUFMLEVBQU47QUFDSCxLQUZELENBRUUsT0FBTzdELENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsd0RBQWYsRUFBeUVoRCxDQUF6RTtBQUNBa0MsTUFBQUEsT0FBTyxDQUFDUyxJQUFSLENBQWEsQ0FBYjtBQUNIOztBQUVELFFBQUltQixrQkFBSjs7QUFDQSxRQUFJO0FBQ0FBLE1BQUFBLGtCQUFrQixHQUFHLE1BQU0sS0FBS0Msd0JBQUwsRUFBM0I7QUFDSCxLQUZELENBRUUsT0FBTy9ELENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsOENBQWYsRUFBK0RoRCxDQUEvRDtBQUNBa0MsTUFBQUEsT0FBTyxDQUFDUyxJQUFSLENBQWEsQ0FBYjtBQUNIOztBQUVELFFBQUk7QUFDQSxZQUFNLEtBQUtxQixXQUFMLENBQWlCLElBQWpCLENBQU47QUFDSCxLQUZELENBRUUsT0FBT2hFLENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsZ0RBQWYsRUFBaUVoRCxDQUFqRTtBQUNBa0MsTUFBQUEsT0FBTyxDQUFDUyxJQUFSLENBQWEsQ0FBYjtBQUNIOztBQUVELFFBQUksQ0FBQ21CLGtCQUFMLEVBQXlCO0FBQ3JCLFVBQUk7QUFDQSxjQUFNLEtBQUtFLFdBQUwsRUFBTjtBQUNILE9BRkQsQ0FFRSxPQUFPaEUsQ0FBUCxFQUFVO0FBQ1IsYUFBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSx1REFBZixFQUF3RWhELENBQXhFO0FBQ0FrQyxRQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7QUFDSjs7QUFFRCxRQUFJO0FBQ0EsWUFBTSxLQUFLc0IsZUFBTCxFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU9qRSxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFnQiw0QkFBMkJoRCxDQUFFLEVBQTdDO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFlBQU0sS0FBS3VCLHVCQUFMLEVBQU47QUFDSCxLQUZELENBRUUsT0FBT2xFLENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsc0RBQWYsRUFBdUVoRCxDQUF2RTtBQUNBa0MsTUFBQUEsT0FBTyxDQUFDUyxJQUFSLENBQWEsQ0FBYjtBQUNIOztBQUdELFFBQUk7QUFDQSxZQUFNLEtBQUt3Qix3QkFBTCxFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU9uRSxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLG1FQUFmLEVBQW9GaEQsQ0FBcEY7QUFDQWtDLE1BQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDs7QUFHRCxRQUFJLEtBQUt4RyxDQUFMLENBQU93QixHQUFQLENBQVd5RyxpQkFBWCxFQUFKLEVBQW9DO0FBQ2hDLFVBQUk7QUFDQSxjQUFNLEtBQUtuSCxrQkFBTCxFQUFOO0FBQ0gsT0FGRCxDQUVFLE9BQU8rQyxDQUFQLEVBQVU7QUFDUixhQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLHdDQUFmLEVBQXlEaEQsQ0FBekQ7QUFDQWtDLFFBQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDtBQUNKLEtBaEpvQixDQWtKckI7OztBQUNBLFFBQUk7QUFDQSxXQUFLMEIsd0JBQUw7QUFDSCxLQUZELENBRUUsT0FBT3JFLENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsd0RBQWYsRUFBeUVoRCxDQUF6RTtBQUNBa0MsTUFBQUEsT0FBTyxDQUFDUyxJQUFSLENBQWEsQ0FBYjtBQUNIOztBQUVELFFBQUk7QUFDQSxZQUFNLEtBQUsyQix3QkFBTCxFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU90RSxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLHNDQUFmLEVBQXVEaEQsQ0FBdkQ7QUFDQWtDLE1BQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDs7QUFFRCxRQUFJO0FBQ0EsWUFBTSxLQUFLNEIsdUJBQUwsRUFBTjtBQUNILEtBRkQsQ0FFRSxPQUFPdkUsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSxvREFBZixFQUFxRWhELENBQXJFO0FBQ0FrQyxNQUFBQSxPQUFPLENBQUNTLElBQVIsQ0FBYSxDQUFiO0FBQ0g7O0FBRUQsUUFBSTtBQUNBLFlBQU0sS0FBSzZCLGtCQUFMLEVBQU47QUFDSCxLQUZELENBRUUsT0FBT3hFLENBQVAsRUFBVTtBQUNSLFdBQUs1RCxHQUFMLENBQVM0RyxLQUFULENBQWUsd0NBQWYsRUFBeURoRCxDQUF6RDtBQUNIOztBQUVELFFBQUk7QUFDQSxZQUFNLEtBQUt5RSxpQkFBTCxFQUFOO0FBQ0gsS0FGRCxDQUVFLE9BQU96RSxDQUFQLEVBQVU7QUFDUixXQUFLNUQsR0FBTCxDQUFTNEcsS0FBVCxDQUFlLGlEQUFmLEVBQWtFaEQsQ0FBbEU7QUFDQWtDLE1BQUFBLE9BQU8sQ0FBQ1MsSUFBUixDQUFhLENBQWI7QUFDSDs7QUFFRCxRQUFJO0FBQ0EsWUFBTSxLQUFLK0Isb0JBQUwsRUFBTjtBQUNILEtBRkQsQ0FFRSxPQUFPMUUsQ0FBUCxFQUFVO0FBQ1IsV0FBSzVELEdBQUwsQ0FBUzRHLEtBQVQsQ0FBZSxxREFBZixFQUFzRWhELENBQXRFO0FBQ0g7O0FBRUQsUUFBSTZDLEdBQUosRUFBUztBQUNMLFdBQUt6RyxHQUFMLENBQVNlLElBQVQsQ0FBYyxTQUFkO0FBQ0EsV0FBS2hCLENBQUwsQ0FBT3NHLFFBQVAsQ0FBZ0JJLEdBQWhCO0FBQ0gsS0FIRCxNQUdPO0FBQ0gsV0FBS3pHLEdBQUwsQ0FBU2UsSUFBVCxDQUFjLE9BQWQ7QUFDSDtBQUNKO0FBRUQ7Ozs7OztBQUlBdUcsRUFBQUEscUJBQXFCLEdBQUc7QUFDcEIsVUFBTTtBQUFFaUIsTUFBQUE7QUFBRixRQUFxQixLQUFLeEksQ0FBTCxDQUFPeUUsT0FBUCxDQUFlQyxXQUFmLEVBQTNCOztBQUNBLFFBQUk4RCxjQUFjLElBQUk3RCxLQUFLLENBQUNDLE9BQU4sQ0FBYzRELGNBQWQsQ0FBbEIsSUFBbURBLGNBQWMsQ0FBQ2xGLE1BQWYsR0FBd0IsQ0FBL0UsRUFBa0Y7QUFDOUUsVUFBSW1GLE9BQU8sR0FBR25ILFlBQUdzQyxZQUFILENBQWdCLEtBQUs1RCxDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCK0csT0FBN0MsRUFBc0QsTUFBdEQsQ0FBZDs7QUFDQSxZQUFNQyxPQUFPLEdBQUcsS0FBSzFJLENBQUwsQ0FBT3lFLE9BQVAsQ0FBZUMsV0FBZixHQUNYOEQsY0FEVyxDQUVYRyxNQUZXLEVBR1I7QUFDQSxPQUFDQyxJQUFELEVBQU90RyxNQUFQLE1BQW1Cc0csSUFBSSxJQUFLLElBQUd0RyxNQUFPLEtBQW5CLEVBQXlCc0csSUFBNUMsQ0FKUSxFQUkyQyxFQUozQyxDQUFoQjtBQU9BSCxNQUFBQSxPQUFPLEdBQUdBLE9BQU8sQ0FBQ0ksT0FBUixDQUFnQiwwQkFBaEIsRUFBNkMsMkJBQTBCSCxPQUFRLEVBQS9FLENBQVY7O0FBQ0FwSCxrQkFBR3dILGFBQUgsQ0FBaUIsS0FBSzlJLENBQUwsQ0FBT3dCLEdBQVAsQ0FBV0MsS0FBWCxDQUFpQkMsV0FBakIsQ0FBNkIrRyxPQUE5QyxFQUF1REEsT0FBdkQ7QUFDSDtBQUNKO0FBRUQ7Ozs7OztBQUlBLFFBQU1ULHdCQUFOLEdBQWlDO0FBQzdCLFFBQUllLFFBQVEsR0FBRyxFQUFmO0FBQ0EsVUFBTUMsbUJBQW1CLEdBQUcsRUFBNUI7QUFDQSxRQUFJQyxPQUFPLEdBQUcsV0FBZDtBQUVBakYsSUFBQUEsTUFBTSxDQUFDQyxJQUFQLENBQVksS0FBS2pFLENBQUwsQ0FBT3lFLE9BQVAsQ0FBZWEsZUFBZixHQUFpQzJELE9BQTdDLEVBQXNENUcsT0FBdEQsQ0FBK0Q2RyxNQUFELElBQVk7QUFDdEU7QUFDQSxZQUFNeEksV0FBVyxHQUNiZ0QsSUFBSSxDQUFDQyxLQUFMLENBQ0lyQyxZQUFHc0MsWUFBSCxDQUNJaEMsY0FBS0MsSUFBTCxDQUNJLEtBQUs3QixDQUFMLENBQU93QixHQUFQLENBQVdDLEtBQVgsQ0FBaUJDLFdBQWpCLENBQTZCQyxXQURqQyxFQUM4Q3VILE1BRDlDLEVBQ3NELGNBRHRELENBREosRUFJSSxNQUpKLENBREosQ0FESjs7QUFVQSxVQUFJLHdCQUF3QnhJLFdBQXhCLElBQXVDLE9BQU9BLFdBQVcsQ0FBQ3lJLGtCQUFuQixLQUEwQyxRQUFyRixFQUErRjtBQUMzRkYsUUFBQUEsT0FBTyxJQUFLLEdBQUVDLE1BQU8sSUFBckI7QUFDQUgsUUFBQUEsUUFBUSxDQUFDSyxPQUFUL