patchwork-mapconverter
Version:
Executable wrapper for https://github.com/ChiefOfGxBxL/WC3MapTranslator
692 lines • 69.1 kB
JavaScript
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJpZ2dlclRyYW5zbGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhbnNsYXRvci9UcmlnZ2VyVHJhbnNsYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2RUFBeUU7QUFFekUsa0VBQWdGO0FBQ2hGLDhFQUEwRTtBQU8xRSxrRkFBOEU7QUFDOUUsa0VBQThEO0FBRTlELGtGQUE4RTtBQUU5RSxrRUFBOEQ7QUFFOUQsNkRBQXlEO0FBQ3pELDJEQUF1RDtBQVN2RCxTQUFTLGlCQUFpQixDQUFFLEtBQXlCO0lBQ25ELE1BQU0sWUFBWSxHQUFxQixDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUE7SUFDakQsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUE7SUFFN0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNqQyxNQUFNLENBQUMsR0FBRyxDQUFDLDRCQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sQ0FBQyxHQUFHLENBQUMsNEJBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDbkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNsQyxNQUFNLENBQUMsR0FBRyxDQUFDLDRCQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sQ0FBQyxHQUFHLENBQUMsNEJBQVcsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDeEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyw0QkFBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUVuQyxPQUFPLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzlCLE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUN6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