@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
364 lines • 39.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InstallPackage = exports.SfpPackageInstallationOptions = void 0;
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const PackageInstallationResult_1 = require("./PackageInstallationResult");
const ProjectConfig_1 = __importDefault(require("../../project/ProjectConfig"));
const SFPStatsSender_1 = __importDefault(require("../../stats/SFPStatsSender"));
const AssignPermissionSets_1 = __importDefault(require("../../permsets/AssignPermissionSets"));
const ScriptExecutorHelpers_1 = __importDefault(require("../../scriptExecutor/ScriptExecutorHelpers"));
const fs = __importStar(require("fs-extra"));
const FileSystem_1 = __importDefault(require("../../utils/FileSystem"));
const OrgDetailsFetcher_1 = __importDefault(require("../../org/OrgDetailsFetcher"));
const path = require("path");
const PermissionSetGroupUpdateAwaiter_1 = __importDefault(require("../../permsets/PermissionSetGroupUpdateAwaiter"));
const SfpPackage_1 = require("../SfpPackage");
const DeploymentExecutor_1 = require("../../deployers/DeploymentExecutor");
const GetFormattedTime_1 = __importDefault(require("../../utils/GetFormattedTime"));
const TestOptions_1 = require("../../apextest/TestOptions");
const PostDeployersRegistry_1 = require("../deploymentCustomizers/PostDeployersRegistry");
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const PreDeployersRegistry_1 = require("../deploymentCustomizers/PreDeployersRegistry");
const AnalyzerRegistry_1 = require("../analyser/AnalyzerRegistry");
class SfpPackageInstallationOptions {
constructor() {
this.apexcompile = 'package';
this.securitytype = 'none';
this.upgradetype = 'mixed-mode';
this.publishWaitTime = 60;
this.disableArtifactCommit = false;
this.isDryRun = false;
}
}
exports.SfpPackageInstallationOptions = SfpPackageInstallationOptions;
class InstallPackage {
constructor(sfpPackage, sfpOrg, logger, options) {
this.sfpPackage = sfpPackage;
this.sfpOrg = sfpOrg;
this.logger = logger;
this.options = options;
this._isArtifactToBeCommittedInOrg = true;
}
async exec() {
let startTime = Date.now();
let elapsedTime;
try {
this.packageDescriptor = ProjectConfig_1.default.getSFDXPackageDescriptor(this.sfpPackage.sourceDir, this.sfpPackage.packageName);
this.connection = this.sfpOrg.getConnection();
if (await this.isPackageToBeInstalled(this.options.skipIfPackageInstalled)) {
if (!this.options.isDryRun) {
await this.waitTillAllPermissionSetGroupIsUpdated();
await this.assignPermsetsPreDeployment();
await this.executePreDeploymentScripts();
await this.setPackageDirectoryForPackage();
await this.executePreDeployers();
await this.checkPackageDirectoryExists();
await this.install();
await this.assignPermsetsPostDeployment();
await this.executePostDeployers();
await this.executePostDeploymentScript();
await this.commitPackageInstallationStatus();
elapsedTime = Date.now() - startTime;
this.sendMetricsWhenSuccessfullyInstalled(elapsedTime);
}
return { result: PackageInstallationResult_1.PackageInstallationStatus.Succeeded, elapsedTime: elapsedTime };
}
else {
sfp_logger_1.default.log('Skipping Package Installation', sfp_logger_1.LoggerLevel.INFO, this.logger);
return { result: PackageInstallationResult_1.PackageInstallationStatus.Skipped };
}
}
catch (error) {
elapsedTime = Date.now() - startTime;
this.sendMetricsWhenFailed(elapsedTime);
return {
result: PackageInstallationResult_1.PackageInstallationStatus.Failed,
message: error.message,
elapsedTime: elapsedTime,
};
}
}
checkPackageDirectoryExists() {
let absPackageDirectory = path.join(this.sfpPackage.sourceDir, this.packageDirectory);
if (!fs.existsSync(absPackageDirectory)) {
throw new Error(`Package directory ${absPackageDirectory} does not exist`);
}
}
async waitTillAllPermissionSetGroupIsUpdated() {
try {
//Package Has Permission Set Group
let permissionSetGroupUpdateAwaiter = new PermissionSetGroupUpdateAwaiter_1.default(this.connection, this.logger);
await permissionSetGroupUpdateAwaiter.waitTillAllPermissionSetGroupIsUpdated();
}
catch (error) {
//Ignore error
// Lets try proceeding
sfp_logger_1.default.log(`Unable to check the status of Permission Set Groups due to ${error}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
}
}
async setPackageDirectoryForPackage() {
if (this.packageDescriptor.aliasfy) {
const searchDirectory = path.join(this.sfpPackage.sourceDir, this.packageDescriptor.path);
const files = FileSystem_1.default.readdirRecursive(searchDirectory, true);
let aliasDir;
let alias = await this.sfpOrg.getAlias();
aliasDir = files.find((file) => path.basename(file) === alias && fs.lstatSync(path.join(searchDirectory, file)).isDirectory());
sfp_logger_1.default.log(`Using alias directory ${aliasDir ? aliasDir : 'default'}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
if (!aliasDir) {
const orgDetails = await new OrgDetailsFetcher_1.default(this.sfpOrg.getUsername()).getOrgDetails();
if (orgDetails.isSandbox) {
// If the target org is a sandbox, find a 'default' directory to use as package directory
aliasDir = files.find((file) => path.basename(file) === 'default' &&
fs.lstatSync(path.join(searchDirectory, file)).isDirectory());
}
}
if (!aliasDir) {
throw new Error(`Aliasfied package '${this.sfpPackage.packageName}' does not have an alias with '${alias}' or 'default' directory`);
}
this.packageDirectory = path.join(this.packageDescriptor.path, aliasDir);
}
else {
this.packageDirectory = path.join(this.packageDescriptor['path']);
}
}
sendMetricsWhenFailed(elapsedTime) {
sfp_logger_1.default.log(`Package ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(this.sfpPackage.package_name)} installation attempt failed,it took ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)((0, GetFormattedTime_1.default)(elapsedTime))}`);
SFPStatsSender_1.default.logCount('package.installation.failure', {
package: this.sfpPackage.package_name,
type: this.sfpPackage.package_type,
target_org: this.sfpOrg.getUsername(),
});
}
sendMetricsWhenSuccessfullyInstalled(elapsedTime) {
sfp_logger_1.default.log(`Package ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(this.sfpPackage.package_name)} installation took ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)((0, GetFormattedTime_1.default)(elapsedTime))}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
SFPStatsSender_1.default.logElapsedTime('package.installation.elapsed_time', elapsedTime, {
package: this.sfpPackage.package_name,
type: this.sfpPackage.package_type,
target_org: this.sfpOrg.getUsername(),
});
SFPStatsSender_1.default.logCount('package.installation', {
package: this.sfpPackage.package_name,
type: this.sfpPackage.package_type,
target_org: this.sfpOrg.getUsername(),
});
}
//Set this to disable whethere info about the artifact has to be recorded in the org
set isArtifactToBeCommittedInOrg(toCommit) {
this._isArtifactToBeCommittedInOrg = toCommit;
}
async commitPackageInstallationStatus() {
if (this._isArtifactToBeCommittedInOrg) {
try {
await this.sfpOrg.updateArtifactInOrg(this.logger, this.sfpPackage);
}
catch (error) {
sfp_logger_1.default.log('Unable to commit information about the package into org..Check whether prerequisities are installed', sfp_logger_1.LoggerLevel.WARN, this.logger);
}
}
}
async isPackageToBeInstalled(skipIfPackageInstalled) {
if (skipIfPackageInstalled) {
let installationStatus = await this.sfpOrg.isArtifactInstalledInOrg(this.logger, this.sfpPackage);
return !installationStatus.isInstalled;
}
else if (this.sfpPackage.packageType == SfpPackage_1.PackageType.Diff) {
// If diff package, check if there are any changes to be deployed, else skip
if (!this.sfpPackage.destructiveChanges && this.sfpPackage.metadataCount == 0) {
return false;
}
}
return true; // Always install packages if skipIfPackageInstalled is false
}
async assignPermsetsPreDeployment() {
try {
if (this.sfpPackage.assignPermSetsPreDeployment) {
sfp_logger_1.default.log('Assigning permission sets before deployment:', sfp_logger_1.LoggerLevel.INFO, this.logger);
await AssignPermissionSets_1.default.applyPermsets(this.sfpPackage.assignPermSetsPreDeployment, this.connection, this.sfpPackage.sourceDir, this.logger);
}
}
catch (error) {
//Proceed ahead not a critical error to break installation
sfp_logger_1.default.log(`Unable to assign permsets (Pre Deployment) due to ${error}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
}
}
async executePreDeploymentScripts() {
let preDeploymentScript = path.join(this.sfpPackage.sourceDir, `scripts`, `preDeployment`);
if (fs.existsSync(preDeploymentScript)) {
let alias = await this.sfpOrg.getAlias();
sfp_logger_1.default.log('Executing preDeployment script', sfp_logger_1.LoggerLevel.INFO, this.logger);
await ScriptExecutorHelpers_1.default.executeScript(this.logger, preDeploymentScript, this.sfpPackage.packageName, this.sfpOrg.getUsername(), alias ? alias : this.sfpOrg.getUsername(), this.sfpPackage.sourceDir, this.sfpPackage.packageDirectory);
}
}
async assignPermsetsPostDeployment() {
try {
if (this.sfpPackage.assignPermSetsPostDeployment) {
sfp_logger_1.default.log('Assigning permission sets after deployment:', sfp_logger_1.LoggerLevel.INFO, this.logger);
await AssignPermissionSets_1.default.applyPermsets(this.sfpPackage.assignPermSetsPostDeployment, this.connection, this.sfpPackage.sourceDir, this.logger);
}
}
catch (error) {
//Proceed ahead not a critical error to break installation
sfp_logger_1.default.log(`Unable to assign permsets (Post Deployment) due to ${error}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
}
}
async executePostDeploymentScript() {
let postDeploymentScript = path.join(this.sfpPackage.sourceDir, `scripts`, `postDeployment`);
if (fs.existsSync(postDeploymentScript)) {
sfp_logger_1.default.log('Executing postDeployment script', sfp_logger_1.LoggerLevel.INFO, this.logger);
let alias = await this.sfpOrg.getAlias();
await ScriptExecutorHelpers_1.default.executeScript(this.logger, postDeploymentScript, this.sfpPackage.packageName, this.sfpOrg.getUsername(), alias ? alias : this.sfpOrg.getUsername(), this.sfpPackage.sourceDir, this.sfpPackage.packageDirectory);
}
}
async executePostDeployers() {
sfp_logger_1.default.log(`Executing Post Deployers`, sfp_logger_1.LoggerLevel.INFO, this.logger);
//Gather componentSet
let componentSet = source_deploy_retrieve_1.ComponentSet.fromSource(path.join(this.sfpPackage.projectDirectory, this.sfpPackage.packageDirectory));
for (const postDeployer of PostDeployersRegistry_1.PostDeployersRegistry.getPostDeployers()) {
try {
if (await postDeployer.isEnabled(this.sfpPackage, this.connection, this.logger)) {
sfp_logger_1.default.log(`Executing Post Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(postDeployer.getName())}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
await postDeployer.execute(this.sfpPackage, componentSet, this.sfpOrg, this.logger, { apiVersion: this.options.apiVersion, waitTime: this.options.waitTime });
}
else {
sfp_logger_1.default.log(`Post Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(postDeployer.getName())} skipped or not enabled`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
}
catch (error) {
sfp_logger_1.default.log(`Unable to process post deploy for ${postDeployer.getName()} due to ${error.message}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
sfp_logger_1.default.log(`Pre Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(postDeployer.getName())} skipped due to error`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
}
}
async executePreDeployers() {
sfp_logger_1.default.log(`Executing Pre Deployers`, sfp_logger_1.LoggerLevel.INFO, this.logger);
//Gather componentSet
let componentSet = source_deploy_retrieve_1.ComponentSet.fromSource(path.join(this.sfpPackage.projectDirectory, this.sfpPackage.packageDirectory));
let analyzers = AnalyzerRegistry_1.AnalyzerRegistry.getAnalyzers();
for (const analyzer of analyzers) {
if (await analyzer.isEnabled(this.sfpPackage, this.logger)) {
sfp_logger_1.default.log(`Executing ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(analyzer.getName())}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
this.sfpPackage = await analyzer.analyze(this.sfpPackage, componentSet, this.logger);
}
else {
sfp_logger_1.default.log(`Skipped ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(analyzer.getName())}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
}
for (const preDeployer of PreDeployersRegistry_1.PreDeployersRegistry.getPreDeployers()) {
try {
if (await preDeployer.isEnabled(this.sfpPackage, this.connection, this.logger)) {
sfp_logger_1.default.log(`Executing Pre Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(preDeployer.getName())}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
await preDeployer.execute(this.sfpPackage, componentSet, this.sfpOrg, this.logger, { apiVersion: this.options.apiVersion, waitTime: this.options.waitTime });
}
else {
sfp_logger_1.default.log(`Pre Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(preDeployer.getName())} skipped or not enabled`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
}
catch (error) {
sfp_logger_1.default.log(`Unable to process pre deploy for ${preDeployer.getName()} due to ${error.message}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
sfp_logger_1.default.log(`Pre Deployer ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(preDeployer.getName())} skipped due to error`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
}
}
async generateDeploymentOptions(waitTime, optimizeDeployment, skipTest, target_org, apiVersion) {
let deploymentOptions = {
ignoreWarnings: true,
waitTime: waitTime,
};
deploymentOptions.ignoreWarnings = true;
deploymentOptions.waitTime = waitTime;
deploymentOptions.apiVersion = apiVersion;
//Find Org Type
let orgDetails;
try {
orgDetails = await new OrgDetailsFetcher_1.default(target_org).getOrgDetails();
}
catch (err) {
sfp_logger_1.default.log(`Unable to fetch org details,assuming it is production`, sfp_logger_1.LoggerLevel.WARN, this.logger);
orgDetails = {
instanceUrl: undefined,
isScratchOrg: false,
isSandbox: false,
organizationType: undefined,
sfdxAuthUrl: undefined,
status: undefined,
};
}
if (this.options.deploymentType == DeploymentExecutor_1.DeploymentType.MDAPI_DEPLOY && this.sfpPackage.isApexFound && this.options.isInstallingForValidation == false) {
if (orgDetails.isSandbox) {
//enforce during selective deployment
if (skipTest) {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunNoTests;
}
else if (this.sfpPackage.apexTestClassses.length > 0 && optimizeDeployment) {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunSpecifiedTests;
deploymentOptions.specifiedTests = this.getAStringOfSpecificTestClasses(this.sfpPackage.apexTestClassses);
}
else {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunLocalTests;
}
}
else {
if (this.sfpPackage.apexTestClassses.length > 0 && optimizeDeployment) {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunSpecifiedTests;
deploymentOptions.specifiedTests = this.getAStringOfSpecificTestClasses(this.sfpPackage.apexTestClassses);
}
else {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunLocalTests;
}
}
}
// #Issue 1417
// Handle the use-cases of a not optimized source package validating
else if (this.sfpPackage.packageType == SfpPackage_1.PackageType.Source && this.sfpPackage.isApexFound && this.options.isInstallingForValidation && !optimizeDeployment) {
if (skipTest) {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunNoTests;
}
else {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunLocalTests;
}
}
else {
if (orgDetails.isSandbox) {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunNoTests;
}
else {
deploymentOptions.testLevel = TestOptions_1.TestLevel.RunSpecifiedTests;
deploymentOptions.specifiedTests = 'skip';
}
}
deploymentOptions.rollBackOnError = true;
return deploymentOptions;
}
getAStringOfSpecificTestClasses(apexTestClassses) {
let specifedTests = apexTestClassses.join();
return specifedTests;
}
}
exports.InstallPackage = InstallPackage;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW5zdGFsbFBhY2thZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9wYWNrYWdlL3BhY2thZ2VJbnN0YWxsZXJzL0luc3RhbGxQYWNrYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUVBQXlGO0FBQ3pGLDJFQUFtRztBQUNuRyxnRkFBd0Q7QUFDeEQsZ0ZBQXdEO0FBQ3hELCtGQUF1RTtBQUN2RSx1R0FBd0U7QUFFeEUsNkNBQStCO0FBQy9CLHdFQUFnRDtBQUNoRCxvRkFBNEU7QUFDNUUsNkJBQThCO0FBQzlCLHFIQUE2RjtBQUU3Riw4Q0FBd0Q7QUFDeEQsMkVBQTRHO0FBRTVHLG9GQUE0RDtBQUM1RCw0REFBdUQ7QUFDdkQsMEZBQXVGO0FBQ3ZGLCtFQUFrRTtBQUdsRSx3RkFBcUY7QUFDckYsbUVBQWdFO0FBRWhFLE1BQWEsNkJBQTZCO0lBQTFDO1FBRUksZ0JBQVcsR0FBWSxTQUFTLENBQUM7UUFDakMsaUJBQVksR0FBWSxNQUFNLENBQUM7UUFDL0IsZ0JBQVcsR0FBWSxZQUFZLENBQUM7UUFHcEMsb0JBQWUsR0FBWSxFQUFFLENBQUM7UUFJOUIsMEJBQXFCLEdBQWEsS0FBSyxDQUFDO1FBR3hDLGFBQVEsR0FBYSxLQUFLLENBQUM7SUFFL0IsQ0FBQztDQUFBO0FBaEJELHNFQWdCQztBQUVELE1BQXNCLGNBQWM7SUFPaEMsWUFDYyxVQUFzQixFQUN0QixNQUFjLEVBQ2QsTUFBYyxFQUNkLE9BQXNDO1FBSHRDLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxZQUFPLEdBQVAsT0FBTyxDQUErQjtRQU41QyxrQ0FBNkIsR0FBWSxJQUFJLENBQUM7SUFPbEQsQ0FBQztJQUVFLEtBQUssQ0FBQyxJQUFJO1FBQ2IsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzNCLElBQUksV0FBbUIsQ0FBQztRQUN4QixJQUFJLENBQUM7WUFDRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsdUJBQWEsQ0FBQyx3QkFBd0IsQ0FDM0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUM5QixDQUFDO1lBRUYsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBRTlDLElBQUksTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLENBQUM7Z0JBQ3pFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUN6QixNQUFNLElBQUksQ0FBQyxzQ0FBc0MsRUFBRSxDQUFDO29CQUNwRCxNQUFNLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO29CQUN6QyxNQUFNLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO29CQUN6QyxNQUFNLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO29CQUMzQyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO29CQUNqQyxNQUFNLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO29CQUN6QyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDckIsTUFBTSxJQUFJLENBQUMsNEJBQTRCLEVBQUUsQ0FBQztvQkFDMUMsTUFBTSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztvQkFDbEMsTUFBTSxJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztvQkFDekMsTUFBTSxJQUFJLENBQUMsK0JBQStCLEVBQUUsQ0FBQztvQkFFN0MsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUM7b0JBQ3JDLElBQUksQ0FBQyxvQ0FBb0MsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDM0QsQ0FBQztnQkFDRCxPQUFPLEVBQUUsTUFBTSxFQUFFLHFEQUF5QixDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7WUFDckYsQ0FBQztpQkFBTSxDQUFDO2dCQUNKLG9CQUFTLENBQUMsR0FBRyxDQUFDLCtCQUErQixFQUFFLHdCQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDOUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxxREFBeUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6RCxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsQ0FBQztZQUNyQyxJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDeEMsT0FBTztnQkFDSCxNQUFNLEVBQUUscURBQXlCLENBQUMsTUFBTTtnQkFDeEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO2dCQUN0QixXQUFXLEVBQUUsV0FBVzthQUMzQixDQUFDO1FBQ04sQ0FBQztJQUNMLENBQUM7SUFFRCwyQkFBMkI7UUFDdkIsSUFBSSxtQkFBbUIsR0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixtQkFBbUIsaUJBQWlCLENBQUMsQ0FBQztRQUMvRSxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxzQ0FBc0M7UUFDaEQsSUFBSSxDQUFDO1lBQ0Qsa0NBQWtDO1lBQ2xDLElBQUksK0JBQStCLEdBQW9DLElBQUkseUNBQStCLENBQ3RHLElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FDZCxDQUFDO1lBQ0YsTUFBTSwrQkFBK0IsQ0FBQyxzQ0FBc0MsRUFBRSxDQUFDO1FBQ25GLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsY0FBYztZQUNkLHNCQUFzQjtZQUN0QixvQkFBUyxDQUFDLEdBQUcsQ0FDVCw4REFBOEQsS0FBSyxFQUFFLEVBQ3JFLHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7UUFDTixDQUFDO0lBQ0wsQ0FBQztJQUVTLEtBQUssQ0FBQyw2QkFBNkI7UUFDekMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakMsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUYsTUFBTSxLQUFLLEdBQUcsb0JBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFakUsSUFBSSxRQUFnQixDQUFDO1lBRXJCLElBQUksS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QyxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FDakIsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FDMUcsQ0FBQztZQUVGLG9CQUFTLENBQUMsR0FBRyxDQUFDLHlCQUF5QixRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRXpHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDWixNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksMkJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUUxRixJQUFJLFVBQVUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDdkIseUZBQXlGO29CQUN6RixRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FDakIsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNMLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssU0FBUzt3QkFDakMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUNuRSxDQUFDO2dCQUNOLENBQUM7WUFDTCxDQUFDO1lBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNaLE1BQU0sSUFBSSxLQUFLLENBQ1gsc0JBQXNCLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxrQ0FBa0MsS0FBSywwQkFBMEIsQ0FDckgsQ0FBQztZQUNOLENBQUM7WUFFRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdFLENBQUM7YUFDSyxDQUFDO1lBQ0gsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDdEUsQ0FBQztJQUVMLENBQUM7SUFFTyxxQkFBcUIsQ0FBQyxXQUFtQjtRQUM3QyxvQkFBUyxDQUFDLEdBQUcsQ0FDVCxXQUFXLElBQUEsOEJBQWlCLEVBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUMvQix3Q0FBd0MsSUFBQSw4QkFBaUIsRUFBQyxJQUFBLDBCQUFnQixFQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FDOUYsQ0FBQztRQUNGLHdCQUFjLENBQUMsUUFBUSxDQUFDLDhCQUE4QixFQUFFO1lBQ3BELE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVk7WUFDckMsSUFBSSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWTtZQUNsQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUU7U0FDeEMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLG9DQUFvQyxDQUFDLFdBQW1CO1FBQzVELG9CQUFTLENBQUMsR0FBRyxDQUNULFdBQVcsSUFBQSw4QkFBaUIsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsSUFBQSw4QkFBaUIsRUFDN0YsSUFBQSwwQkFBZ0IsRUFBQyxXQUFXLENBQUMsQ0FDaEMsRUFBRSxFQUNILHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7UUFDRix3QkFBYyxDQUFDLGNBQWMsQ0FBQyxtQ0FBbUMsRUFBRSxXQUFXLEVBQUU7WUFDNUUsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWTtZQUNyQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZO1lBQ2xDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRTtTQUN4QyxDQUFDLENBQUM7UUFDSCx3QkFBYyxDQUFDLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRTtZQUM1QyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZO1lBQ3JDLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVk7WUFDbEMsVUFBVSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFO1NBQ3hDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxvRkFBb0Y7SUFDcEYsSUFBVyw0QkFBNEIsQ0FBQyxRQUFpQjtRQUNyRCxJQUFJLENBQUMsNkJBQTZCLEdBQUcsUUFBUSxDQUFDO0lBQ2xELENBQUM7SUFFTyxLQUFLLENBQUMsK0JBQStCO1FBQ3pDLElBQUksSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7WUFDckMsSUFBSSxDQUFDO2dCQUNELE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN4RSxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDYixvQkFBUyxDQUFDLEdBQUcsQ0FDVCxxR0FBcUcsRUFDckcsd0JBQVcsQ0FBQyxJQUFJLEVBQ2hCLElBQUksQ0FBQyxNQUFNLENBQ2QsQ0FBQztZQUNOLENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztJQUVTLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxzQkFBK0I7UUFDbEUsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1lBQ3pCLElBQUksa0JBQWtCLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2xHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUM7UUFDM0MsQ0FBQzthQUFNLElBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLElBQUksd0JBQVcsQ0FBQyxJQUFJLEVBQ3pELENBQUM7WUFDQyw0RUFBNEU7WUFDM0UsSUFBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLElBQUUsQ0FBQyxFQUMxRSxDQUFDO2dCQUNBLE9BQU8sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNKLENBQUM7UUFFQSxPQUFPLElBQUksQ0FBQyxDQUFDLDZEQUE2RDtJQUMvRSxDQUFDO0lBRU8sS0FBSyxDQUFDLDJCQUEyQjtRQUNyQyxJQUFJLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztnQkFDOUMsb0JBQVMsQ0FBQyxHQUFHLENBQUMsOENBQThDLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUU3RixNQUFNLDhCQUFvQixDQUFDLGFBQWEsQ0FDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQywyQkFBMkIsRUFDM0MsSUFBSSxDQUFDLFVBQVUsRUFDZixJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFDekIsSUFBSSxDQUFDLE1BQU0sQ0FDZCxDQUFDO1lBQ04sQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsMERBQTBEO1lBQzFELG9CQUFTLENBQUMsR0FBRyxDQUFDLHFEQUFxRCxLQUFLLEVBQUUsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0csQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsMkJBQTJCO1FBQ3BDLElBQUksbUJBQW1CLEdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDbkcsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUNyQyxJQUFJLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDekMsb0JBQVMsQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9FLE1BQU0sK0JBQWMsQ0FBQyxhQUFhLENBQzlCLElBQUksQ0FBQyxNQUFNLEVBQ1gsbUJBQW1CLEVBQ25CLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUN6QixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFDekMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQ25DLENBQUM7UUFDTixDQUFDO0lBQ0wsQ0FBQztJQUlPLEtBQUssQ0FBQyw0QkFBNEI7UUFDdEMsSUFBSSxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLDRCQUE0QixFQUFFLENBQUM7Z0JBQy9DLG9CQUFTLENBQUMsR0FBRyxDQUFDLDZDQUE2QyxFQUFFLHdCQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFFNUYsTUFBTSw4QkFBb0IsQ0FBQyxhQUFhLENBQ3BDLElBQUksQ0FBQyxVQUFVLENBQUMsNEJBQTRCLEVBQzVDLElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQ3pCLElBQUksQ0FBQyxNQUFNLENBQ2QsQ0FBQztZQUNOLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNiLDBEQUEwRDtZQUMxRCxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxzREFBc0QsS0FBSyxFQUFFLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hILENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLDJCQUEyQjtRQUNwQyxJQUFJLG9CQUFvQixHQUFXLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDckcsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDLEVBQUUsQ0FBQztZQUN0QyxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDaEYsSUFBSSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sK0JBQWMsQ0FBQyxhQUFhLENBQzlCLElBQUksQ0FBQyxNQUFNLEVBQ1gsb0JBQW9CLEVBQ3BCLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUN6QixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFDekMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQ25DLENBQUM7UUFDTixDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxvQkFBb0I7UUFDOUIsb0JBQVMsQ0FBQyxHQUFHLENBQUMsMEJBQTBCLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXpFLHFCQUFxQjtRQUNyQixJQUFJLFlBQVksR0FBRyxxQ0FBWSxDQUFDLFVBQVUsQ0FDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FDaEYsQ0FBQztRQUVGLEtBQUssTUFBTSxZQUFZLElBQUksNkNBQXFCLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDO1lBQ2xFLElBQUksQ0FBQztnQkFDRCxJQUFJLE1BQU0sWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQzlFLG9CQUFTLENBQUMsR0FBRyxDQUNULDJCQUEyQixJQUFBLDhCQUFpQixFQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQ3RFLHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7b0JBRUYsTUFBTSxZQUFZLENBQUMsT0FBTyxDQUN0QixJQUFJLENBQUMsVUFBVSxFQUNmLFlBQVksRUFDWixJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxNQUFNLEVBQ1gsRUFBQyxVQUFVLEVBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUMsUUFBUSxFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFDLENBQ3RFLENBQUM7Z0JBRU4sQ0FBQztxQkFBTSxDQUFDO29CQUNKLG9CQUFTLENBQUMsR0FBRyxDQUNULGlCQUFpQixJQUFBLDhCQUFpQixFQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQyx5QkFBeUIsRUFDbkYsd0JBQVcsQ0FBQyxJQUFJLEVBQ2hCLElBQUksQ0FBQyxNQUFNLENBQ2QsQ0FBQztnQkFDTixDQUFDO1lBQ0wsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2Isb0JBQVMsQ0FBQyxHQUFHLENBQ1QscUNBQXFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsV0FBVyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQ3JGLHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7Z0JBQ0Ysb0JBQVMsQ0FBQyxHQUFHLENBQ1QsZ0JBQWdCLElBQUEsOEJBQWlCLEVBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDLHVCQUF1QixFQUNoRix3QkFBVyxDQUFDLElBQUksRUFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FDZCxDQUFDO1lBQ04sQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLG1CQUFtQjtRQUM3QixvQkFBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFeEUscUJBQXFCO1FBQ3JCLElBQUksWUFBWSxHQUFHLHFDQUFZLENBQUMsVUFBVSxDQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUNoRixDQUFDO1FBRUYsSUFBSSxTQUFTLEdBQUcsbUNBQWdCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDaEQsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUMvQixJQUFHLE1BQU0sUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFDekQsQ0FBQztnQkFDQyxvQkFBUyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUEsOEJBQWlCLEVBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRSx3QkFBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ25HLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0RixDQUFDO2lCQUVELENBQUM7Z0JBQ0csb0JBQVMsQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFBLDhCQUFpQixFQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUUsd0JBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JHLENBQUM7UUFDTCxDQUFDO1FBRUQsS0FBSyxNQUFNLFdBQVcsSUFBSSwyQ0FBb0IsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO1lBQy9ELElBQUksQ0FBQztnQkFDRCxJQUFJLE1BQU0sV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQzdFLG9CQUFTLENBQUMsR0FBRyxDQUNULDBCQUEwQixJQUFBLDhCQUFpQixFQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQ3BFLHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7b0JBRUYsTUFBTSxXQUFXLENBQUMsT0FBTyxDQUNyQixJQUFJLENBQUMsVUFBVSxFQUNmLFlBQVksRUFDWixJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxNQUFNLEVBQ1gsRUFBQyxVQUFVLEVBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUMsUUFBUSxFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFDLENBQ3RFLENBQUM7Z0JBRU4sQ0FBQztxQkFBTSxDQUFDO29CQUNKLG9CQUFTLENBQUMsR0FBRyxDQUNULGdCQUFnQixJQUFBLDhCQUFpQixFQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyx5QkFBeUIsRUFDakYsd0JBQVcsQ0FBQyxJQUFJLEVBQ2hCLElBQUksQ0FBQyxNQUFNLENBQ2QsQ0FBQztnQkFDTixDQUFDO1lBQ0wsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2Isb0JBQVMsQ0FBQyxHQUFHLENBQ1Qsb0NBQW9DLFdBQVcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQ25GLHdCQUFXLENBQUMsSUFBSSxFQUNoQixJQUFJLENBQUMsTUFBTSxDQUNkLENBQUM7Z0JBQ0Ysb0JBQVMsQ0FBQyxHQUFHLENBQ1QsZ0JBQWdCLElBQUEsOEJBQWlCLEVBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLHVCQUF1QixFQUMvRSx3QkFBVyxDQUFDLElBQUksRUFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FDZCxDQUFDO1lBQ04sQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRVMsS0FBSyxDQUFDLHlCQUF5QixDQUNyQyxRQUFnQixFQUNoQixrQkFBMkIsRUFDM0IsUUFBaUIsRUFDakIsVUFBa0IsRUFDbEIsVUFBa0I7UUFFbEIsSUFBSSxpQkFBaUIsR0FBc0I7WUFDdkMsY0FBYyxFQUFFLElBQUk7WUFDcEIsUUFBUSxFQUFFLFFBQVE7U0FDckIsQ0FBQztRQUNGLGlCQUFpQixDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDeEMsaUJBQWlCLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN0QyxpQkFBaUIsQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBRTFDLGVBQWU7UUFDZixJQUFJLFVBQXNCLENBQUM7UUFDM0IsSUFBSSxDQUFDO1lBQ0QsVUFBVSxHQUFHLE1BQU0sSUFBSSwyQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN6RSxDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNYLG9CQUFTLENBQUMsR0FBRyxDQUFDLHVEQUF1RCxFQUFFLHdCQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0RyxVQUFVLEdBQUc7Z0JBQ1QsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLFlBQVksRUFBRSxLQUFLO2dCQUNuQixTQUFTLEVBQUUsS0FBSztnQkFDaEIsZ0JBQWdCLEVBQUUsU0FBUztnQkFDM0IsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLE1BQU0sRUFBRSxTQUFTO2FBQ3BCLENBQUM7UUFDTixDQUFDO1FBR0YsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsSUFBSSxtQ0FBYyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLHlCQUF5QixJQUFJLEtBQUssRUFBRSxDQUFDO1lBQzlJLElBQUksVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUN2QixxQ0FBcUM7Z0JBQ3JDLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ1gsaUJBQWlCLENBQUMsU0FBUyxHQUFHLHVCQUFTLENBQUMsVUFBVSxDQUFDO2dCQUN2RCxDQUFDO3FCQUFNLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLGtCQUFrQixFQUFFLENBQUM7b0JBQzNFLGlCQUFpQixDQUFDLFNBQVMsR0FBRyx1QkFBUyxDQUFDLGlCQUFpQixDQUFDO29CQUMxRCxpQkFBaUIsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLCtCQUErQixDQUNuRSxJQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUNuQyxDQUFDO2dCQUNOLENBQUM7cUJBQU0sQ0FBQztvQkFDSixpQkFBaUIsQ0FBQyxTQUFTLEdBQUcsdUJBQVMsQ0FBQyxhQUFhLENBQUM7Z0JBQzFELENBQUM7WUFDTCxDQUFDO2lCQUFNLENBQUM7Z0JBQ0osSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksa0JBQWtCLEVBQUUsQ0FBQztvQkFDcEUsaUJBQWlCLENBQUMsU0FBUyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQUM7b0JBQzFELGlCQUFpQixDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsK0JBQStCLENBQ25FLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQ25DLENBQUM7Z0JBQ04sQ0FBQztxQkFBTSxDQUFDO29CQUNKLGlCQUFpQixDQUFDLFNBQVMsR0FBRyx1QkFBUyxDQUFDLGFBQWEsQ0FBQztnQkFDMUQsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBQ0QsY0FBYztRQUNkLG9FQUFvRTthQUMvRCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxJQUFJLHdCQUFXLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMseUJBQXlCLElBQUksQ0FBQyxrQkFBa0IsRUFBRyxDQUFDO1lBQzFKLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ1gsaUJBQWlCLENBQUMsU0FBUyxHQUFHLHVCQUFTLENBQUMsVUFBVSxDQUFDO1lBQ3ZELENBQUM7aUJBQU0sQ0FBQztnQkFDSixpQkFBaUIsQ0FBQyxTQUFTLEdBQUcsdUJBQVMsQ0FBQyxhQUFhLENBQUM7WUFDMUQsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3ZCLGlCQUFpQixDQUFDLFNBQVMsR0FBRyx1QkFBUyxDQUFDLFVBQVUsQ0FBQztZQUN2RCxDQUFDO2lCQUFNLENBQUM7Z0JBQ0osaUJBQWlCLENBQUMsU0FBUyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQUM7Z0JBQzFELGlCQUFpQixDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUM7WUFDOUMsQ0FBQztRQUNMLENBQUM7UUFFRCxpQkFBaUIsQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO1FBQ3pDLE9BQU8saUJBQWlCLENBQUM7SUFDN0IsQ0FBQztJQUVPLCtCQUErQixDQUFDLGdCQUEwQjtRQUM5RCxJQUFJLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM1QyxPQUFPLGFBQWEsQ0FBQztJQUN6QixDQUFDO0NBQ0o7QUFyY0Qsd0NBcWNDIn0=