webpack-strip-log-loader
Version:
Remove log statements from any logging module
428 lines • 38.2 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const ts = __importStar(require("byots"));
const fs = __importStar(require("fs"));
const loader_utils_1 = require("loader-utils");
const path = __importStar(require("path"));
const tmp = __importStar(require("tmp"));
const logger = __importStar(require("loglevel"));
const minimatch_1 = __importDefault(require("minimatch"));
const flatMap = require('array.prototype.flatmap');
flatMap.shim();
if (process.env.NODE_ENV === 'trace') {
logger.setDefaultLevel(logger.levels.TRACE);
}
else if (process.env.NODE_ENV === 'debug') {
logger.setDefaultLevel(logger.levels.DEBUG);
}
else {
logger.setDefaultLevel(logger.levels.ERROR);
}
const utils_1 = require("./utils");
const ignoreRegex = /^\/\/(\W*)strip-log(\W*)$/i;
function isNodeCommentTrigger(node, sourceFile) {
const comments = utils_1.getComments(node, sourceFile.getFullText(), true);
const matchingComment = comments.find(tmpComment => {
return ignoreRegex.test(tmpComment);
});
if (matchingComment !== undefined) {
return true;
}
else {
return false;
}
}
class PluginLoader {
constructor(loaderContext, sourceText) {
this.restrictedSymbols = new Set();
this.restrictedExpressions = new Set();
this.sourceText = sourceText;
let rawOptions = loader_utils_1.getOptions(loaderContext);
if (rawOptions === null) {
rawOptions = {};
}
rawOptions.modules = rawOptions.modules || [];
this.options = rawOptions;
this.initTypescriptCompiler();
}
process() {
this.findAllImportClauses();
this.findAllRequireStatements();
this.findExplicitlyRestrictedSymbols();
this.findAllSymbolsAndExpressions();
const targetText = this.returntransformedSource();
this.cleanup();
return targetText;
}
initTypescriptCompiler() {
logger.trace(`Input file content: \n ${this.sourceText}`);
this.tmpFile = tmp.fileSync({
postfix: '.js',
});
fs.writeFileSync(this.tmpFile.fd, this.sourceText);
this.tsProgram = ts.createProgram([this.tmpFile.name], {
allowJs: true,
noResolve: true,
});
this.tsChecker = this.tsProgram.getTypeChecker();
for (const tmpSourceFile of this.tsProgram.getSourceFiles()) {
if (!tmpSourceFile.isDeclarationFile) {
if (path.normalize(tmpSourceFile.fileName) ===
path.normalize(this.tmpFile.name)) {
this.mainSourceFile = tmpSourceFile;
}
}
}
if (this.mainSourceFile === undefined) {
this.cleanup();
throw new TypeError('Source file not found');
}
}
findAllImportClauses() {
this.mainSourceFile = this.mainSourceFile;
const allImportClauses = utils_1.findChildNodes(this.mainSourceFile, ts.isImportDeclaration);
for (const tmpImportClause of allImportClauses) {
if (tmpImportClause) {
if (isNodeCommentTrigger(tmpImportClause, this.mainSourceFile) ||
this.isImportModuleNameRestrictedGlobally(tmpImportClause)) {
logger.trace(`Checking import statement: ${utils_1.nodeToString(tmpImportClause, this.mainSourceFile)}`);
this.restrictedExpressions.add(tmpImportClause);
if (tmpImportClause.importClause) {
if (tmpImportClause.importClause.name) {
const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportClause.importClause.name);
if (importedSymbol) {
this.restrictedSymbols.add(importedSymbol);
}
}
if (tmpImportClause.importClause.namedBindings) {
if (ts.isNamespaceImport(tmpImportClause.importClause.namedBindings)) {
const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportClause.importClause.namedBindings.name);
if (importedSymbol) {
this.restrictedSymbols.add(importedSymbol);
}
}
else if (ts.isNamedImports(tmpImportClause.importClause.namedBindings)) {
for (const tmpImportSpecifier of tmpImportClause.importClause
.namedBindings.elements) {
const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportSpecifier.name);
if (importedSymbol) {
this.restrictedSymbols.add(importedSymbol);
}
}
}
}
}
}
}
}
}
findAllRequireStatements() {
this.mainSourceFile = this.mainSourceFile;
const allRequireCalls = utils_1.findChildNodes(this.mainSourceFile, (node) => ts.isRequireCall(node, true));
for (const tmpRequireCall of allRequireCalls) {
const tmpRequireStatement = this.getParentStatement(tmpRequireCall);
if (tmpRequireStatement &&
(isNodeCommentTrigger(tmpRequireStatement, this.mainSourceFile) ||
this.isRequireModuleNameRestrictedGlobally(tmpRequireCall))) {
this.restrictedExpressions.add(tmpRequireCall);
}
}
}
findExplicitlyRestrictedSymbols() {
const restrictIdentierOrCommaBinaryExpression = (node) => {
if (ts.isIdentifier(node)) {
const trySymbol = this.tsChecker.getSymbolAtLocation(node);
if (trySymbol) {
this.restrictedSymbols.add(trySymbol);
}
}
else if (ts.isBinaryExpression(node) &&
node.operatorToken.kind === ts.SyntaxKind.CommaToken) {
restrictIdentierOrCommaBinaryExpression(node.left);
restrictIdentierOrCommaBinaryExpression(node.right);
}
};
const findExpResSymbolsInternal = (node) => {
if (ts.isExpressionStatement(node) &&
isNodeCommentTrigger(node, this.mainSourceFile)) {
restrictIdentierOrCommaBinaryExpression(node.expression);
}
else {
ts.forEachChild(node, findExpResSymbolsInternal);
}
};
ts.forEachChild(this.mainSourceFile, findExpResSymbolsInternal);
}
isImportModuleNameRestrictedGlobally(importClause) {
if (ts.isStringLiteral(importClause.moduleSpecifier)) {
const moduleName = importClause.moduleSpecifier.text;
return this.options.modules.some(modulePattern => minimatch_1.default(moduleName, modulePattern, this.options.matchOptions));
}
return false;
}
isRequireModuleNameRestrictedGlobally(requireCallExpression) {
if (ts.isRequireCall(requireCallExpression, true)) {
const moduleName = requireCallExpression
.arguments[0].text;
return this.options.modules.includes(moduleName);
}
return false;
}
isExpressionRestricted(checkeeExpression) {
return this.restrictedExpressions.has(checkeeExpression);
}
isSymbolRestricted(checkeeSymbol) {
const isRestrictedSymbol = this.restrictedSymbols.has(checkeeSymbol);
const isAliasedRestrictedSymbolOrExpr = this.isSymbolDeclaredWithRestrictedInit(checkeeSymbol) ||
this.isSymbolAssignedWithRestrictedInit(checkeeSymbol);
return isRestrictedSymbol || isAliasedRestrictedSymbolOrExpr;
}
isSymbolDeclaredWithRestrictedInit(checkeeSymbol) {
this.mainSourceFile = this.mainSourceFile;
const isDeclarationForGivenSymbol = (node) => {
if (ts.isVariableDeclaration(node)) {
const variableSymbol = this.tsChecker.getSymbolAtLocation(node.name);
const initializer = node.initializer;
if (variableSymbol === checkeeSymbol && initializer) {
const initializerSymbol = this.tsChecker.getSymbolAtLocation(initializer);
if ((initializerSymbol &&
this.restrictedSymbols.has(initializerSymbol)) ||
this.restrictedExpressions.has(initializer)) {
return true;
}
}
}
return false;
};
const matchingVarDecl = utils_1.findChildNode(this.mainSourceFile, isDeclarationForGivenSymbol);
return matchingVarDecl !== undefined;
}
isSymbolAssignedWithRestrictedInit(checkeeSymbol) {
this.mainSourceFile = this.mainSourceFile;
const isVariableAssignmentForGivenSymbol = (node) => {
if (ts.isBinaryExpression(node) &&
node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
const variableSymbol = this.tsChecker.getSymbolAtLocation(node.left);
const initializer = node.right;
if (variableSymbol === checkeeSymbol && initializer) {
const initializerSymbol = this.tsChecker.getSymbolAtLocation(initializer);
if ((initializerSymbol &&
this.restrictedSymbols.has(initializerSymbol)) ||
this.restrictedExpressions.has(initializer)) {
return true;
}
}
}
return false;
};
const matchingVarAssignment = utils_1.findChildNode(this.mainSourceFile, isVariableAssignmentForGivenSymbol);
return matchingVarAssignment !== undefined;
}
findAllSymbolsAndExpressions() {
this.mainSourceFile = this.mainSourceFile;
const findAndRecordMethods = [
this.findAndRecordPropertyAccess,
this.findAndRecordNewCalls,
this.findAndRecordFunctionCalls,
];
let oldRestrictedSymbolsLength = -1;
let oldRestrictedExpressionsLength = -1;
while (oldRestrictedSymbolsLength < this.restrictedSymbols.size ||
oldRestrictedExpressionsLength < this.restrictedExpressions.size) {
oldRestrictedSymbolsLength = this.restrictedSymbols.size;
oldRestrictedExpressionsLength = this.restrictedExpressions.size;
findAndRecordMethods.forEach(method => {
method.call(this);
});
}
const expressionsFromSymbols = [...this.restrictedSymbols].flatMap(symbol => this.findExpressionsWhichUseSymbol(symbol));
logger.trace(`Expression from symbols count: ${expressionsFromSymbols.length}`);
expressionsFromSymbols.forEach(expr => this.restrictedExpressions.add(expr));
}
findAndRecordPropertyAccess() {
this.mainSourceFile = this.mainSourceFile;
const checkPropAccess = (node) => {
if (ts.isPropertyAccessExpression(node)) {
const leftHandObjectIdentifier = node.expression;
const rightHandPropIdentifier = node.name;
const leftHandSymbol = this.tsChecker.getSymbolAtLocation(leftHandObjectIdentifier);
const rightHandSymbol = this.tsChecker.getSymbolAtLocation(rightHandPropIdentifier);
if ((leftHandSymbol && this.isSymbolRestricted(leftHandSymbol)) ||
this.isExpressionRestricted(leftHandObjectIdentifier)) {
this.restrictedExpressions.add(node);
if (leftHandSymbol) {
this.restrictedSymbols.add(leftHandSymbol);
}
}
}
else {
ts.forEachChild(node, checkPropAccess);
}
};
ts.forEachChild(this.mainSourceFile, checkPropAccess);
}
findAndRecordNewCalls() {
this.mainSourceFile = this.mainSourceFile;
const checkSymbolCall = (node) => {
if (ts.isNewExpression(node)) {
logger.trace('New expression check:', utils_1.nodeToString(node, this.mainSourceFile));
const expressionIdentifier = node.expression;
const expressionSymbol = this.tsChecker.getSymbolAtLocation(expressionIdentifier);
const newReturnSymbol = this.tsChecker.getSymbolAtLocation(node);
if ((expressionSymbol && this.isSymbolRestricted(expressionSymbol)) ||
this.isExpressionRestricted(expressionIdentifier)) {
this.restrictedExpressions.add(node);
if (expressionSymbol) {
this.restrictedSymbols.add(expressionSymbol);
}
}
}
else {
ts.forEachChild(node, checkSymbolCall);
}
};
ts.forEachChild(this.mainSourceFile, checkSymbolCall);
}
findAndRecordFunctionCalls() {
this.mainSourceFile = this.mainSourceFile;
const checkFunctionCall = (node) => {
if (ts.isCallExpression(node)) {
logger.trace('Call expression check:', utils_1.nodeToString(node, this.mainSourceFile));
const expressionIdentifier = node.expression;
const expressionSymbol = this.tsChecker.getSymbolAtLocation(expressionIdentifier);
const expressionReturnSymbol = this.tsChecker.getSymbolAtLocation(node);
if ((expressionSymbol && this.isSymbolRestricted(expressionSymbol)) ||
this.isExpressionRestricted(expressionIdentifier)) {
this.restrictedExpressions.add(node);
if (expressionSymbol) {
this.restrictedSymbols.add(expressionSymbol);
}
}
}
else {
ts.forEachChild(node, checkFunctionCall);
}
};
ts.forEachChild(this.mainSourceFile, checkFunctionCall);
}
findExpressionsWhichUseSymbol(checkeesymbol, hoistToStatements) {
this.mainSourceFile = this.mainSourceFile;
if (hoistToStatements === undefined) {
hoistToStatements = false;
}
const matchingExpressions = [];
const findExpressionInternal = (node) => {
const trySymbol = this.tsChecker.getSymbolAtLocation(node);
if (trySymbol && trySymbol === checkeesymbol) {
let toPush = node;
if (hoistToStatements) {
toPush = this.getParentStatement(node);
}
if (toPush !== undefined) {
matchingExpressions.push(node);
}
}
ts.forEachChild(node, findExpressionInternal);
};
ts.forEachChild(this.mainSourceFile, findExpressionInternal);
return matchingExpressions;
}
logFindDetails(expressions) {
logger.debug('Found symbols: ', [...this.restrictedSymbols]
.map(tmpSymbol => tmpSymbol.getName())
.join(', '));
logger.debug('Found expressions: ', expressions
.map(expr => utils_1.nodeToString(expr, this.mainSourceFile))
.join(', '));
}
getParentStatement(node) {
return utils_1.findParentOrSelfNode(node, ts.isStatement);
}
returntransformedSource() {
let newText = this.sourceText;
const toRemoveExpressions = [...this.restrictedExpressions]
.map((node) => {
return this.getParentStatement(node);
})
.filter(statementOrUndefined => {
return statementOrUndefined !== undefined;
});
const revSortedExpressions = toRemoveExpressions.sort((expr1, expr2) => {
if (utils_1.getNodeEnd(expr1) !== utils_1.getNodeEnd(expr2)) {
if (utils_1.getNodeEnd(expr1) > utils_1.getNodeEnd(expr2)) {
return -1;
}
else {
return +1;
}
}
else {
if (utils_1.getNodeStart(expr1) < utils_1.getNodeStart(expr2)) {
return -1;
}
else {
return +1;
}
}
});
this.logFindDetails(revSortedExpressions);
for (let exprIndex = 0; exprIndex < revSortedExpressions.length; exprIndex++) {
this.mainSourceFile = this.mainSourceFile;
const currentExpr = revSortedExpressions[exprIndex];
if (exprIndex > 0) {
const prevExpr = revSortedExpressions[exprIndex - 1];
if (utils_1.getNodeEnd(currentExpr) > utils_1.getNodeStart(prevExpr)) {
if (utils_1.getNodeStart(currentExpr) >= utils_1.getNodeStart(prevExpr) &&
utils_1.getNodeEnd(currentExpr) <= utils_1.getNodeEnd(prevExpr)) {
logger.trace(`Skipping expression as it is completely contained: ${utils_1.nodeToString(currentExpr, this.mainSourceFile)}`);
continue;
}
else {
throw new Error('Breaking build as there is non-contained overlap between 2 expressions');
}
}
}
const startPosition = utils_1.getNodeStart(currentExpr);
let endPosition = utils_1.getNodeEnd(currentExpr);
if (newText.slice(endPosition, endPosition + 1) === '\n') {
endPosition += 1;
}
else if (newText.slice(endPosition, endPosition + 2) === '\r\n') {
endPosition += 2;
}
newText =
newText.slice(0, startPosition) +
'' +
newText.slice(endPosition);
}
return newText;
}
cleanup() {
this.tmpFile.removeCallback();
}
}
const schema = {
type: 'object',
properties: {
test: {
type: 'string',
},
},
};
function loader(sourceText) {
const options = loader_utils_1.getOptions(this);
const newLoaderInstance = new PluginLoader(this, sourceText);
return newLoaderInstance.process();
}
exports.default = loader;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wbHVnaW4tbG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDBDQUE0QjtBQUM1Qix1Q0FBeUI7QUFDekIsK0NBQXdEO0FBQ3hELDJDQUE2QjtBQUM3Qix5Q0FBMkI7QUFFM0IsaURBQW1DO0FBQ25DLDBEQUFrQztBQUVsQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUduRCxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7QUFFZixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRTtJQUNwQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDN0M7S0FBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRTtJQUMzQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDN0M7S0FBTTtJQUNMLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztDQUM3QztBQUVELG1DQVFpQjtBQUVqQixNQUFNLFdBQVcsR0FBRyw0QkFBNEIsQ0FBQztBQUVqRCw4QkFBOEIsSUFBYSxFQUFFLFVBQXlCO0lBQ3BFLE1BQU0sUUFBUSxHQUFHLG1CQUFXLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVuRSxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQ2pELE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0QyxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksZUFBZSxLQUFLLFNBQVMsRUFBRTtRQUNqQyxPQUFPLElBQUksQ0FBQztLQUNiO1NBQU07UUFDTCxPQUFPLEtBQUssQ0FBQztLQUNkO0FBQ0gsQ0FBQztBQU9EO0lBV0UsWUFBWSxhQUEwQyxFQUFFLFVBQWtCO1FBSmxFLHNCQUFpQixHQUFtQixJQUFJLEdBQUcsRUFBYSxDQUFDO1FBQ3pELDBCQUFxQixHQUFpQixJQUFJLEdBQUcsRUFBVyxDQUFDO1FBSS9ELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksVUFBVSxHQUFHLHlCQUFVLENBQUMsYUFBYSxDQUF3QixDQUFDO1FBQ2xFLElBQUksVUFBVSxLQUFLLElBQUksRUFBRTtZQUN2QixVQUFVLEdBQUcsRUFBRSxDQUFDO1NBQ2pCO1FBQ0QsVUFBVSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQWlDLENBQUM7UUFFakQsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7SUFDaEMsQ0FBQztJQUVNLE9BQU87UUFDWixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsK0JBQStCLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsNEJBQTRCLEVBQUUsQ0FBQztRQUVwQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUVsRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDZixPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRU8sc0JBQXNCO1FBQzVCLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBRzFELElBQUksQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQztZQUMxQixPQUFPLEVBQUUsS0FBSztTQUNmLENBQUMsQ0FBQztRQUdILEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRW5ELElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDckQsT0FBTyxFQUFFLElBQUk7WUFDYixTQUFTLEVBQUUsSUFBSTtTQUNoQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFakQsS0FBSyxNQUFNLGFBQWEsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxFQUFFO1lBQzNELElBQUksQ0FBQyxhQUFhLENBQUMsaUJBQWlCLEVBQUU7Z0JBQ3BDLElBQ0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO29CQUN0QyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQ2pDO29CQUNBLElBQUksQ0FBQyxjQUFjLEdBQUcsYUFBYSxDQUFDO2lCQUNyQzthQUNGO1NBQ0Y7UUFFRCxJQUFJLElBQUksQ0FBQyxjQUFjLEtBQUssU0FBUyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxTQUFTLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUM5QztJQUNILENBQUM7SUFFTyxvQkFBb0I7UUFDMUIsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBK0IsQ0FBQztRQUUzRCxNQUFNLGdCQUFnQixHQUEyQixzQkFBYyxDQUM3RCxJQUFJLENBQUMsY0FBYyxFQUNuQixFQUFFLENBQUMsbUJBQW1CLENBQ3ZCLENBQUM7UUFFRixLQUFLLE1BQU0sZUFBZSxJQUFJLGdCQUFnQixFQUFFO1lBQzlDLElBQUksZUFBZSxFQUFFO2dCQUVuQixJQUNFLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDO29CQUMxRCxJQUFJLENBQUMsb0NBQW9DLENBQUMsZUFBZSxDQUFDLEVBQzFEO29CQUNBLE1BQU0sQ0FBQyxLQUFLLENBQ1YsOEJBQThCLG9CQUFZLENBQ3hDLGVBQWUsRUFDZixJQUFJLENBQUMsY0FBYyxDQUNwQixFQUFFLENBQ0osQ0FBQztvQkFLRixJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO29CQUVoRCxJQUFJLGVBQWUsQ0FBQyxZQUFZLEVBQUU7d0JBQ2hDLElBQUksZUFBZSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUU7NEJBR3JDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQ3ZELGVBQWUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUNsQyxDQUFDOzRCQUNGLElBQUksY0FBYyxFQUFFO2dDQUNsQixJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDOzZCQUM1Qzt5QkFDRjt3QkFHRCxJQUFJLGVBQWUsQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFOzRCQUM5QyxJQUNFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxFQUNoRTtnQ0FHQSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUN2RCxlQUFlLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQ2hELENBQUM7Z0NBQ0YsSUFBSSxjQUFjLEVBQUU7b0NBQ2xCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7aUNBQzVDOzZCQUNGO2lDQUFNLElBQ0wsRUFBRSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxFQUM3RDtnQ0FHQSxLQUFLLE1BQU0sa0JBQWtCLElBQUksZUFBZSxDQUFDLFlBQVk7cUNBQzFELGFBQWEsQ0FBQyxRQUFRLEVBQUU7b0NBQ3pCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQ3ZELGtCQUFrQixDQUFDLElBQUksQ0FDeEIsQ0FBQztvQ0FDRixJQUFJLGNBQWMsRUFBRTt3Q0FDbEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztxQ0FDNUM7aUNBQ0Y7NkJBQ0Y7eUJBQ0Y7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGO0lBQ0gsQ0FBQztJQUVPLHdCQUF3QjtRQUM5QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUErQixDQUFDO1FBRTNELE1BQU0sZUFBZSxHQUF3QixzQkFBYyxDQUN6RCxJQUFJLENBQUMsY0FBYyxFQUNuQixDQUFDLElBQUksRUFBNkIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUNsRSxDQUFDO1FBRUYsS0FBSyxNQUFNLGNBQWMsSUFBSSxlQUFlLEVBQUU7WUFJNUMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDcEUsSUFDRSxtQkFBbUI7Z0JBQ25CLENBQUMsb0JBQW9CLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQztvQkFDN0QsSUFBSSxDQUFDLHFDQUFxQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEVBQzdEO2dCQUNBLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7YUFDaEQ7U0FDRjtJQUNILENBQUM7SUFFTywrQkFBK0I7UUFDckMsTUFBTSx1Q0FBdUMsR0FBRyxDQUFDLElBQW1CLEVBQUUsRUFBRTtZQUN0RSxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3pCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzNELElBQUksU0FBUyxFQUFFO29CQUNiLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQ3ZDO2FBQ0Y7aUJBQU0sSUFDTCxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDO2dCQUMzQixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFDcEQ7Z0JBQ0EsdUNBQXVDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNuRCx1Q0FBdUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDckQ7UUFDSCxDQUFDLENBQUM7UUFFRixNQUFNLHlCQUF5QixHQUFHLENBQUMsSUFBYSxFQUFFLEVBQUU7WUFDbEQsSUFDRSxFQUFFLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDO2dCQUM5QixvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGNBQStCLENBQUMsRUFDaEU7Z0JBQ0EsdUNBQXVDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQzFEO2lCQUFNO2dCQUNMLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLHlCQUF5QixDQUFDLENBQUM7YUFDbEQ7UUFDSCxDQUFDLENBQUM7UUFFRixFQUFFLENBQUMsWUFBWSxDQUNiLElBQUksQ0FBQyxjQUErQixFQUNwQyx5QkFBeUIsQ0FDMUIsQ0FBQztJQUNKLENBQUM7SUFFTyxvQ0FBb0MsQ0FDMUMsWUFBa0M7UUFFbEMsSUFBSSxFQUFFLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsRUFBRTtZQUNwRCxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQztZQUNyRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUMvQyxtQkFBUyxDQUFDLFVBQVUsRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FDaEUsQ0FBQztTQUNIO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8scUNBQXFDLENBQzNDLHFCQUF3QztRQUV4QyxJQUFJLEVBQUUsQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUUsSUFBSSxDQUFDLEVBQUU7WUFDakQsTUFBTSxVQUFVLEdBQUkscUJBQXFCO2lCQUN0QyxTQUFTLENBQUMsQ0FBQyxDQUFzQixDQUFDLElBQUksQ0FBQztZQUMxQyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUNsRDtRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVPLHNCQUFzQixDQUFDLGlCQUFnQztRQUM3RCxPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRU8sa0JBQWtCLENBQUMsYUFBd0I7UUFDakQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXJFLE1BQU0sK0JBQStCLEdBQ25DLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxhQUFhLENBQUM7WUFDdEQsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXpELE9BQU8sa0JBQWtCLElBQUksK0JBQStCLENBQUM7SUFDL0QsQ0FBQztJQUVPLGtDQUFrQyxDQUN4QyxhQUF3QjtRQUV4QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUErQixDQUFDO1FBRTNELE1BQU0sMkJBQTJCLEdBQUcsQ0FBQyxJQUFhLEVBQVcsRUFBRTtZQUU3RCxJQUFJLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFFbEMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3JFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7Z0JBQ3JDLElBQUksY0FBYyxLQUFLLGFBQWEsSUFBSSxXQUFXLEVBQUU7b0JBQ25ELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FDMUQsV0FBVyxDQUNaLENBQUM7b0JBQ0YsSUFDRSxDQUFDLGlCQUFpQjt3QkFDaEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO3dCQUNoRCxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUMzQzt3QkFDQSxPQUFPLElBQUksQ0FBQztxQkFDYjtpQkFDRjthQUNGO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDLENBQUM7UUFFRixNQUFNLGVBQWUsR0FBRyxxQkFBYSxDQUNuQyxJQUFJLENBQUMsY0FBYyxFQUNuQiwyQkFBMkIsQ0FDNUIsQ0FBQztRQUVGLE9BQU8sZUFBZSxLQUFLLFNBQVMsQ0FBQztJQUN2QyxDQUFDO0lBRU8sa0NBQWtDLENBQ3hDLGFBQXdCO1FBRXhCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQStCLENBQUM7UUFFM0QsTUFBTSxrQ0FBa0MsR0FBRyxDQUFDLElBQWEsRUFBVyxFQUFFO1lBRXBFLElBQ0UsRUFBRSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQztnQkFDM0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQ3JEO2dCQUVBLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNyRSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO2dCQUMvQixJQUFJLGNBQWMsS0FBSyxhQUFhLElBQUksV0FBVyxFQUFFO29CQUNuRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQzFELFdBQVcsQ0FDWixDQUFDO29CQUNGLElBQ0UsQ0FBQyxpQkFBaUI7d0JBQ2hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQzt3QkFDaEQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFDM0M7d0JBQ0EsT0FBTyxJQUFJLENBQUM7cUJBQ2I7aUJBQ0Y7YUFDRjtZQUVELE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQyxDQUFDO1FBRUYsTUFBTSxxQkFBcUIsR0FBRyxxQkFBYSxDQUN6QyxJQUFJLENBQUMsY0FBYyxFQUNuQixrQ0FBa0MsQ0FDbkMsQ0FBQztRQUVGLE9BQU8scUJBQXFCLEtBQUssU0FBUyxDQUFDO0lBQzdDLENBQUM7SUFFTyw0QkFBNEI7UUFDbEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBK0IsQ0FBQztRQUUzRCxNQUFNLG9CQUFvQixHQUFHO1lBQzNCLElBQUksQ0FBQywyQkFBMkI7WUFDaEMsSUFBSSxDQUFDLHFCQUFxQjtZQUMxQixJQUFJLENBQUMsMEJBQTBCO1NBQ2hDLENBQUM7UUFFRixJQUFJLDBCQUEwQixHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLElBQUksOEJBQThCLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFJeEMsT0FDRSwwQkFBMEIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSTtZQUN4RCw4QkFBOEIsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxFQUNoRTtZQUVBLDBCQUEwQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUM7WUFDekQsOEJBQThCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQztZQUdqRSxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQ3BDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDcEIsQ0FBQyxDQUFDLENBQUM7U0FDSjtRQUdELE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUMxRSxJQUFJLENBQUMsNkJBQTZCLENBQUMsTUFBTSxDQUFDLENBQzNDLENBQUM7UUFFRixNQUFNLENBQUMsS0FBSyxDQUNWLGtDQUFrQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FDbEUsQ0FBQztRQUVGLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUNwQyxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUNyQyxDQUFDO0lBQ0osQ0FBQztJQUVPLDJCQUEyQjtRQUlqQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUErQixDQUFDO1FBRTNELE1BQU0sZUFBZSxHQUFHLENBQUMsSUFBYSxFQUFRLEVBQUU7WUFFOUMsSUFBSSxFQUFFLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBRXZDLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDakQsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUMxQyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUN2RCx3QkFBd0IsQ0FDekIsQ0FBQztnQkFDRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUN4RCx1QkFBdUIsQ0FDeEIsQ0FBQztnQkFFRixJQUNFLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztvQkFDM0QsSUFBSSxDQUFDLHNCQUFzQixDQUFDLHdCQUF3QixDQUFDLEVBQ3JEO29CQUVBLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBR3JDLElBQUksY0FBYyxFQUFFO3dCQUNsQixJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO3FCQUM1QztpQkFDRjthQUNGO2lCQUFNO2dCQUNMLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO2FBQ3hDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTyxxQkFBcUI7UUFJM0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBK0IsQ0FBQztRQUUzRCxNQUFNLGVBQWUsR0FBRyxDQUFDLElBQWEsRUFBUSxFQUFFO1lBRTlDLElBQUksRUFBRSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFHNUIsTUFBTSxDQUFDLEtBQUssQ0FDVix1QkFBdUIsRUFDdkIsb0JBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGNBQStCLENBQUMsQ0FDekQsQ0FBQztnQkFFRixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7Z0JBQzdDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FDekQsb0JBQW9CLENBQ3JCLENBQUM7Z0JBQ0YsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFakUsSUFDRSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO29CQUMvRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsRUFDakQ7b0JBRUEsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFHckMsSUFBSSxnQkFBZ0IsRUFBRTt3QkFDcEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3FCQUM5QztpQkFDRjthQUNGO2lCQUFNO2dCQUNMLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO2FBQ3hDO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTywwQkFBMEI7UUFJaEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBK0IsQ0FBQztRQUUzRCxNQUFNLGlCQUFpQixHQUFHLENBQUMsSUFBYSxFQUFRLEVBQUU7WUFFaEQsSUFBSSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBRzdCLE1BQU0sQ0FBQyxLQUFLLENBQ1Ysd0JBQXdCLEVBQ3hCLG9CQUFZLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxjQUErQixDQUFDLENBQ3pELENBQUM7Z0JBRUYsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO2dCQUM3QyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQ3pELG9CQUFvQixDQUNyQixDQUFDO2dCQUNGLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFeEUsSUFDRSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO29CQUMvRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsb0JBQW9CLENBQUMsRUFDakQ7b0JBRUEsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFHckMsSUFBSSxnQkFBZ0IsRUFBRTt3QkFDcEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3FCQUM5QztpQkFDRjthQUNGO2lCQUFNO2dCQUNMLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGlCQUFpQixDQUFDLENBQUM7YUFDMUM7UUFDSCxDQUFDLENBQUM7UUFFRixFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRU8sNkJBQTZCLENBQ25DLGFBQXdCLEVBQ3hCLGlCQUEyQjtRQUUzQixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUErQixDQUFDO1FBRTNELElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO1lBQ25DLGlCQUFpQixHQUFHLEtBQUssQ0FBQztTQUMzQjtRQUVELE1BQU0sbUJBQW1CLEdBQWMsRUFBRSxDQUFDO1FBRTFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxJQUFhLEVBQUUsRUFBRTtZQUMvQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNELElBQUksU0FBUyxJQUFJLFNBQVMsS0FBSyxhQUFhLEVBQUU7Z0JBRTVDLElBQUksTUFBTSxHQUF3QixJQUFJLENBQUM7Z0JBQ3ZDLElBQUksaUJBQTRCLEVBQUU7b0JBQ2hDLE1BQU0sR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQ3hDO2dCQUdELElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtvQkFDeEIsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2lCQUNoQzthQUNGO1lBRUQsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztRQUNoRCxDQUFDLENBQUM7UUFFRixFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztRQUU3RCxPQUFPLG1CQUFtQixDQUFDO0lBQzdCLENBQUM7SUFFTyxjQUFjLENBQUMsV0FBc0I7UUFDM0MsTUFBTSxDQUFDLEtBQUssQ0FDVixpQkFBaUIsRUFDakIsQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQzthQUN4QixHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDckMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNkLENBQUM7UUFFRixNQUFNLENBQUMsS0FBSyxDQUNWLHFCQUFxQixFQUNyQixXQUFXO2FBQ1IsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsb0JBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGNBQStCLENBQUMsQ0FBQzthQUNyRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2QsQ0FBQztJQUNKLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxJQUFhO1FBQ3RDLE9BQU8sNEJBQW9CLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRU8sdUJBQXVCO1FBQzdCLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFFOUIsTUFBTSxtQkFBbUIsR0FBbUIsQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQzthQUN4RSxHQUFHLENBQUMsQ0FBQyxJQUFhLEVBQUUsRUFBRTtZQUNyQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsb0JBQW9CLENBQUMsRUFBRTtZQUM3QixPQUFPLG9CQUFvQixLQUFLLFNBQVMsQ0FBQztRQUM1QyxDQUFDLENBQW1CLENBQUM7UUFFdkIsTUFBTSxvQkFBb0IsR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDckUsSUFBSSxrQkFBVSxDQUFDLEtBQUssQ0FBQyxLQUFLLGtCQUFVLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQzNDLElBQUksa0JBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxrQkFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFO29CQUN6QyxPQUFPLENBQUMsQ0FBQyxDQUFDO2lCQUNYO3FCQUFNO29CQUNMLE9BQU8sQ0FBQyxDQUFDLENBQUM7aUJBQ1g7YUFDRjtpQkFBTTtnQkFDTCxJQUFJLG9CQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsb0JBQVksQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDN0MsT0FBTyxDQUFDLENBQUMsQ0FBQztpQkFDWDtxQkFBTTtvQkFDTCxPQUFPLENBQUMsQ0FBQyxDQUFDO2lCQUNYO2FBQ0Y7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUUxQyxLQUNFLElBQUksU0FBUyxHQUFHLENBQUMsRUFDakIsU0FBUyxHQUFHLG9CQUFvQixDQUFDLE1BQU0sRUFDdkMsU0FBUyxFQUFFLEVBQ1g7WUFDQSxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxjQUErQixDQUFDO1lBQzNELE1BQU0sV0FBVyxHQUFHLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRXBELElBQUksU0FBUyxHQUFHLENBQUMsRUFBRTtnQkFDakIsTUFBTSxRQUFRLEdBQUcsb0JBQW9CLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNyRCxJQUFJLGtCQUFVLENBQUMsV0FBVyxDQUFDLEdBQUcsb0JBQVksQ0FBQyxRQUFRLENBQUMsRUFBRTtvQkFFcEQsSUFDRSxvQkFBWSxDQUFDLFdBQVcsQ0FBQyxJQUFJLG9CQUFZLENBQUMsUUFBUSxDQUFDO3dCQUNuRCxrQkFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLGtCQUFVLENBQUMsUUFBUSxDQUFDLEVBQy9DO3dCQUdBLE1BQU0sQ0FBQyxLQUFLLENBQ1Ysc0RBQXNELG9CQUFZLENBQ2hFLFdBQVcsRUFDWCxJQUFJLENBQUMsY0FBYyxDQUNwQixFQUFFLENBQ0osQ0FBQzt3QkFFRixTQUFTO3FCQUNWO3lCQUFNO3dCQUVMLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0VBQXdFLENBQ3pFLENBQUM7cUJBQ0g7aUJBQ0Y7YUFDRjtZQUVELE1BQU0sYUFBYSxHQUFHLG9CQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDaEQsSUFBSSxXQUFXLEdBQUcsa0JBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUcxQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLFdBQVcsR0FBRyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hELFdBQVcsSUFBSSxDQUFDLENBQUM7YUFDbEI7aUJBQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsQ0FBQyxDQUFDLEtBQUssTUFBTSxFQUFFO2dCQUNqRSxXQUFXLElBQUksQ0FBQyxDQUFDO2FBQ2xCO1lBRUQsT0FBTztnQkFDTCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUM7b0JBQy9CLEVBQUU7b0JBQ0YsT0FBTyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUM5QjtRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxPQUFPO1FBQ2IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLE1BQU0sR0FBRztJQUNiLElBQUksRUFBRSxRQUFRO0lBQ2QsVUFBVSxFQUFFO1FBQ1YsSUFBSSxFQUFFO1lBQ0osSUFBSSxFQUFFLFFBQVE7U0FDZjtLQUNGO0NBQ0YsQ0FBQztBQUVGLGdCQUFtRCxVQUFrQjtJQUNuRSxNQUFNLE9BQU8sR0FBRyx5QkFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWpDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxZQUFZLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzdELE9BQU8saUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDckMsQ0FBQztBQUVELGtCQUFlLE1BQU0sQ0FBQyJ9