UNPKG

patchwork-mapconverter

Version:

Executable wrapper for https://github.com/ChiefOfGxBxL/WC3MapTranslator

692 lines 69.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TriggersTranslator = void 0; const TriggerDataRegistry_1 = require("../enhancements/TriggerDataRegistry"); const TriggerContent_1 = require("./data/content/TriggerContent"); const ContentTypeEnumConverter_1 = require("./util/ContentTypeEnumConverter"); const StatementTypeEnumConverter_1 = require("./util/StatementTypeEnumConverter"); const StatementType_1 = require("./data/statement/StatementType"); const ParameterTypeEnumConverter_1 = require("./util/ParameterTypeEnumConverter"); const ParameterType_1 = require("./data/parameter/ParameterType"); const HexBuffer_1 = require("../wc3maptranslator/HexBuffer"); const W3Buffer_1 = require("../wc3maptranslator/W3Buffer"); function countContentTypes(roots) { const triggerStack = [...roots]; const result = new Map(); result.set(TriggerContent_1.ContentType.HEADER, 0); result.set(TriggerContent_1.ContentType.LIBRARY, 0); result.set(TriggerContent_1.ContentType.CATEGORY, 0); result.set(TriggerContent_1.ContentType.TRIGGER, 0); result.set(TriggerContent_1.ContentType.COMMENT, 0); result.set(TriggerContent_1.ContentType.CUSTOM_SCRIPT, 0); result.set(TriggerContent_1.ContentType.VARIABLE, 0); while (triggerStack.length > 0) { const currentTrigger = triggerStack.pop(); if (currentTrigger == null) continue; const count = result.get(currentTrigger.contentType); if (count == null) { result.set(currentTrigger.contentType, 1); } else { result.set(currentTrigger.contentType, count + 1); } switch (currentTrigger.contentType) { case TriggerContent_1.ContentType.HEADER: case TriggerContent_1.ContentType.LIBRARY: case TriggerContent_1.ContentType.CATEGORY: triggerStack.push(...currentTrigger.children); } } return result; } function getAllOfContentType(roots, elementReference, type) { const triggerStack = [...roots]; const parentStack = []; const result = new Map(); while (triggerStack.length > 0) { const currentTrigger = triggerStack.pop(); if (currentTrigger == null) continue; let parent = parentStack.pop(); let parentId; while (parent != null) { if (parent.children.findIndex((value) => value === currentTrigger) > -1) break; // this is the parent parent = parentStack.pop(); // go down the stack } if (parent == null) { parentId = -1; } else { parentStack.push(parent); parentId = elementReference.get(parent); if (parentId == null) { throw new Error('Parent ' + parent.name + ' has no ID??'); // something wrong with tree traversal? :thinking: } } if (currentTrigger.children != null) { parentStack.push(currentTrigger); } if (currentTrigger.contentType === type) { result.set(currentTrigger, parentId); } switch (currentTrigger.contentType) { case TriggerContent_1.ContentType.HEADER: case TriggerContent_1.ContentType.LIBRARY: case TriggerContent_1.ContentType.CATEGORY: triggerStack.push(...currentTrigger.children); } } return result; } class TriggersTranslator { constructor() { } static getInstance() { if (this.instance == null) { this.instance = new this(); } return this.instance; } static jsonToWar(triggers) { return this.getInstance().jsonToWar(triggers); } static warToJson(buffer) { return this.getInstance().warToJson(buffer); } jsonToWar(json) { const outBufferToWar = new HexBuffer_1.HexBuffer(); outBufferToWar.addChars('WTG!'); // File header outBufferToWar.addByte(0x04); outBufferToWar.addByte(0x00); outBufferToWar.addByte(0x00); outBufferToWar.addByte(0x80); // Format version outBufferToWar.addInt(7); // TFT Game Version const contentTypeCounts = countContentTypes(json.roots); let totalElements = 0; for (const count of contentTypeCounts.values()) { totalElements = totalElements + count; } const writeContentCount = function (contentType) { outBufferToWar.addInt(contentTypeCounts.get(contentType)); outBufferToWar.addInt(0); // deleted count }; writeContentCount(TriggerContent_1.ContentType.HEADER); writeContentCount(TriggerContent_1.ContentType.LIBRARY); writeContentCount(TriggerContent_1.ContentType.CATEGORY); writeContentCount(TriggerContent_1.ContentType.TRIGGER); writeContentCount(TriggerContent_1.ContentType.COMMENT); writeContentCount(TriggerContent_1.ContentType.CUSTOM_SCRIPT); writeContentCount(TriggerContent_1.ContentType.VARIABLE); outBufferToWar.addInt(0); // unknown outBufferToWar.addInt(0); // unknown outBufferToWar.addInt(2); // 1 for RoC?, 2 for TFT? const elementReference = new Map(); let headerCount = 0; let libraryCount = 0; let categoryCount = 0; let triggerCount = 0; let commentCount = 0; let customScriptCount = 0; let variableCount = 0; const triggerStack = [...json.roots]; while (triggerStack.length > 0) { const currentTrigger = triggerStack.pop(); if (currentTrigger == null) continue; let elementId; switch (currentTrigger.contentType) { case TriggerContent_1.ContentType.HEADER: elementId = 0x00000000 + headerCount++; triggerStack.push(...currentTrigger.children); break; case TriggerContent_1.ContentType.LIBRARY: elementId = 0x01000000 + libraryCount++; triggerStack.push(...currentTrigger.children); break; case TriggerContent_1.ContentType.CATEGORY: elementId = 0x02000000 + categoryCount++; triggerStack.push(...currentTrigger.children); break; case TriggerContent_1.ContentType.TRIGGER: case TriggerContent_1.ContentType.TRIGGER_SCRIPTED: elementId = 0x03000000 + triggerCount++; break; case TriggerContent_1.ContentType.COMMENT: elementId = 0x04000000 + commentCount++; break; case TriggerContent_1.ContentType.CUSTOM_SCRIPT: elementId = 0x05000000 + customScriptCount++; break; case TriggerContent_1.ContentType.VARIABLE: elementId = 0x06000000 + variableCount++; break; default: continue; } elementReference.set(currentTrigger, elementId); } const variables = getAllOfContentType(json.roots, elementReference, TriggerContent_1.ContentType.VARIABLE); outBufferToWar.addInt(variables.size); for (const [variable, parentId] of variables.entries()) { outBufferToWar.addString(variable.name); outBufferToWar.addString(variable.type); outBufferToWar.addInt(1); // unknown, always 1? outBufferToWar.addInt(variable.isArray ? 1 : 0); outBufferToWar.addInt(variable.arrayLength); outBufferToWar.addInt(variable.isInitialized ? 1 : 0); outBufferToWar.addString(variable.initialValue); const elementId = elementReference.get(variable); if (elementId == null) { throw new Error(`Variable ${variable.name} missing ID`); } outBufferToWar.addInt(elementId); outBufferToWar.addInt(parentId); // parent } triggerStack.push(...json.roots); const parentStack = []; outBufferToWar.addInt(totalElements); while (triggerStack.length > 0) { const currentTrigger = triggerStack.pop(); if (currentTrigger == null) continue; const elementId = elementReference.get(currentTrigger); if (elementId == null) { throw new Error(`TriggerContent ${currentTrigger.name} missing ID`); } outBufferToWar.addInt(ContentTypeEnumConverter_1.ContentTypeEnumConverter.toIdentifier(currentTrigger.contentType)); let parent = parentStack.pop(); let parentId; while (parent != null) { if (parent.children.findIndex((value) => value === currentTrigger) > -1) break; // this is the parent parent = parentStack.pop(); // go down the stack } if (parent == null) { parentId = -1; } else { parentStack.push(parent); parentId = elementReference.get(parent); if (parentId == null) { throw new Error('Parent ' + parent.name + ' has no ID??'); // something wrong with tree traversal? :thinking: } } if (currentTrigger.children != null) { parentStack.push(currentTrigger); } let ecaCount; switch (currentTrigger.contentType) { case TriggerContent_1.ContentType.HEADER: case TriggerContent_1.ContentType.LIBRARY: case TriggerContent_1.ContentType.CATEGORY: outBufferToWar.addInt(elementId); outBufferToWar.addString(currentTrigger.name); outBufferToWar.addInt(0); // not a comment outBufferToWar.addInt(currentTrigger.isExpanded ? 1 : 0); // not expanded outBufferToWar.addInt(parentId); triggerStack.push(...currentTrigger.children); break; case TriggerContent_1.ContentType.TRIGGER: case TriggerContent_1.ContentType.TRIGGER_SCRIPTED: case TriggerContent_1.ContentType.COMMENT: case TriggerContent_1.ContentType.CUSTOM_SCRIPT: outBufferToWar.addString(currentTrigger.name); if (currentTrigger.contentType === TriggerContent_1.ContentType.COMMENT) { outBufferToWar.addString(currentTrigger.comment); } else { outBufferToWar.addString(currentTrigger.description); } outBufferToWar.addInt(currentTrigger.contentType === TriggerContent_1.ContentType.COMMENT ? 1 : 0); outBufferToWar.addInt(elementId); if (currentTrigger.contentType === TriggerContent_1.ContentType.CUSTOM_SCRIPT) { outBufferToWar.addInt(currentTrigger.isEnabled ? 1 : 0); outBufferToWar.addInt(1); // is custom script outBufferToWar.addInt(0); // initially off outBufferToWar.addInt(0); // doesn't run on map init outBufferToWar.addInt(parentId); outBufferToWar.addInt(0); // ECA count 0 } else if (currentTrigger.contentType === TriggerContent_1.ContentType.COMMENT) { outBufferToWar.addInt(0); // not enabled outBufferToWar.addInt(0); // is custom script outBufferToWar.addInt(0); // initially off outBufferToWar.addInt(0); // doesn't run on map init outBufferToWar.addInt(parentId); outBufferToWar.addInt(0); // ECA count 0 } else if (currentTrigger.contentType === TriggerContent_1.ContentType.TRIGGER) { ecaCount = currentTrigger.events.length + currentTrigger.conditions.length + currentTrigger.actions.length; outBufferToWar.addInt(currentTrigger.isEnabled ? 1 : 0); outBufferToWar.addInt(0); // is custom script outBufferToWar.addInt(currentTrigger.initiallyOff ? 1 : 0); outBufferToWar.addInt(currentTrigger.runOnMapInit ? 1 : 0); outBufferToWar.addInt(parentId); outBufferToWar.addInt(ecaCount); const writeStatements = (parent, ECAs, group) => { for (const eca of ECAs) { outBufferToWar.addInt(StatementTypeEnumConverter_1.StatementTypeEnumConverter.toIdentifier(eca.type)); if (group !== -1) { outBufferToWar.addInt(group); } outBufferToWar.addString(eca.name); outBufferToWar.addInt(eca.isEnabled ? 1 : 0); const writeParams = (parent, parameters) => { for (const param of parameters) { outBufferToWar.addInt(ParameterTypeEnumConverter_1.ParameterTypeEnumConverter.toIdentifier(param.type)); outBufferToWar.addString(param.value); if (param.statement != null) { outBufferToWar.addInt(1); // has sub params outBufferToWar.addInt(StatementTypeEnumConverter_1.StatementTypeEnumConverter.toIdentifier(param.statement.type)); outBufferToWar.addString(param.statement.name); outBufferToWar.addInt(1); // begin function writeParams(param, param.statement.parameters); outBufferToWar.addInt(0); // unknown, end function maybe? } else { outBufferToWar.addInt(0); // no sub params } if (param.arrayIndex != null) { outBufferToWar.addInt(1); // is array writeParams(param, [param.arrayIndex]); } else { outBufferToWar.addInt(0); // is not array } } }; writeParams(eca, eca.parameters); if (eca.statements != null) { const nestingStatement = eca; let ecaCount = 0; for (const nestedStatements of Object.values(nestingStatement.statements)) { if (nestedStatements != null) { ecaCount += nestedStatements.length; } } outBufferToWar.addInt(ecaCount); for (const [group, nestedStatements] of Object.entries(nestingStatement.statements)) { if (nestedStatements != null) { writeStatements(eca, nestedStatements, Number(group)); } } } else { outBufferToWar.addInt(0); // ecaCount } } }; writeStatements(currentTrigger, currentTrigger.actions, -1); writeStatements(currentTrigger, currentTrigger.events, -1); writeStatements(currentTrigger, currentTrigger.conditions, -1); } else if (currentTrigger.contentType === TriggerContent_1.ContentType.TRIGGER_SCRIPTED) { outBufferToWar.addInt(currentTrigger.isEnabled ? 1 : 0); outBufferToWar.addInt(1); // is custom script outBufferToWar.addInt(0); // initially off outBufferToWar.addInt(currentTrigger.runOnMapInit ? 1 : 0); outBufferToWar.addInt(parentId); outBufferToWar.addInt(0); } break; case TriggerContent_1.ContentType.VARIABLE: outBufferToWar.addInt(elementId); outBufferToWar.addString(currentTrigger.name); outBufferToWar.addInt(parentId); break; } } return { buffer: outBufferToWar.getBuffer(), errors: [] }; } warToJson(buffer) { const outBufferToJSON = new W3Buffer_1.W3Buffer(buffer); try { const fileId = outBufferToJSON.readChars(4); // WTG! const formatVersion = outBufferToJSON.readInt(); // 04 00 00 80 const gameVersion = outBufferToJSON.readInt(); // 4 = Roc, 7 = TFT const headerCount = outBufferToJSON.readInt(); // always 1..? const deletedHeaderCount = outBufferToJSON.readInt(); // Includes both existing and deleted headers. (Map script headers?) for (let i = 0; i < deletedHeaderCount; i++) { const headerId = outBufferToJSON.readInt(); // always 0..? } const libraryCount = outBufferToJSON.readInt(); const deletedLibraryCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedLibraryCount; i++) { const libraryId = outBufferToJSON.readInt(); } const triggerCategoryCount = outBufferToJSON.readInt(); const deletedCategoryCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedCategoryCount; i++) { // trigger categories const categoryId = outBufferToJSON.readInt(); } const triggerCount = outBufferToJSON.readInt(); const deletedTriggerCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedTriggerCount; i++) { const triggerId = outBufferToJSON.readInt(); } const triggerCommentCount = outBufferToJSON.readInt(); const deletedTriggerCommentCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedTriggerCommentCount; i++) { const triggerCommentId = outBufferToJSON.readInt(); } const customScriptCount = outBufferToJSON.readInt(); const deletedCustomScriptCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedCustomScriptCount; i++) { const customScriptId = outBufferToJSON.readInt(); } const variableCount = outBufferToJSON.readInt(); const deletedVariableCount = outBufferToJSON.readInt(); for (let i = 0; i < deletedVariableCount; i++) { const variableId = outBufferToJSON.readInt(); } outBufferToJSON.readInt(); // unknown outBufferToJSON.readInt(); // unknown const triggerDefinitionVersion = outBufferToJSON.readInt(); // 1 for RoC?, 2 for TFT? const elementRelations = new Map(); const containers = {}; const content = {}; const customScripts = []; const allGlobalVariables = {}; const existingVariablesCount = outBufferToJSON.readInt(); for (let i = 0; i < existingVariablesCount; i++) { const globalVariable = { name: '', contentType: TriggerContent_1.ContentType.VARIABLE, type: '', isArray: false, arrayLength: 0, isInitialized: false, initialValue: '' }; globalVariable.name = outBufferToJSON.readString(); globalVariable.type = outBufferToJSON.readString(); outBufferToJSON.readInt(); // unknown, always 1? globalVariable.isArray = outBufferToJSON.readInt() === 1; if (gameVersion === 7) { globalVariable.arrayLength = outBufferToJSON.readInt(); } globalVariable.isInitialized = outBufferToJSON.readInt() === 1; globalVariable.initialValue = outBufferToJSON.readString(); const variableId = outBufferToJSON.readInt(); // last byte 06? allGlobalVariables[variableId] = globalVariable; content[variableId] = globalVariable; elementRelations.set(variableId, outBufferToJSON.readInt()); } const totalElements = outBufferToJSON.readInt(); for (let i = 0; i < totalElements; i++) { const type = ContentTypeEnumConverter_1.ContentTypeEnumConverter.toEnum(outBufferToJSON.readInt()); let elementId; let name; let description; let isComment = false; let isExpanded = false; let isEnabled = false; let isCustomScript = false; let initiallyOff = false; let runOnMapInit = false; let ecaCount = 0; let parentElementId; let trigger; let container; switch (type) { case TriggerContent_1.ContentType.HEADER: case TriggerContent_1.ContentType.LIBRARY: case TriggerContent_1.ContentType.CATEGORY: elementId = outBufferToJSON.readInt(); name = outBufferToJSON.readString(); if (gameVersion === 7) { isComment = outBufferToJSON.readInt() === 1; } isExpanded = outBufferToJSON.readInt() === 1; parentElementId = outBufferToJSON.readInt(); elementRelations.set(elementId, parentElementId); container = { name, isExpanded, contentType: type, children: [] }; containers[elementId] = container; if (type === TriggerContent_1.ContentType.HEADER) { customScripts.push(container); } break; case TriggerContent_1.ContentType.TRIGGER: case TriggerContent_1.ContentType.COMMENT: case TriggerContent_1.ContentType.CUSTOM_SCRIPT: name = outBufferToJSON.readString(); description = outBufferToJSON.readString(); if (gameVersion === 7) { isComment = outBufferToJSON.readInt() === 1; } elementId = outBufferToJSON.readInt(); isEnabled = outBufferToJSON.readInt() === 1; isCustomScript = outBufferToJSON.readInt() === 1; initiallyOff = outBufferToJSON.readInt() === 1; runOnMapInit = outBufferToJSON.readInt() === 1; parentElementId = outBufferToJSON.readInt(); elementRelations.set(elementId, parentElementId); ecaCount = outBufferToJSON.readInt(); if (type === TriggerContent_1.ContentType.TRIGGER) { if (isCustomScript) { const script = { name, contentType: TriggerContent_1.ContentType.TRIGGER_SCRIPTED, description, isEnabled, runOnMapInit, script: '' }; content[elementId] = script; customScripts.push(script); } else { trigger = { name, contentType: TriggerContent_1.ContentType.TRIGGER, description, isEnabled, initiallyOff, runOnMapInit, events: [], conditions: [], actions: [] }; const readStatements = (content, functionCount, isChild) => { for (let j = 0; j < functionCount; j++) { const functionType = StatementTypeEnumConverter_1.StatementTypeEnumConverter.toEnum(outBufferToJSON.readInt()); let group = -1; if (isChild) { group = outBufferToJSON.readInt(); } const name = outBufferToJSON.readString(); const isEnabled = outBufferToJSON.readInt() === 1; const parameterCount = TriggerDataRegistry_1.TriggerDataRegistry.getParameterCount(functionType, name); const readParams = (parent, paramCount, arrayIndex) => { for (let k = 0; k < paramCount; k++) { const paramType = ParameterTypeEnumConverter_1.ParameterTypeEnumConverter.toEnum(outBufferToJSON.readInt()); const value = outBufferToJSON.readString(); const hasSubParameters = !(outBufferToJSON.readInt() === 0); const parameter = { type: paramType, value }; if (hasSubParameters) { parameter.statement = { type: StatementTypeEnumConverter_1.StatementTypeEnumConverter.toEnum(outBufferToJSON.readInt()), isEnabled: true, name: outBufferToJSON.readString(), parameters: [] }; const beginParams = outBufferToJSON.readInt() !== 0; const subParamCount = TriggerDataRegistry_1.TriggerDataRegistry.getParameterCount(parameter.statement.type, parameter.statement.name); if (subParamCount == null) { throw new Error('Missing parameter count for function ' + parameter.statement.name); } readParams(parameter.statement, subParamCount, false); } if (gameVersion === 4 && paramType === ParameterType_1.ParameterType.FUNCTION) { outBufferToJSON.readInt(); } else if (gameVersion === 7 && hasSubParameters) { outBufferToJSON.readInt(); } let isArray; if (gameVersion !== 4 || paramType !== ParameterType_1.ParameterType.FUNCTION) { isArray = outBufferToJSON.readInt() === 1; } else { isArray = false; } if (isArray) { readParams(parameter, 1, true); } if (arrayIndex) { parent.arrayIndex = parameter; } else if (parent.statement != null) { parent.statement.parameters.push(parameter); } else { parent.parameters.push(parameter); } } }; const statement = { name, type: functionType, isEnabled, parameters: [] }; if (parameterCount == null) { throw new Error('Missing parameter count for function ' + name); } readParams(statement, parameterCount, false); if (gameVersion === 7) { const nestedEcaCount = outBufferToJSON.readInt(); readStatements(statement, nestedEcaCount, true); } if (content.events != null) { // is GUITrigger switch (functionType) { case StatementType_1.StatementType.EVENT: content.events.push(statement); break; case StatementType_1.StatementType.CONDITION: content.conditions.push(statement); break; case StatementType_1.StatementType.ACTION: content.actions.push(statement); break; } } else { if (content.statements == null) { content.statements = []; } if (content.statements[group] != null) { content.statements[group].push(statement); } else { (content.statements[group]) = [statement]; } } } }; readStatements(trigger, ecaCount, false); content[elementId] = trigger; customScripts.push(null); } } else if (type === TriggerContent_1.ContentType.COMMENT) { content[elementId] = { name, contentType: TriggerContent_1.ContentType.COMMENT, comment: description }; } else if (type === TriggerContent_1.ContentType.CUSTOM_SCRIPT) { const script = { name, contentType: TriggerContent_1.ContentType.CUSTOM_SCRIPT, description, isEnabled, script: '' }; content[elementId] = script; customScripts.push(script); } break; case TriggerContent_1.ContentType.VARIABLE: elementId = outBufferToJSON.readInt(); name = outBufferToJSON.readString(); // excess data? parentElementId = outBufferToJSON.readInt(); elementRelations.set(elementId, parentElementId); break; } } const roots = []; const missingElements = []; // Generate data tree structure for (const [elementId, parentId] of elementRelations.entries()) { if (parentId === -1) { if (containers[elementId] != null) { roots.push(containers[elementId]); } } else { let parent; if (containers[parentId] != null) { parent = containers[parentId]; } let element; if (containers[elementId] != null) { element = containers[elementId]; } else if (content[elementId] != null) { element = content[elementId]; } if (parent == null || element == null) { missingElements.push({ foundElement: element != null, foundParent: parent != null, elementId, parentId, data: parent != null ? parent : element }); continue; } parent.children.push(element); } } return { json: { roots, scriptReferences: customScripts }, errors: [] }; } catch (e) { return { json: { roots: [], scriptReferences: [] }, errors: [ { message: ` Error at offset: ${outBufferToJSON._offset}` }, { message: e } ] }; } } } exports.TriggersTranslator = TriggersTranslator; TriggersTranslator.instance = null; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJpZ2dlclRyYW5zbGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhbnNsYXRvci9UcmlnZ2VyVHJhbnNsYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2RUFBeUU7QUFFekUsa0VBQWdGO0FBQ2hGLDhFQUEwRTtBQU8xRSxrRkFBOEU7QUFDOUUsa0VBQThEO0FBRTlELGtGQUE4RTtBQUU5RSxrRUFBOEQ7QUFFOUQsNkRBQXlEO0FBQ3pELDJEQUF1RDtBQVN2RCxTQUFTLGlCQUFpQixDQUFFLEtBQXlCO0lBQ25ELE1BQU0sWUFBWSxHQUFxQixDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUE7SUFDakQsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUE7SUFFN0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNqQyxNQUFNLENBQUMsR0FBRyxDQUFDLDRCQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sQ0FBQyxHQUFHLENBQUMsNEJBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDbkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNsQyxNQUFNLENBQUMsR0FBRyxDQUFDLDRCQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sQ0FBQyxHQUFHLENBQUMsNEJBQVcsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDeEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUVuQyxPQUFPLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzlCLE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUN6QyxJQUFJLGNBQWMsSUFBSSxJQUFJO1lBQUUsU0FBUTtRQUNwQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUNwRCxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUU7WUFDakIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFBO1NBQzFDO2FBQU07WUFDTCxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFBO1NBQ2xEO1FBQ0QsUUFBUSxjQUFjLENBQUMsV0FBVyxFQUFFO1lBQ2xDLEtBQUssNEJBQVcsQ0FBQyxNQUFNLENBQUM7WUFDeEIsS0FBSyw0QkFBVyxDQUFDLE9BQU8sQ0FBQztZQUN6QixLQUFLLDRCQUFXLENBQUMsUUFBUTtnQkFDdkIsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFJLGNBQW1DLENBQUMsUUFBUSxDQUFDLENBQUE7U0FDdEU7S0FDRjtJQUVELE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUUsS0FBeUIsRUFBRSxnQkFBNkMsRUFBRSxJQUFpQjtJQUN2SCxNQUFNLFlBQVksR0FBcUIsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFBO0lBQ2pELE1BQU0sV0FBVyxHQUF1QixFQUFFLENBQUE7SUFDMUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQTBCLENBQUE7SUFDaEQsT0FBTyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUM5QixNQUFNLGNBQWMsR0FBRyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDekMsSUFBSSxjQUFjLElBQUksSUFBSTtZQUFFLFNBQVE7UUFFcEMsSUFBSSxNQUFNLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQzlCLElBQUksUUFBNEIsQ0FBQTtRQUNoQyxPQUFPLE1BQU0sSUFBSSxJQUFJLEVBQUU7WUFDckIsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxLQUFLLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFBRSxNQUFLLENBQUMscUJBQXFCO1lBQ3BHLE1BQU0sR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUEsQ0FBQyxvQkFBb0I7U0FDaEQ7UUFDRCxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUU7WUFDbEIsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFBO1NBQ2Q7YUFBTTtZQUNMLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDeEIsUUFBUSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN2QyxJQUFJLFFBQVEsSUFBSSxJQUFJLEVBQUU7Z0JBQ3BCLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLEdBQUcsY0FBYyxDQUFDLENBQUEsQ0FBQyxrREFBa0Q7YUFDN0c7U0FDRjtRQUNELElBQUssY0FBbUMsQ0FBQyxRQUFRLElBQUksSUFBSSxFQUFFO1lBQ3pELFdBQVcsQ0FBQyxJQUFJLENBQUMsY0FBa0MsQ0FBQyxDQUFBO1NBQ3JEO1FBRUQsSUFBSSxjQUFjLENBQUMsV0FBVyxLQUFLLElBQUksRUFBRTtZQUN2QyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQTtTQUNyQztRQUVELFFBQVEsY0FBYyxDQUFDLFdBQVcsRUFBRTtZQUNsQyxLQUFLLDRCQUFXLENBQUMsTUFBTSxDQUFDO1lBQ3hCLEtBQUssNEJBQVcsQ0FBQyxPQUFPLENBQUM7WUFDekIsS0FBSyw0QkFBVyxDQUFDLFFBQVE7Z0JBQ3ZCLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBSSxjQUFtQyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1NBQ3RFO0tBQ0Y7SUFFRCxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUM7QUFFRCxNQUFhLGtCQUFrQjtJQUc3QixnQkFBeUIsQ0FBQztJQUVuQixNQUFNLENBQUMsV0FBVztRQUN2QixJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQTtTQUMzQjtRQUNELE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQTtJQUN0QixDQUFDO0lBRU0sTUFBTSxDQUFDLFNBQVMsQ0FBRSxRQUFpQztRQUN4RCxPQUFPLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDL0MsQ0FBQztJQUVNLE1BQU0sQ0FBQyxTQUFTLENBQUUsTUFBYztRQUNyQyxPQUFPLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDN0MsQ0FBQztJQUVNLFNBQVMsQ0FBRSxJQUE2QjtRQUM3QyxNQUFNLGNBQWMsR0FBRyxJQUFJLHFCQUFTLEVBQUUsQ0FBQTtRQUV0QyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFBLENBQUMsY0FBYztRQUM5QyxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzVCLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDNUIsY0FBYyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM1QixjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBLENBQUMsaUJBQWlCO1FBQzlDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUEsQ0FBQyxtQkFBbUI7UUFFNUMsTUFBTSxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDdkQsSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFBO1FBQ3JCLEtBQUssTUFBTSxLQUFLLElBQUksaUJBQWlCLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDOUMsYUFBYSxHQUFHLGFBQWEsR0FBRyxLQUFLLENBQUE7U0FDdEM7UUFDRCxNQUFNLGlCQUFpQixHQUFHLFVBQVUsV0FBd0I7WUFDMUQsY0FBYyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFXLENBQUMsQ0FBQTtZQUNuRSxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBLENBQUMsZ0JBQWdCO1FBQzNDLENBQUMsQ0FBQTtRQUNELGlCQUFpQixDQUFDLDRCQUFXLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDckMsaUJBQWlCLENBQUMsNEJBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUN0QyxpQkFBaUIsQ0FBQyw0QkFBVyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3ZDLGlCQUFpQixDQUFDLDRCQUFXLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDdEMsaUJBQWlCLENBQUMsNEJBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUN0QyxpQkFBaUIsQ0FBQyw0QkFBVyxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBQzVDLGlCQUFpQixDQUFDLDRCQUFXLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFdkMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLFVBQVU7UUFDbkMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLFVBQVU7UUFDbkMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLHlCQUF5QjtRQUVsRCxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUEwQixDQUFBO1FBRTFELElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQTtRQUNuQixJQUFJLFlBQVksR0FBRyxDQUFDLENBQUE7UUFDcEIsSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFBO1FBQ3JCLElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQTtRQUNwQixJQUFJLFlBQVksR0FBRyxDQUFDLENBQUE7UUFDcEIsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUE7UUFDekIsSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFBO1FBRXJCLE1BQU0sWUFBWSxHQUFxQixDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRXRELE9BQU8sWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDOUIsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFBO1lBQ3pDLElBQUksY0FBYyxJQUFJLElBQUk7Z0JBQUUsU0FBUTtZQUNwQyxJQUFJLFNBQWlCLENBQUE7WUFFckIsUUFBUSxjQUFjLENBQUMsV0FBVyxFQUFFO2dCQUNsQyxLQUFLLDRCQUFXLENBQUMsTUFBTTtvQkFDckIsU0FBUyxHQUFHLFVBQVUsR0FBRyxXQUFXLEVBQUUsQ0FBQTtvQkFDdEMsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFJLGNBQW1DLENBQUMsUUFBUSxDQUFDLENBQUE7b0JBQ25FLE1BQUs7Z0JBQ1AsS0FBSyw0QkFBVyxDQUFDLE9BQU87b0JBQ3RCLFNBQVMsR0FBRyxVQUFVLEdBQUcsWUFBWSxFQUFFLENBQUE7b0JBQ3ZDLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBSSxjQUFtQyxDQUFDLFFBQVEsQ0FBQyxDQUFBO29CQUNuRSxNQUFLO2dCQUNQLEtBQUssNEJBQVcsQ0FBQyxRQUFRO29CQUN2QixTQUFTLEdBQUcsVUFBVSxHQUFHLGFBQWEsRUFBRSxDQUFBO29CQUN4QyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUksY0FBbUMsQ0FBQyxRQUFRLENBQUMsQ0FBQTtvQkFDbkUsTUFBSztnQkFDUCxLQUFLLDRCQUFXLENBQUMsT0FBTyxDQUFDO2dCQUN6QixLQUFLLDRCQUFXLENBQUMsZ0JBQWdCO29CQUMvQixTQUFTLEdBQUcsVUFBVSxHQUFHLFlBQVksRUFBRSxDQUFBO29CQUN2QyxNQUFLO2dCQUNQLEtBQUssNEJBQVcsQ0FBQyxPQUFPO29CQUN0QixTQUFTLEdBQUcsVUFBVSxHQUFHLFlBQVksRUFBRSxDQUFBO29CQUN2QyxNQUFLO2dCQUNQLEtBQUssNEJBQVcsQ0FBQyxhQUFhO29CQUM1QixTQUFTLEdBQUcsVUFBVSxHQUFHLGlCQUFpQixFQUFFLENBQUE7b0JBQzVDLE1BQUs7Z0JBQ1AsS0FBSyw0QkFBVyxDQUFDLFFBQVE7b0JBQ3ZCLFNBQVMsR0FBRyxVQUFVLEdBQUcsYUFBYSxFQUFFLENBQUE7b0JBQ3hDLE1BQUs7Z0JBQ1A7b0JBQ0UsU0FBUTthQUNYO1lBQ0QsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxTQUFTLENBQUMsQ0FBQTtTQUNoRDtRQUVELE1BQU0sU0FBUyxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsNEJBQVcsQ0FBQyxRQUFRLENBQWdDLENBQUE7UUFDeEgsY0FBYyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFckMsS0FBSyxNQUFNLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN0RCxjQUFjLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUN2QyxjQUFjLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUN2QyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFBLENBQUMscUJBQXFCO1lBQzlDLGNBQWMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUMvQyxjQUFjLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUMzQyxjQUFjLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDckQsY0FBYyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUE7WUFDL0MsTUFBTSxTQUFTLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQ2hELElBQUksU0FBUyxJQUFJLElBQUksRUFBRTtnQkFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLFFBQVEsQ0FBQyxJQUFJLGFBQWEsQ0FBQyxDQUFBO2FBQ3hEO1lBQ0QsY0FBYyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQTtZQUNoQyxjQUFjLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFBLENBQUMsU0FBUztTQUMxQztRQUVELFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDaEMsTUFBTSxXQUFXLEdBQXVCLEVBQUUsQ0FBQTtRQUMxQyxjQUFjLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBQ3BDLE9BQU8sWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDOUIsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFBO1lBQ3pDLElBQUksY0FBYyxJQUFJLElBQUk7Z0JBQUUsU0FBUTtZQUNwQyxNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUE7WUFDdEQsSUFBSSxTQUFTLElBQUksSUFBSSxFQUFFO2dCQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixjQUFjLENBQUMsSUFBSSxhQUFhLENBQUMsQ0FBQTthQUNwRTtZQUNELGNBQWMsQ0FBQyxNQUFNLENBQUMsbURBQXdCLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFBO1lBRXhGLElBQUksTUFBTSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQTtZQUM5QixJQUFJLFFBQTRCLENBQUE7WUFDaEMsT0FBTyxNQUFNLElBQUksSUFBSSxFQUFFO2dCQUNyQixJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEtBQUssY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUFFLE1BQUssQ0FBQyxxQkFBcUI7Z0JBQ3BHLE1BQU0sR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUEsQ0FBQyxvQkFBb0I7YUFDaEQ7WUFDRCxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUU7Z0JBQ2xCLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQTthQUNkO2lCQUFNO2dCQUNMLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQ3hCLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQ3ZDLElBQUksUUFBUSxJQUFJLElBQUksRUFBRTtvQkFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUMsQ0FBQSxDQUFDLGtEQUFrRDtpQkFDN0c7YUFDRjtZQUNELElBQUssY0FBbUMsQ0FBQyxRQUFRLElBQUksSUFBSSxFQUFFO2dCQUN6RCxXQUFXLENBQUMsSUFBSSxDQUFDLGNBQWtDLENBQUMsQ0FBQTthQUNyRDtZQUVELElBQUksUUFBZ0IsQ0FBQTtZQUNwQixRQUFRLGNBQWMsQ0FBQyxXQUFXLEVBQUU7Z0JBQ2xDLEtBQUssNEJBQVcsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hCLEtBQUssNEJBQVcsQ0FBQyxPQUFPLENBQUM7Z0JBQ3pCLEtBQUssNEJBQVcsQ0FBQyxRQUFRO29CQUN2QixjQUFjLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFBO29CQUNoQyxjQUFjLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDN0MsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLGdCQUFnQjtvQkFDekMsY0FBYyxDQUFDLE1BQU0sQ0FBRSxjQUFtQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLGVBQWU7b0JBQzlGLGNBQWMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7b0JBQy9CLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBSSxjQUFtQyxDQUFDLFFBQVEsQ0FBQyxDQUFBO29CQUNuRSxNQUFLO2dCQUVQLEtBQUssNEJBQVcsQ0FBQyxPQUFPLENBQUM7Z0JBQ3pCLEtBQUssNEJBQVcsQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDbEMsS0FBSyw0QkFBVyxDQUFDLE9BQU8sQ0FBQztnQkFDekIsS0FBSyw0QkFBVyxDQUFDLGFBQWE7b0JBQzVCLGNBQWMsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFBO29CQUM3QyxJQUFJLGNBQWMsQ0FBQyxXQUFXLEtBQUssNEJBQVcsQ0FBQyxPQUFPLEVBQUU7d0JBQ3RELGNBQWMsQ0FBQyxTQUFTLENBQUUsY0FBaUMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtxQkFDckU7eUJBQU07d0JBQ0wsY0FBYyxDQUFDLFNBQVMsQ0FBRSxjQUE2QixDQUFDLFdBQVcsQ0FBQyxDQUFBO3FCQUNyRTtvQkFDRCxjQUFjLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxXQUFXLEtBQUssNEJBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7b0JBQ2pGLGNBQWMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUE7b0JBQ2hDLElBQUksY0FBYyxDQUFDLFdBQVcsS0FBSyw0QkFBVyxDQUFDLGFBQWEsRUFBRTt3QkFDNUQsY0FBYyxDQUFDLE1BQU0sQ0FBRSxjQUErQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTt3QkFDekUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLG1CQUFtQjt3QkFDNUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLGdCQUFnQjt3QkFDekMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLDBCQUEwQjt3QkFDbkQsY0FBYyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQTt3QkFDL0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLGNBQWM7cUJBQ3hDO3lCQUFNLElBQUksY0FBYyxDQUFDLFdBQVcsS0FBSyw0QkFBVyxDQUFDLE9BQU8sRUFBRTt3QkFDN0QsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQSxDQUFDLGNBQWM7d0JBQ3ZDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUEsQ0FBQyxtQkFBbUI7d0JBQzVDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUEsQ0FBQyxnQkFBZ0I7d0JBQ3pDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUEsQ0FBQywwQkFBMEI7d0JBQ25ELGNBQWMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7d0JBQy9CLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUEsQ0FBQyxjQUFjO3FCQUN4Qzt5QkFBTSxJQUFJLGNBQWMsQ0FBQyxXQUFXLEtBQUssNEJBQVcsQ0FBQyxPQUFPLEVBQUU7d0JBQzdELFFBQVEsR0FBSSxj