You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
919 lines
130 KiB
919 lines
130 KiB
"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 () {
|
|
var ownKeys = function(o) {
|
|
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
var ar = [];
|
|
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
return ar;
|
|
};
|
|
return ownKeys(o);
|
|
};
|
|
return function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
})();
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.excelToJsonPlugin = void 0;
|
|
const fs = __importStar(require("fs"));
|
|
const path = __importStar(require("path"));
|
|
const os = __importStar(require("os"));
|
|
const MembershipSet_1 = require("./MembershipSet");
|
|
/** 内置 xlsx 库,无需 npm install */
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
const XLSX = require(path.join(__dirname, '../lib/xlsx.js'));
|
|
const DEFAULT_CONFIG = {
|
|
excelPath: '配置表/excelList',
|
|
jsonExportPath: 'assets/bundles/first/config',
|
|
langJsonExportPath: 'assets/bundles/lang',
|
|
tsExportPath: 'assets/script/interface',
|
|
autoExport: true,
|
|
};
|
|
class ExcelToJsonPlugin {
|
|
constructor() {
|
|
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), { watcher: null });
|
|
this.fileWatcher = null;
|
|
this.isExporting = false;
|
|
this.exportQueue = [];
|
|
/** 本次导出写入过的 JSON 目录,用于刷新 asset-db */
|
|
this.jsonRefreshPaths = (0, MembershipSet_1.createMembershipSet)();
|
|
// 消息处理
|
|
this.messages = {
|
|
'excel-to-json-ts:export-manual': () => {
|
|
this.exportManual();
|
|
}
|
|
};
|
|
}
|
|
async load() {
|
|
await this.exportAllExcel();
|
|
this.setupFileWatcher();
|
|
}
|
|
/** 插件根目录(config.json 所在目录) */
|
|
getPluginRoot() {
|
|
return path.join(__dirname, '..');
|
|
}
|
|
/** 将 config.json 中的相对路径解析为绝对路径(相对项目根目录) */
|
|
resolveProjectPath(relativePath) {
|
|
const projectRoot = Editor.Project.path;
|
|
return path.normalize(path.join(projectRoot, relativePath.replace(/\\/g, '/').replace(/^\.\//, '')));
|
|
}
|
|
/** 判断工作表是否需要导出:格式为 "描述|json文件名",且非默认 Sheet */
|
|
isExportableSheet(sheetName) {
|
|
if (!sheetName || sheetName.startsWith('Sheet')) {
|
|
return false;
|
|
}
|
|
const parts = sheetName.split('|');
|
|
return parts.length >= 2 && parts[1].trim().length > 0;
|
|
}
|
|
/** 获取工作表导出的 json 文件名(| 后第一段) */
|
|
getSheetExportName(sheetName) {
|
|
return sheetName.split('|')[1].trim();
|
|
}
|
|
/** 语言表:lang_cn / lang_en … */
|
|
isLangExportName(exportName) {
|
|
return /^lang_[a-z]{2}$/i.test(exportName);
|
|
}
|
|
/** 解析 JSON 导出目录(语言表进对应语言包 bundle) */
|
|
resolveJsonExportDir(exportName) {
|
|
if (this.isLangExportName(exportName)) {
|
|
return path.join(this.config.langJsonExportPath, exportName, 'config');
|
|
}
|
|
return this.config.jsonExportPath;
|
|
}
|
|
/** 清理 first 中遗留的语言表 JSON(历史路径) */
|
|
removeStaleLangJsonInFirst(jsonFileName) {
|
|
const stalePath = path.join(this.config.jsonExportPath, jsonFileName);
|
|
if (fs.existsSync(stalePath)) {
|
|
fs.unlinkSync(stalePath);
|
|
this.log(`[Excel插件] 已删除 first 中遗留语言表: ${jsonFileName}`);
|
|
}
|
|
const staleMeta = `${stalePath}.meta`;
|
|
if (fs.existsSync(staleMeta)) {
|
|
fs.unlinkSync(staleMeta);
|
|
}
|
|
}
|
|
unload() {
|
|
this.log('[Excel插件] 插件已卸载');
|
|
this.stopFileWatcher();
|
|
}
|
|
/** 从插件根目录 config.json 加载配置,路径相对项目根目录 */
|
|
loadConfig() {
|
|
var _a;
|
|
const configPath = path.join(this.getPluginRoot(), 'config.json');
|
|
try {
|
|
if (!fs.existsSync(configPath)) {
|
|
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 4), 'utf-8');
|
|
this.warn(`[Excel插件] 已创建默认配置文件: ${configPath}`);
|
|
}
|
|
const raw = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
const merged = Object.assign(Object.assign({}, DEFAULT_CONFIG), raw);
|
|
this.config.excelPath = this.resolveProjectPath(merged.excelPath);
|
|
this.config.jsonExportPath = this.resolveProjectPath(merged.jsonExportPath);
|
|
this.config.langJsonExportPath = this.resolveProjectPath((_a = merged.langJsonExportPath) !== null && _a !== void 0 ? _a : DEFAULT_CONFIG.langJsonExportPath);
|
|
this.config.tsExportPath = this.resolveProjectPath(merged.tsExportPath);
|
|
this.config.autoExport = merged.autoExport;
|
|
this.log('[Excel插件] 配置已加载 (extensions/excel-to-json-ts/config.json)');
|
|
this.log(`[Excel插件] excelPath: ${this.config.excelPath}`);
|
|
this.log(`[Excel插件] jsonPath: ${this.config.jsonExportPath}`);
|
|
this.log(`[Excel插件] langJsonPath: ${this.config.langJsonExportPath}`);
|
|
this.log(`[Excel插件] tsPath: ${this.config.tsExportPath}`);
|
|
this.log(`[Excel插件] autoExport: ${this.config.autoExport}`);
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 加载配置失败 (${configPath}): ${err}`);
|
|
}
|
|
}
|
|
// 手动导出
|
|
exportManual() {
|
|
this.exportAllExcel();
|
|
}
|
|
// 导出所有Excel(增强健壮性)
|
|
async exportAllExcel() {
|
|
this.loadConfig();
|
|
if (!this.config.excelPath) {
|
|
this.error('[Excel插件] Excel目录路径未配置');
|
|
return;
|
|
}
|
|
if (!fs.existsSync(this.config.excelPath)) {
|
|
this.error(`[Excel插件] Excel目录不存在: ${this.config.excelPath}`);
|
|
return;
|
|
}
|
|
try {
|
|
(0, MembershipSet_1.membershipClear)(this.jsonRefreshPaths);
|
|
// 确保导出目录存在
|
|
if (this.config.jsonExportPath && !fs.existsSync(this.config.jsonExportPath)) {
|
|
fs.mkdirSync(this.config.jsonExportPath, { recursive: true });
|
|
}
|
|
if (this.config.langJsonExportPath && !fs.existsSync(this.config.langJsonExportPath)) {
|
|
fs.mkdirSync(this.config.langJsonExportPath, { recursive: true });
|
|
}
|
|
if (this.config.tsExportPath && !fs.existsSync(this.config.tsExportPath)) {
|
|
fs.mkdirSync(this.config.tsExportPath, { recursive: true });
|
|
}
|
|
// 获取目录中所有Excel文件
|
|
const excelFiles = this.getExcelFilesInDirectory(this.config.excelPath);
|
|
if (excelFiles.length === 0) {
|
|
this.warn(`[Excel插件] 目录中没有找到Excel文件: ${this.config.excelPath}`);
|
|
return;
|
|
}
|
|
this.log(`[Excel插件] 找到 ${excelFiles.length} 个Excel文件`);
|
|
let successCount = 0;
|
|
let errorCount = 0;
|
|
// 处理每个Excel文件
|
|
for (const excelFile of excelFiles) {
|
|
try {
|
|
this.processExcelFile(excelFile);
|
|
successCount++;
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 处理文件失败 ${path.basename(excelFile)}: ${err}`);
|
|
errorCount++;
|
|
}
|
|
}
|
|
if (successCount > 0) {
|
|
this.refreshAssetDatabase();
|
|
this.success(`[Excel插件] 导出完成,成功处理 ${successCount} 个文件,失败 ${errorCount} 个`);
|
|
}
|
|
else {
|
|
this.error(`[Excel插件] 导出失败,没有成功处理任何文件`);
|
|
}
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 导出失败: ${err}`);
|
|
}
|
|
}
|
|
// 获取目录中的所有Excel文件
|
|
getExcelFilesInDirectory(dirPath) {
|
|
return fs.readdirSync(dirPath)
|
|
.filter(file => {
|
|
// 过滤隐藏文件(以点开头的文件)
|
|
if (file.startsWith('.') || file.startsWith('~')) {
|
|
return false;
|
|
}
|
|
const ext = path.extname(file).toLowerCase();
|
|
return (ext === '.xlsx' || ext === '.xls') &&
|
|
fs.statSync(path.join(dirPath, file)).isFile();
|
|
})
|
|
.map(file => path.join(dirPath, file));
|
|
}
|
|
// 处理单个Excel文件
|
|
processExcelFile(filePath) {
|
|
try {
|
|
// 安全读取打开状态的Excel文件
|
|
const workbook = this.readExcelSafely(filePath);
|
|
const sheetNames = workbook.SheetNames;
|
|
// 导出每个工作表
|
|
for (const sheetName of sheetNames) {
|
|
if (!this.isExportableSheet(sheetName)) {
|
|
continue;
|
|
}
|
|
this.exportSheet(workbook, sheetName, filePath);
|
|
}
|
|
}
|
|
catch (err) {
|
|
throw new Error(`处理文件 ${path.basename(filePath)} 失败: ${err}`);
|
|
}
|
|
}
|
|
/** 从 buffer 解析 Excel,避免 readFile 在 Windows 中文路径下失败 */
|
|
parseExcelBuffer(buffer) {
|
|
return XLSX.read(buffer, { type: 'buffer' });
|
|
}
|
|
/** 读取 Excel:优先直接读,失败时复制到 ASCII 临时文件再读 */
|
|
readExcelSafely(filePath) {
|
|
// 1. 直接读取(文件未占用时最快)
|
|
try {
|
|
const buffer = fs.readFileSync(filePath);
|
|
if (buffer.length > 0) {
|
|
return this.parseExcelBuffer(buffer);
|
|
}
|
|
}
|
|
catch (directErr) {
|
|
this.warn(`[Excel插件] 直接读取失败,尝试复制后读取: ${path.basename(filePath)} (${directErr})`);
|
|
}
|
|
// 2. 复制到纯 ASCII 临时路径(避免中文文件名导致 xlsx 库无法访问)
|
|
const tempPath = path.join(os.tmpdir(), `excel-temp-${Date.now()}-${process.pid}.xlsx`);
|
|
try {
|
|
fs.copyFileSync(filePath, tempPath);
|
|
const tempStats = fs.statSync(tempPath);
|
|
if (tempStats.size === 0) {
|
|
throw new Error('临时文件大小为0,复制可能未完成');
|
|
}
|
|
const buffer = fs.readFileSync(tempPath);
|
|
return this.parseExcelBuffer(buffer);
|
|
}
|
|
catch (err) {
|
|
throw new Error(`读取Excel失败: ${err.message || err}`);
|
|
}
|
|
finally {
|
|
try {
|
|
if (fs.existsSync(tempPath)) {
|
|
fs.unlinkSync(tempPath);
|
|
}
|
|
}
|
|
catch (e) {
|
|
this.warn(`[Excel插件] 无法删除临时文件: ${tempPath} - ${e}`);
|
|
}
|
|
}
|
|
}
|
|
// 导出单个工作表
|
|
exportSheet(workbook, sheetName, filePath) {
|
|
try {
|
|
const worksheet = workbook.Sheets[sheetName];
|
|
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
|
// 检查是否有足够的表头行(至少3行:字段名、类型、说明)
|
|
if (jsonData.length < 3) {
|
|
this.warn(`[Excel插件] 工作表 "${sheetName}" 数据不足,跳过导出 (文件: ${path.basename(filePath)})的${sheetName}`);
|
|
return;
|
|
}
|
|
if (!this.isExportableSheet(sheetName)) {
|
|
this.warn(`[Excel插件] 工作表 "${sheetName}" 名称格式错误,跳过导出 (文件: ${path.basename(filePath)})`);
|
|
return;
|
|
}
|
|
const sName = this.getSheetExportName(sheetName);
|
|
// 提取表头信息
|
|
const headers = {
|
|
fields: jsonData[0],
|
|
types: jsonData[1],
|
|
descriptions: jsonData[2]
|
|
};
|
|
// 从第4行开始是数据
|
|
const dataRows = jsonData.slice(3);
|
|
// 生成JSON数据
|
|
const jsonResult = this.generateJsonData(dataRows, headers);
|
|
// 生成TS接口
|
|
const tsInterface = this.generateTSInterface(sName, headers);
|
|
// 生成文件名
|
|
const safeSheetName = this.makeSafeFileName(sName);
|
|
const jsonFileName = `${safeSheetName}.json`;
|
|
//const tsFileName = `ITable${safeSheetName}.ts`;
|
|
const tsFileName = `AutoTable.ts`;
|
|
const jsonExportDir = this.resolveJsonExportDir(sName);
|
|
if (!fs.existsSync(jsonExportDir)) {
|
|
fs.mkdirSync(jsonExportDir, { recursive: true });
|
|
}
|
|
// 写入JSON文件
|
|
if (jsonExportDir) {
|
|
const jsonPath = path.join(jsonExportDir, jsonFileName);
|
|
fs.writeFileSync(jsonPath, JSON.stringify(jsonResult, null, 4), 'utf-8');
|
|
(0, MembershipSet_1.membershipAdd)(this.jsonRefreshPaths, jsonExportDir);
|
|
if (this.isLangExportName(sName)) {
|
|
this.removeStaleLangJsonInFirst(jsonFileName);
|
|
}
|
|
}
|
|
// 写入TS文件
|
|
if (this.config.tsExportPath) {
|
|
const tsPath = path.join(this.config.tsExportPath, tsFileName);
|
|
let tsContent = "";
|
|
try {
|
|
if (fs.existsSync(tsPath)) {
|
|
tsContent = fs.readFileSync(tsPath, 'utf-8');
|
|
}
|
|
}
|
|
catch (err) {
|
|
this.warn(`[Excel插件] 读取TS文件失败: ${err}`);
|
|
}
|
|
if (tsContent == "") {
|
|
tsContent = "declare global {\n\n}\nexport { };";
|
|
}
|
|
if (this.extractFullInterfaceBlock(tsContent, "ITable" + sName)) {
|
|
tsContent = this.replaceInterfaceBlock(tsContent, "ITable" + sName, tsInterface);
|
|
}
|
|
else {
|
|
tsContent = tsContent.replace(/\}\r?\nexport \{ \};$/, tsInterface + "}\nexport { };");
|
|
}
|
|
tsContent = this.normalizeAutoTableBlankLines(tsContent);
|
|
fs.writeFileSync(tsPath, tsContent, 'utf-8');
|
|
}
|
|
}
|
|
catch (err) {
|
|
throw new Error(`工作表 "${sheetName}" 导出失败 (文件: ${path.basename(filePath)}): ${err}`);
|
|
}
|
|
}
|
|
/**
|
|
* 转义正则特殊字符
|
|
*/
|
|
escapeRegExp(str) {
|
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
}
|
|
/**
|
|
* 精准查找接口声明行(全字匹配)
|
|
*/
|
|
findInterfaceDeclarationLine(fileContent, interfaceName) {
|
|
// 使用单词边界 \b 确保全字匹配
|
|
const regex = new RegExp(`\\binterface\\s+${this.escapeRegExp(interfaceName)}\\b(?:\\s*<[^>]*>)?\\s*[\\{\\n]`, 'g');
|
|
let match;
|
|
while ((match = regex.exec(fileContent)) !== null) {
|
|
// 找到匹配位置,确定完整行
|
|
const matchStart = match.index;
|
|
// 向前找到行开始
|
|
const lineStart = fileContent.lastIndexOf('\n', matchStart - 1) + 1;
|
|
// 向后找到行结束
|
|
const lineEnd = fileContent.indexOf('\n', matchStart);
|
|
const actualLineEnd = lineEnd === -1 ? fileContent.length : lineEnd;
|
|
const lineContent = fileContent.substring(lineStart, actualLineEnd);
|
|
// 验证:确保这一行确实是我们的目标接口
|
|
if (lineContent.trim().startsWith(`interface ${interfaceName}`)) {
|
|
return {
|
|
lineStart,
|
|
lineEnd: actualLineEnd,
|
|
lineContent
|
|
};
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* 提取完整的接口块(包括上方注释)
|
|
*/
|
|
extractFullInterfaceBlock(fileContent, interfaceName) {
|
|
const interfaceLine = this.findInterfaceDeclarationLine(fileContent, interfaceName);
|
|
if (!interfaceLine) {
|
|
return null;
|
|
}
|
|
// === 向前查找连续的注释块 ===
|
|
let blockStart = interfaceLine.lineStart;
|
|
let currentPos = interfaceLine.lineStart;
|
|
while (currentPos > 0) {
|
|
const prevLineEnd = currentPos - 1;
|
|
const prevLineStart = fileContent.lastIndexOf('\n', prevLineEnd - 1) + 1;
|
|
const prevLine = fileContent.substring(prevLineStart, prevLineEnd).trim();
|
|
// 检查是否为注释行或空行
|
|
if (prevLine === '' ||
|
|
prevLine.startsWith('//') ||
|
|
prevLine.startsWith('/*') ||
|
|
prevLine.startsWith('*')) {
|
|
currentPos = prevLineStart;
|
|
}
|
|
else {
|
|
blockStart = currentPos;
|
|
break;
|
|
}
|
|
}
|
|
if (currentPos === 0) {
|
|
blockStart = 0;
|
|
}
|
|
// === 向后查找接口体结束 ===
|
|
// 找到 interface 行中的开括号位置
|
|
const openBraceIndex = interfaceLine.lineContent.indexOf('{');
|
|
let startPos = interfaceLine.lineStart;
|
|
let braceCount = 0;
|
|
if (openBraceIndex !== -1) {
|
|
// 开括号在同一行
|
|
startPos = interfaceLine.lineStart + openBraceIndex;
|
|
braceCount = 1;
|
|
}
|
|
else {
|
|
// 开括号在下一行,找到第一个 {
|
|
const nextOpenBrace = fileContent.indexOf('{', interfaceLine.lineEnd);
|
|
if (nextOpenBrace === -1)
|
|
return null;
|
|
startPos = nextOpenBrace;
|
|
braceCount = 1;
|
|
}
|
|
let pos = startPos + 1; // 跳过 {
|
|
while (pos < fileContent.length && braceCount > 0) {
|
|
if (fileContent[pos] === '{') {
|
|
braceCount++;
|
|
}
|
|
else if (fileContent[pos] === '}') {
|
|
braceCount--;
|
|
}
|
|
pos++;
|
|
}
|
|
if (braceCount !== 0) {
|
|
return null; // 括号不匹配
|
|
}
|
|
// 吞掉 } 后紧跟的换行,避免替换时 newBlock 再带 \n 导致空行累加
|
|
let blockEnd = pos;
|
|
if (fileContent[blockEnd] === '\r')
|
|
blockEnd++;
|
|
if (fileContent[blockEnd] === '\n')
|
|
blockEnd++;
|
|
const fullContent = fileContent.substring(blockStart, blockEnd);
|
|
return {
|
|
start: blockStart,
|
|
end: blockEnd,
|
|
content: fullContent
|
|
};
|
|
}
|
|
/**
|
|
* 去掉接口之间 / declare global 末尾多余空行(生成时易累加)
|
|
*/
|
|
normalizeAutoTableBlankLines(content) {
|
|
let out = content.replace(/\r\n/g, '\n');
|
|
// 若误带入未解决冲突(通常是空行 vs 无空行),丢掉冲突标记
|
|
out = out.replace(/^<<<<<<< .+\n(?:.*\n)*?=======\n(?:.*\n)*?>>>>>>> .+\n/gm, '');
|
|
// 接口结束 } 后只保留一个换行,再接下一接口注释或 global 结束 }
|
|
out = out.replace(/(\n {4}\})\n(?:[ \t]*\n)+(?=[ \t]*(?:\/\*\*|\}))/g, '$1\n');
|
|
// 文件末尾 export 前也不留空行
|
|
out = out.replace(/\n(?:[ \t]*\n)+(\}\nexport \{ \};)\s*$/g, '\n$1\n');
|
|
return out;
|
|
}
|
|
/**
|
|
* 完全替换接口块(全字匹配,精准替换)
|
|
*/
|
|
replaceInterfaceBlock(fileContent, interfaceName, newInterfaceBlock) {
|
|
const blockInfo = this.extractFullInterfaceBlock(fileContent, interfaceName);
|
|
if (!blockInfo) {
|
|
throw new Error(`❌ 接口 "${interfaceName}" 未找到!请检查名称是否正确。`);
|
|
}
|
|
// 验证:确保提取的块确实只包含目标接口
|
|
const interfaceLines = blockInfo.content.split('\n');
|
|
const interfaceDeclLines = interfaceLines.filter(line => line.trim().startsWith('interface '));
|
|
if (interfaceDeclLines.length !== 1) {
|
|
throw new Error(`❌ 找到多个 interface 声明,可能匹配错误!`);
|
|
}
|
|
if (!interfaceDeclLines[0].includes(`interface ${interfaceName}`)) {
|
|
throw new Error(`❌ 匹配到错误的接口名称!`);
|
|
}
|
|
//console.log(`✅ 精准匹配到接口 "${interfaceName}"`);
|
|
return (fileContent.substring(0, blockInfo.start) +
|
|
newInterfaceBlock +
|
|
fileContent.substring(blockInfo.end));
|
|
}
|
|
// 设置文件监听
|
|
setupFileWatcher() {
|
|
this.stopFileWatcher();
|
|
this.loadConfig();
|
|
if (!this.config.autoExport) {
|
|
this.log('[Excel插件] 自动导出已关闭,跳过文件监听');
|
|
return;
|
|
}
|
|
if (!this.config.excelPath)
|
|
return;
|
|
if (!fs.existsSync(this.config.excelPath)) {
|
|
this.error(`[Excel插件] 监听目录不存在: ${this.config.excelPath}`);
|
|
return;
|
|
}
|
|
try {
|
|
// 使用更可靠的监听方式
|
|
this.fileWatcher = fs.watch(this.config.excelPath, {
|
|
recursive: false,
|
|
encoding: 'utf8'
|
|
}, async (eventType, filename) => {
|
|
if (!filename)
|
|
return;
|
|
this.loadConfig();
|
|
if (!this.config.autoExport)
|
|
return;
|
|
// 确保是字符串
|
|
const fileNameStr = typeof filename === 'string' ? filename : filename + "";
|
|
const ext = path.extname(fileNameStr).toLowerCase();
|
|
if (ext === '.xlsx' || ext === '.xls') {
|
|
const filePath = path.join(this.config.excelPath, fileNameStr);
|
|
// 额外验证:确保是文件且存在
|
|
try {
|
|
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
|
this.log(`[Excel插件] 检测到文件变更: ${fileNameStr} (${eventType})`);
|
|
// 使用终极重试机制
|
|
// 重试次数增加到8,基础延迟1秒
|
|
this.processExcelFileWithRetry(filePath, 8, 1000);
|
|
}
|
|
}
|
|
catch (err) {
|
|
this.warn(`[Excel插件] 验证文件状态时出错: ${err}`);
|
|
}
|
|
}
|
|
});
|
|
// 处理监听错误
|
|
if (this.fileWatcher && typeof this.fileWatcher.on === 'function') {
|
|
this.fileWatcher.on('error', (error) => {
|
|
this.error(`[Excel插件] 文件监听错误: ${error}`);
|
|
// 尝试重新设置监听
|
|
setTimeout(() => {
|
|
this.stopFileWatcher();
|
|
this.setupFileWatcher();
|
|
}, 15000);
|
|
});
|
|
}
|
|
this.log('[Excel插件] 已启动Excel目录监听(终极版)');
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 目录监听失败: ${err}`);
|
|
// 尝试重新设置监听
|
|
setTimeout(() => {
|
|
this.stopFileWatcher();
|
|
this.setupFileWatcher();
|
|
}, 20000);
|
|
}
|
|
}
|
|
// 带重试机制处理Excel文件(自动导出)
|
|
processExcelFileWithRetry(filePath, maxRetries = 8, baseDelay = 1000) {
|
|
this.enqueueExport(() => this.processExcelFileWithRetryInternal(filePath, maxRetries, baseDelay));
|
|
}
|
|
/** 串行执行导出,避免并发写 AutoTable.ts */
|
|
enqueueExport(task) {
|
|
this.exportQueue.push(task);
|
|
if (!this.isExporting) {
|
|
this.runNextExport();
|
|
}
|
|
}
|
|
runNextExport() {
|
|
const task = this.exportQueue.shift();
|
|
if (!task) {
|
|
this.isExporting = false;
|
|
return;
|
|
}
|
|
this.isExporting = true;
|
|
task();
|
|
}
|
|
processExcelFileWithRetryInternal(filePath, maxRetries = 8, baseDelay = 1000) {
|
|
let attempt = 0;
|
|
const startTime = Date.now();
|
|
const tryProcess = () => {
|
|
attempt++;
|
|
const elapsed = Date.now() - startTime;
|
|
const delay = baseDelay * Math.min(1.5 ** (attempt - 1), 4); // 指数退避,但上限为4倍基础延迟
|
|
this.log(`[Excel插件] 处理文件 "${path.basename(filePath)}" - 尝试 ${attempt}/${maxRetries} (延迟 ${Math.round(delay)}ms, 已耗时 ${Math.round(elapsed / 1000)}s)`);
|
|
setTimeout(() => {
|
|
try {
|
|
// 额外检查文件是否可读
|
|
const stats = fs.statSync(filePath);
|
|
if (stats.size === 0) {
|
|
throw new Error("文件大小为0,可能仍在写入");
|
|
}
|
|
// 检查文件最后修改时间,确保不是刚被修改
|
|
const now = Date.now();
|
|
const fileAge = now - stats.mtimeMs;
|
|
if (fileAge < 2000) { // 文件修改时间少于2秒,可能还在写入
|
|
throw new Error(`文件刚被修改 (${Math.round(fileAge)}ms前),可能仍在写入`);
|
|
}
|
|
this.processExcelFile(filePath);
|
|
const totalTime = Date.now() - startTime;
|
|
this.refreshAssetDatabase();
|
|
this.success(`[Excel插件] 文件 "${path.basename(filePath)}" 自动导出成功 (总耗时 ${Math.round(totalTime / 1000)}s, 尝试 ${attempt}/${maxRetries})`);
|
|
this.runNextExport();
|
|
}
|
|
catch (err) {
|
|
// 详细记录错误
|
|
this.warn(`[Excel插件] 尝试 ${attempt} 失败: ${err.message || err}`);
|
|
// 检查是否是文件锁定或权限错误
|
|
const isFileLockError = err.message && (err.message.includes('EPERM') ||
|
|
err.message.includes('EBUSY') ||
|
|
err.message.includes('permission') ||
|
|
err.message.includes('locked') ||
|
|
err.message.includes('EACCES') ||
|
|
err.message.includes('file size 0') ||
|
|
err.message.includes('刚被修改'));
|
|
if (isFileLockError && attempt < maxRetries) {
|
|
// 计算下一次尝试的延迟(指数退避)
|
|
const nextDelay = baseDelay * Math.min(1.5 ** attempt, 4);
|
|
this.warn(`[Excel插件] 文件 "${path.basename(filePath)}" 可能仍在保存中,将在 ${Math.round(nextDelay)}ms 后重试 (尝试 ${attempt + 1}/${maxRetries})`);
|
|
setTimeout(tryProcess, nextDelay);
|
|
}
|
|
else {
|
|
const totalTime = Date.now() - startTime;
|
|
this.error(`[Excel插件] 文件 "${path.basename(filePath)}" 自动导出失败 (总耗时 ${Math.round(totalTime / 1000)}s): ${err}`);
|
|
// 如果是文件锁定错误但已达到最大重试次数,提供具体建议
|
|
if (isFileLockError) {
|
|
this.error(`[Excel插件] 建议: 确保Excel完全保存后再进行修改,或增加重试次数和延迟`);
|
|
}
|
|
this.runNextExport();
|
|
}
|
|
}
|
|
}, delay);
|
|
};
|
|
tryProcess();
|
|
}
|
|
// 停止文件监听(更新)
|
|
stopFileWatcher() {
|
|
if (this.fileWatcher) {
|
|
try {
|
|
// 使用类型断言确保调用close方法
|
|
this.fileWatcher.close();
|
|
this.fileWatcher = null;
|
|
}
|
|
catch (e) {
|
|
this.warn(`[Excel插件] 停止监听时出错: ${e}`);
|
|
}
|
|
if (this.config.watcher) {
|
|
clearTimeout(this.config.watcher);
|
|
this.config.watcher = null;
|
|
}
|
|
this.log('[Excel插件] 已停止Excel文件监听');
|
|
}
|
|
}
|
|
// 生成JSON数据
|
|
generateJsonData(dataRows, headers) {
|
|
const result = [];
|
|
for (const row of dataRows) {
|
|
if (!this.isDataRow(row, headers.fields)) {
|
|
continue;
|
|
}
|
|
const obj = {};
|
|
for (let i = 0; i < headers.fields.length; i++) {
|
|
const field = headers.fields[i];
|
|
const type = headers.types[i];
|
|
if (field) {
|
|
const value = row[i] !== undefined ? row[i] : this.getDefaultValue(type);
|
|
obj[field] = this.convertValue(value, type);
|
|
}
|
|
}
|
|
result.push(obj);
|
|
}
|
|
return result;
|
|
}
|
|
/** 跳过全空行 */
|
|
isDataRow(row, fields) {
|
|
if (!row || row.length === 0) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < fields.length; i++) {
|
|
const field = fields[i];
|
|
if (!field)
|
|
continue;
|
|
const value = row[i];
|
|
if (value !== null && value !== undefined && String(value).trim() !== '') {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/** 判断单元格是否为空 */
|
|
isEmptyValue(value) {
|
|
return value === null || value === undefined || (typeof value === 'string' && value.trim() === '');
|
|
}
|
|
// 根据类型获取默认值
|
|
getDefaultValue(type) {
|
|
if (!type)
|
|
return null;
|
|
const cleanType = type.toLowerCase().trim();
|
|
switch (cleanType) {
|
|
case 'int':
|
|
case 'float':
|
|
return 0;
|
|
case 'boolean':
|
|
return false;
|
|
case 'int[]':
|
|
case 'float[]':
|
|
case 'string[]':
|
|
case 'any[]':
|
|
return [];
|
|
case 'string':
|
|
return '';
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
// 类型转换
|
|
convertValue(value, type) {
|
|
if (this.isEmptyValue(value)) {
|
|
return this.getDefaultValue(type);
|
|
}
|
|
const cleanType = type.toLowerCase().trim();
|
|
try {
|
|
switch (cleanType) {
|
|
case 'int': {
|
|
const n = parseInt(value, 10);
|
|
return isNaN(n) ? 0 : n;
|
|
}
|
|
case 'float': {
|
|
const n = parseFloat(value);
|
|
return isNaN(n) ? 0 : n;
|
|
}
|
|
case 'json':
|
|
return JSON.parse(value);
|
|
case 'boolean':
|
|
return value.toString().toLowerCase() === 'true' || value === 1;
|
|
case 'int[]':
|
|
return this.parseArray(value, 'int');
|
|
case 'float[]':
|
|
return this.parseArray(value, 'float');
|
|
case 'string[]':
|
|
return this.parseArray(value, 'string');
|
|
case 'any[]':
|
|
return this.parseArray(value, 'any');
|
|
default:
|
|
return value;
|
|
}
|
|
}
|
|
catch (e) {
|
|
this.warn(`[Excel插件] 类型转换失败 [${type}]: ${value} - ${e}`);
|
|
return value;
|
|
}
|
|
}
|
|
// 解析数组
|
|
parseArray(value, targetType) {
|
|
if (Array.isArray(value))
|
|
return value;
|
|
// 尝试分割字符串
|
|
let items = [];
|
|
if (typeof value === 'string') {
|
|
items = value.split(/[,;#\s]\s*/).filter(v => v);
|
|
}
|
|
else {
|
|
items = [value];
|
|
}
|
|
return items.map(item => {
|
|
if (targetType === 'any') {
|
|
// 自动识别类型
|
|
if (!isNaN(item)) {
|
|
return !isNaN(parseFloat(item)) ? parseFloat(item) : parseInt(item);
|
|
}
|
|
if (item.toLowerCase() === 'true' || item.toLowerCase() === 'false') {
|
|
return item.toLowerCase() === 'true';
|
|
}
|
|
return item;
|
|
}
|
|
// 指定类型转换
|
|
switch (targetType) {
|
|
case 'int': return parseInt(item);
|
|
case 'float': return parseFloat(item);
|
|
case 'string': return String(item);
|
|
default: return item;
|
|
}
|
|
});
|
|
}
|
|
generateTSInterfaceStart(sheetName) {
|
|
const interfaceName = `ITable${sheetName}`;
|
|
const safeSheetName = `${this.makeSafeFileName(sheetName)}`;
|
|
let tsContent = ` /**\n * ${safeSheetName} 配置数据\n */\n`;
|
|
tsContent += ` interface ${interfaceName} {\n`;
|
|
return tsContent;
|
|
}
|
|
// 生成TS接口
|
|
generateTSInterface(sheetName, headers) {
|
|
const interfaceName = `ITable${sheetName}`;
|
|
const safeSheetName = `${this.makeSafeFileName(sheetName)}`;
|
|
let tsContent = ` /**\n * ${safeSheetName} 配置数据\n */\n`;
|
|
tsContent += ` interface ${interfaceName} {\n`;
|
|
for (let i = 0; i < headers.fields.length; i++) {
|
|
const field = headers.fields[i];
|
|
const type = headers.types[i];
|
|
const description = headers.descriptions[i] || '字段说明';
|
|
if (field) {
|
|
tsContent += ` /** ${description} */\n`;
|
|
tsContent += ` readonly ${field}: ${this.convertToTSType(type)};\n`;
|
|
}
|
|
}
|
|
tsContent += ` }\n`;
|
|
return tsContent;
|
|
}
|
|
// 转换为TS类型
|
|
convertToTSType(excelType) {
|
|
if (!excelType)
|
|
return 'any';
|
|
const type = excelType.toLowerCase().trim();
|
|
switch (type) {
|
|
case 'string':
|
|
return 'string';
|
|
case 'int':
|
|
case 'float':
|
|
return 'number';
|
|
case 'boolean':
|
|
return 'boolean';
|
|
case 'int[]':
|
|
return 'number[]';
|
|
case 'float[]':
|
|
return 'number[]';
|
|
case 'string[]':
|
|
return 'string[]';
|
|
case 'any[]':
|
|
return '(number | string | boolean)[]';
|
|
default:
|
|
return 'any';
|
|
}
|
|
}
|
|
// 转换为PascalCase
|
|
toPascalCase(str) {
|
|
return str.replace(/(\w)(\w*)/g, (_, g1, g2) => g1.toUpperCase() + g2.toLowerCase()).replace(/[^a-zA-Z0-9]/g, '');
|
|
}
|
|
// 创建安全的文件名
|
|
makeSafeFileName(name) {
|
|
return name.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
}
|
|
// 日志输出
|
|
log(message) {
|
|
console.log(message);
|
|
}
|
|
error(message) {
|
|
console.error(message);
|
|
}
|
|
warn(message) {
|
|
console.warn(message);
|
|
}
|
|
success(message) {
|
|
console.log(message);
|
|
}
|
|
// 刷新资源管理器
|
|
async refreshAssetDatabase() {
|
|
try {
|
|
const paths = (0, MembershipSet_1.membershipFromArray)([
|
|
...(0, MembershipSet_1.membershipToArray)(this.jsonRefreshPaths),
|
|
this.config.jsonExportPath,
|
|
this.config.langJsonExportPath,
|
|
]);
|
|
for (const systemPath of (0, MembershipSet_1.membershipToArray)(paths)) {
|
|
const dbPath = this.convertToDbPath(systemPath);
|
|
if (dbPath && dbPath.startsWith('db://')) {
|
|
await Editor.Message.request('asset-db', 'refresh-asset', dbPath);
|
|
}
|
|
}
|
|
const tsDbPath = this.convertToDbPath(this.config.tsExportPath);
|
|
if (tsDbPath && tsDbPath.startsWith('db://')) {
|
|
await Editor.Message.request('asset-db', 'refresh-asset', tsDbPath);
|
|
}
|
|
this.success('[Excel插件] 资源刷新请求已发送');
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 资源刷新失败: ${err}`);
|
|
}
|
|
}
|
|
// 将系统路径转换为Cocos的db路径
|
|
convertToDbPath(systemPath) {
|
|
if (!systemPath)
|
|
return '';
|
|
try {
|
|
// 获取项目路径
|
|
const projectPath = Editor.Project.path;
|
|
// 规范化路径(统一使用正斜杠)
|
|
systemPath = systemPath.replace(/\\/g, '/');
|
|
const normalizedProjectPath = projectPath.replace(/\\/g, '/');
|
|
// 确保路径以/结尾
|
|
const projectPathWithSlash = normalizedProjectPath.endsWith('/')
|
|
? normalizedProjectPath
|
|
: normalizedProjectPath + '/';
|
|
// 检查是否在项目目录内
|
|
if (systemPath.startsWith(projectPathWithSlash)) {
|
|
// 计算相对路径
|
|
const relativePath = systemPath.substring(projectPathWithSlash.length);
|
|
return `db://${relativePath}`;
|
|
}
|
|
// 如果路径包含assets目录,尝试直接转换
|
|
if (systemPath.includes('/assets/') || systemPath.includes('\\assets\\')) {
|
|
const assetsIndex = systemPath.toLowerCase().indexOf('/assets/');
|
|
if (assetsIndex !== -1) {
|
|
const relativeToAssets = systemPath.substring(assetsIndex + 1);
|
|
return `db://${relativeToAssets}`;
|
|
}
|
|
}
|
|
this.warn(`[Excel插件] 路径不在项目内,可能无法正确刷新: ${systemPath}`);
|
|
return systemPath;
|
|
}
|
|
catch (err) {
|
|
this.error(`[Excel插件] 路径转换失败: ${err}`);
|
|
return systemPath;
|
|
}
|
|
}
|
|
}
|
|
exports.excelToJsonPlugin = new ExcelToJsonPlugin();
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhjZWwyanNvbkFuZFRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc291cmNlL2V4Y2VsMmpzb25BbmRUcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLHVDQUF5QjtBQUN6QixtREFNeUI7QUFFekIsK0JBQStCO0FBQy9CLGlFQUFpRTtBQUNqRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0FBZTdELE1BQU0sY0FBYyxHQUFxQjtJQUNyQyxTQUFTLEVBQUUsZUFBZTtJQUMxQixjQUFjLEVBQUUsNkJBQTZCO0lBQzdDLGtCQUFrQixFQUFFLHFCQUFxQjtJQUN6QyxZQUFZLEVBQUUseUJBQXlCO0lBQ3ZDLFVBQVUsRUFBRSxJQUFJO0NBQ25CLENBQUM7QUFFRixNQUFNLGlCQUFpQjtJQUF2QjtRQUNZLFdBQU0sbUNBQXNCLGNBQWMsS0FBRSxPQUFPLEVBQUUsSUFBSSxJQUFHO1FBRTVELGdCQUFXLEdBQXdCLElBQUksQ0FBQztRQUN4QyxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUNwQixnQkFBVyxHQUFtQixFQUFFLENBQUM7UUFDekMscUNBQXFDO1FBQzdCLHFCQUFnQixHQUFHLElBQUEsbUNBQW1CLEdBQVUsQ0FBQztRQTg1QnpELE9BQU87UUFDUCxhQUFRLEdBQUc7WUFDUCxnQ0FBZ0MsRUFBRSxHQUFHLEVBQUU7Z0JBQ25DLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixDQUFDO1NBQ0osQ0FBQTtJQXFFTCxDQUFDO0lBdCtCRyxLQUFLLENBQUMsSUFBSTtRQUNOLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRCw4QkFB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cUJBQXFCLEdBQUcsR0FBRyxDQUFDO1lBRWxDLGFBQWE7WUFDYixJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsRUFBRSxDQUFDO2dCQUM5QyxTQUFTO2dCQUNULE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3ZFLE9BQU8sUUFBUSxZQUFZLEVBQUUsQ0FBQztZQUNsQyxDQUFDO1lBRUQsd0JBQXdCO1lBQ3hCLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxVQUFVLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZFLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2pFLElBQUksV0FBVyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLE1BQU0sZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQy9ELE9BQU8sUUFBUSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN0QyxDQUFDO1lBQ0wsQ0FBQztZQUVELElBQUksQ0FBQyxJQUFJLENBQUMsK0JBQStCLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDdkQsT0FBTyxVQUFVLENBQUM7UUFDdEIsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsS0FBSyxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZDLE9BQU8sVUFBVSxDQUFDO1FBQ3RCLENBQUM7SUFDTCxDQUFDO0NBQ0o7QUFFWSxRQUFBLGlCQUFpQixHQUFHLElBQUksaUJBQWlCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcclxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcclxuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xyXG5pbXBvcnQge1xyXG4gICAgY3JlYXRlTWVtYmVyc2hpcFNldCxcclxuICAgIG1lbWJlcnNoaXBBZGQsXHJcbiAgICBtZW1iZXJzaGlwQ2xlYXIsXHJcbiAgICBtZW1iZXJzaGlwRnJvbUFycmF5LFxyXG4gICAgbWVtYmVyc2hpcFRvQXJyYXksXHJcbn0gZnJvbSAnLi9NZW1iZXJzaGlwU2V0JztcclxuXHJcbi8qKiDlhoXnva4geGxzeCDlupPvvIzml6DpnIAgbnBtIGluc3RhbGwgKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcclxuY29uc3QgWExTWCA9IHJlcXVpcmUocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2xpYi94bHN4LmpzJykpO1xyXG5cclxuaW50ZXJmYWNlIFBsdWdpbkNvbmZpZ0ZpbGUge1xyXG4gICAgZXhjZWxQYXRoOiBzdHJpbmc7XHJcbiAgICBqc29uRXhwb3J0UGF0aDogc3RyaW5nO1xyXG4gICAgLyoqIOivreiogOihqCBsYW5nXyog5a+85Ye65qC555uu5b2V77yM5a6e6ZmF6Lev5b6E5Li6IGB7bGFuZ0pzb25FeHBvcnRQYXRofS9sYW5nX3h4L2NvbmZpZy9gICovXHJcbiAgICBsYW5nSnNvbkV4cG9ydFBhdGg6IHN0cmluZztcclxuICAgIHRzRXhwb3J0UGF0aDogc3RyaW5nO1xyXG4gICAgYXV0b0V4cG9ydDogYm9vbGVhbjtcclxufVxyXG5cclxuaW50ZXJmYWNlIFBsdWdpbkNvbmZpZyBleHRlbmRzIFBsdWdpbkNvbmZpZ0ZpbGUge1xyXG4gICAgd2F0Y2hlcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsO1xyXG59XHJcblxyXG5jb25zdCBERUZBVUxUX0NPTkZJRzogUGx1Z2luQ29uZmlnRmlsZSA9IHtcclxuICAgIGV4Y2VsUGF0aDogJ+mFjee9ruihqC9leGNlbExpc3QnLFxyXG4gICAganNvbkV4cG9ydFBhdGg6ICdhc3NldHMvYnVuZGxlcy9maXJzdC9jb25maWcnLFxyXG4gICAgbGFuZ0pzb25FeHBvcnRQYXRoOiAnYXNzZXRzL2J1bmRsZXMvbGFuZycsXHJcbiAgICB0c0V4cG9ydFBhdGg6ICdhc3NldHMvc2NyaXB0L2ludGVyZmFjZScsXHJcbiAgICBhdXRvRXhwb3J0OiB0cnVlLFxyXG59O1xyXG5cclxuY2xhc3MgRXhjZWxUb0pzb25QbHVnaW4ge1xyXG4gICAgcHJpdmF0ZSBjb25maWc6IFBsdWdpbkNvbmZpZyA9IHsgLi4uREVGQVVMVF9DT05GSUcsIHdhdGNoZXI6IG51bGwgfTtcclxuXHJcbiAgICBwcml2YXRlIGZpbGVXYXRjaGVyOiBmcy5GU1dhdGNoZXIgfCBudWxsID0gbnVsbDtcclxuICAgIHByaXZhdGUgaXNFeHBvcnRpbmcgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgZXhwb3J0UXVldWU6ICgoKSA9PiB2b2lkKVtdID0gW107XHJcbiAgICAvKiog5pys5qyh5a+85Ye65YaZ5YWl6L+H55qEIEpTT04g55uu5b2V77yM55So5LqO5Yi35pawIGFzc2V0LWRiICovXHJcbiAgICBwcml2YXRlIGpzb25SZWZyZXNoUGF0aHMgPSBjcmVhdGVNZW1iZXJzaGlwU2V0PHN0cmluZz4oKTtcclxuXHJcbiAgICBhc3luYyBsb2FkKCkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuZXhwb3J0QWxsRXhjZWwoKTtcclxuICAgICAgICB0aGlzLnNldHVwRmlsZVdhdGNoZXIoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiog5o+S5Lu25qC555uu5b2V77yIY29uZmlnLmpzb24g5omA5Zyo55uu5b2V77yJICovXHJcbiAgICBwcml2YXRlIGdldFBsdWdpblJvb3QoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIOWwhiBjb25maWcuanNvbiDkuK3nmoTnm7jlr7not6/lvoTop6PmnpDkuLrnu53lr7not6/lvoTvvIjnm7jlr7npobnnm67moLnnm67lvZXvvIkgKi9cclxuICAgIHByaXZhdGUgcmVzb2x2ZVByb2plY3RQYXRoKHJlbGF0aXZlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBwcm9qZWN0Um9vdCA9IEVkaXRvci5Qcm9qZWN0LnBhdGg7XHJcbiAgICAgICAgcmV0dXJuIHBhdGgubm9ybWFsaXplKHBhdGguam9pbihwcm9qZWN0Um9vdCwgcmVsYXRpdmVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKS5yZXBsYWNlKC9eXFwuXFwvLywgJycpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIOWIpOaWreW3peS9nOihqOaYr+WQpumcgOimgeWvvOWHuu+8muagvOW8j+S4uiBcIuaPj+i/sHxqc29u5paH5Lu25ZCNXCLvvIzkuJTpnZ7pu5jorqQgU2hlZXQgKi9cclxuICAgIHByaXZhdGUgaXNFeHBvcnRhYmxlU2hlZXQoc2hlZXROYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoIXNoZWV0TmFtZSB8fCBzaGVldE5hbWUuc3RhcnRzV2l0aCgnU2hlZXQnKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHBhcnRzID0gc2hlZXROYW1lLnNwbGl0KCd8Jyk7XHJcbiAgICAgICAgcmV0dXJuIHBhcnRzLmxlbmd0aCA+PSAyICYmIHBhcnRzWzFdLnRyaW0oKS5sZW5ndGggPiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiDojrflj5blt6XkvZzooajlr7zlh7rnmoQganNvbiDmlofku7blkI3vvIh8IOWQjuesrOS4gOaute+8iSAqL1xyXG4gICAgcHJpdmF0ZSBnZXRTaGVldEV4cG9ydE5hbWUoc2hlZXROYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBzaGVldE5hbWUuc3BsaXQoJ3wnKVsxXS50cmltKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIOivreiogOihqO+8mmxhbmdfY24gLyBsYW5nX2VuIOKApiAqL1xyXG4gICAgcHJpdmF0ZSBpc0xhbmdFeHBvcnROYW1lKGV4cG9ydE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAvXmxhbmdfW2Etel17Mn0kL2kudGVzdChleHBvcnROYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiog6Kej5p6QIEpTT04g5a+85Ye655uu5b2V77yI6K+t6KiA6KGo6L+b5a+55bqU6K+t6KiA5YyFIGJ1bmRsZe+8iSAqL1xyXG4gICAgcHJpdmF0ZSByZXNvbHZlSnNvbkV4cG9ydERpcihleHBvcnROYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICh0aGlzLmlzTGFuZ0V4cG9ydE5hbWUoZXhwb3J0TmFtZSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHBhdGguam9pbih0aGlzLmNvbmZpZy5sYW5nSnNvbkV4cG9ydFBhdGgsIGV4cG9ydE5hbWUsICdjb25maWcnKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmpzb25FeHBvcnRQYXRoO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiDmuIXnkIYgZmlyc3Qg5Lit6YGX55WZ55qE6K+t6KiA6KGoIEpTT07vvIjljoblj7Lot6/lvoTvvIkgKi9cclxuICAgIHByaXZhdGUgcmVtb3ZlU3RhbGVMYW5nSnNvbkluRmlyc3QoanNvbkZpbGVOYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBzdGFsZVBhdGggPSBwYXRoLmpvaW4odGhpcy5jb25maWcuanNvbkV4cG9ydFBhdGgsIGpzb25GaWxlTmFtZSk7XHJcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoc3RhbGVQYXRoKSkge1xyXG4gICAgICAgICAgICBmcy51bmxpbmtTeW5jKHN0YWxlUGF0aCk7XHJcbiAgICAgICAgICAgIHRoaXMubG9nKGBbRXhjZWzmj5Lku7ZdIOW3suWIoOmZpCBmaXJzdCDkuK3pgZfnlZnor63oqIDooag6ICR7anNvbkZpbGVOYW1lfWApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBzdGFsZU1ldGEgPSBgJHtzdGFsZVBhdGh9Lm1ldGFgO1xyXG4gICAgICAgIGlmIChmcy5leGlzdHNTeW5jKHN0YWxlTWV0YSkpIHtcclxuICAgICAgICAgICAgZnMudW5saW5rU3luYyhzdGFsZU1ldGEpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB1bmxvYWQoKSB7XHJcbiAgICAgICAgdGhpcy5sb2coJ1tFeGNlbOaPkuS7tl0g5o+S5Lu25bey5Y246L29Jyk7XHJcbiAgICAgICAgdGhpcy5zdG9wRmlsZVdhdGNoZXIoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiog5LuO5o+S5Lu25qC555uu5b2VIGNvbmZpZy5qc29uIOWKoOi9vemFjee9ru+8jOi3r+W+hOebuOWvuemhueebruagueebruW9lSAqL1xyXG4gICAgbG9hZENvbmZpZygpIHtcclxuICAgICAgICBjb25zdCBjb25maWdQYXRoID0gcGF0aC5qb2luKHRoaXMuZ2V0UGx1Z2luUm9vdCgpLCAnY29uZmlnLmpzb24nKTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoY29uZmlnUGF0aCkpIHtcclxuICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmMoY29uZmlnUGF0aCwgSlNPTi5zdHJpbmdpZnkoREVGQVVMVF9DT05GSUcsIG51bGwsIDQpLCAndXRmLTgnKTtcclxuICAgICAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDlt7LliJvlu7rpu5jorqTphY3nva7mlofku7Y6ICR7Y29uZmlnUGF0aH1gKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgcmF3ID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoY29uZmlnUGF0aCwgJ3V0Zi04JykpIGFzIFBhcnRpYWw8UGx1Z2luQ29uZmlnRmlsZT47XHJcbiAgICAgICAgICAgIGNvbnN0IG1lcmdlZCA9IHsgLi4uREVGQVVMVF9DT05GSUcsIC4uLnJhdyB9O1xyXG5cclxuICAgICAgICAgICAgdGhpcy5jb25maWcuZXhjZWxQYXRoID0gdGhpcy5yZXNvbHZlUHJvamVjdFBhdGgobWVyZ2VkLmV4Y2VsUGF0aCk7XHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmpzb25FeHBvcnRQYXRoID0gdGhpcy5yZXNvbHZlUHJvamVjdFBhdGgobWVyZ2VkLmpzb25FeHBvcnRQYXRoKTtcclxuICAgICAgICAgICAgdGhpcy5jb25maWcubGFuZ0pzb25FeHBvcnRQYXRoID0gdGhpcy5yZXNvbHZlUHJvamVjdFBhdGgoXHJcbiAgICAgICAgICAgICAgICBtZXJnZWQubGFuZ0pzb25FeHBvcnRQYXRoID8/IERFRkFVTFRfQ09ORklHLmxhbmdKc29uRXhwb3J0UGF0aCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgdGhpcy5jb25maWcudHNFeHBvcnRQYXRoID0gdGhpcy5yZXNvbHZlUHJvamVjdFBhdGgobWVyZ2VkLnRzRXhwb3J0UGF0aCk7XHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dG9FeHBvcnQgPSBtZXJnZWQuYXV0b0V4cG9ydDtcclxuXHJcbiAgICAgICAgICAgIHRoaXMubG9nKCdbRXhjZWzmj5Lku7ZdIOmFjee9ruW3suWKoOi9vSAoZXh0ZW5zaW9ucy9leGNlbC10by1qc29uLXRzL2NvbmZpZy5qc29uKScpO1xyXG4gICAgICAgICAgICB0aGlzLmxvZyhgW0V4Y2Vs5o+S5Lu2XSBleGNlbFBhdGg6ICR7dGhpcy5jb25maWcuZXhjZWxQYXRofWApO1xyXG4gICAgICAgICAgICB0aGlzLmxvZyhgW0V4Y2Vs5o+S5Lu2XSBqc29uUGF0aDogJHt0aGlzLmNvbmZpZy5qc29uRXhwb3J0UGF0aH1gKTtcclxuICAgICAgICAgICAgdGhpcy5sb2coYFtFeGNlbOaPkuS7tl0gbGFuZ0pzb25QYXRoOiAke3RoaXMuY29uZmlnLmxhbmdKc29uRXhwb3J0UGF0aH1gKTtcclxuICAgICAgICAgICAgdGhpcy5sb2coYFtFeGNlbOaPkuS7tl0gdHNQYXRoOiAke3RoaXMuY29uZmlnLnRzRXhwb3J0UGF0aH1gKTtcclxuICAgICAgICAgICAgdGhpcy5sb2coYFtFeGNlbOaPkuS7tl0gYXV0b0V4cG9ydDogJHt0aGlzLmNvbmZpZy5hdXRvRXhwb3J0fWApO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgICAgICB0aGlzLmVycm9yKGBbRXhjZWzmj5Lku7ZdIOWKoOi9vemFjee9ruWksei0pSAoJHtjb25maWdQYXRofSk6ICR7ZXJyfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyDmiYvliqjlr7zlh7pcclxuICAgIGV4cG9ydE1hbnVhbCgpIHtcclxuICAgICAgICB0aGlzLmV4cG9ydEFsbEV4Y2VsKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5a+85Ye65omA5pyJRXhjZWzvvIjlop7lvLrlgaXlo67mgKfvvIlcclxuICAgIGFzeW5jIGV4cG9ydEFsbEV4Y2VsKCkge1xyXG4gICAgICAgIHRoaXMubG9hZENvbmZpZygpO1xyXG5cclxuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmV4Y2VsUGF0aCkge1xyXG4gICAgICAgICAgICB0aGlzLmVycm9yKCdbRXhjZWzmj5Lku7ZdIEV4Y2Vs55uu5b2V6Lev5b6E5pyq6YWN572uJyk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghZnMuZXhpc3RzU3luYyh0aGlzLmNvbmZpZy5leGNlbFBhdGgpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZXJyb3IoYFtFeGNlbOaPkuS7tl0gRXhjZWznm67lvZXkuI3lrZjlnKg6ICR7dGhpcy5jb25maWcuZXhjZWxQYXRofWApO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBtZW1iZXJzaGlwQ2xlYXIodGhpcy5qc29uUmVmcmVzaFBhdGhzKTtcclxuXHJcbiAgICAgICAgICAgIC8vIOehruS/neWvvOWHuuebruW9leWtmOWcqFxyXG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcuanNvbkV4cG9ydFBhdGggJiYgIWZzLmV4aXN0c1N5bmModGhpcy5jb25maWcuanNvbkV4cG9ydFBhdGgpKSB7XHJcbiAgICAgICAgICAgICAgICBmcy5ta2RpclN5bmModGhpcy5jb25maWcuanNvbkV4cG9ydFBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5sYW5nSnNvbkV4cG9ydFBhdGggJiYgIWZzLmV4aXN0c1N5bmModGhpcy5jb25maWcubGFuZ0pzb25FeHBvcnRQYXRoKSkge1xyXG4gICAgICAgICAgICAgICAgZnMubWtkaXJTeW5jKHRoaXMuY29uZmlnLmxhbmdKc29uRXhwb3J0UGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnRzRXhwb3J0UGF0aCAmJiAhZnMuZXhpc3RzU3luYyh0aGlzLmNvbmZpZy50c0V4cG9ydFBhdGgpKSB7XHJcbiAgICAgICAgICAgICAgICBmcy5ta2RpclN5bmModGhpcy5jb25maWcudHNFeHBvcnRQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8g6I635Y+W55uu5b2V5Lit5omA5pyJRXhjZWzmlofku7ZcclxuICAgICAgICAgICAgY29uc3QgZXhjZWxGaWxlcyA9IHRoaXMuZ2V0RXhjZWxGaWxlc0luRGlyZWN0b3J5KHRoaXMuY29uZmlnLmV4Y2VsUGF0aCk7XHJcblxyXG4gICAgICAgICAgICBpZiAoZXhjZWxGaWxlcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDnm67lvZXkuK3msqHmnInmib7liLBFeGNlbOaWh+S7tjogJHt0aGlzLmNvbmZpZy5leGNlbFBhdGh9YCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMubG9nKGBbRXhjZWzmj5Lku7ZdIOaJvuWIsCAke2V4Y2VsRmlsZXMubGVuZ3RofSDkuKpFeGNlbOaWh+S7tmApO1xyXG5cclxuICAgICAgICAgICAgbGV0IHN1Y2Nlc3NDb3VudCA9IDA7XHJcbiAgICAgICAgICAgIGxldCBlcnJvckNvdW50ID0gMDtcclxuXHJcbiAgICAgICAgICAgIC8vIOWkhOeQhuavj+S4qkV4Y2Vs5paH5Lu2XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgZXhjZWxGaWxlIG9mIGV4Y2VsRmlsZXMpIHtcclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzRXhjZWxGaWxlKGV4Y2VsRmlsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NvdW50Kys7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9yKGBbRXhjZWzmj5Lku7ZdIOWkhOeQhuaWh+S7tuWksei0pSAke3BhdGguYmFzZW5hbWUoZXhjZWxGaWxlKX06ICR7ZXJyfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHN1Y2Nlc3NDb3VudCA+IDApIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaEFzc2V0RGF0YWJhc2UoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3VjY2VzcyhgW0V4Y2Vs5o+S5Lu2XSDlr7zlh7rlrozmiJDvvIzmiJDlip/lpITnkIYgJHtzdWNjZXNzQ291bnR9IOS4quaWh+S7tu+8jOWksei0pSAke2Vycm9yQ291bnR9IOS4qmApO1xyXG5cclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IoYFtFeGNlbOaPkuS7tl0g5a+85Ye65aSx6LSl77yM5rKh5pyJ5oiQ5Yqf5aSE55CG5Lu75L2V5paH5Lu2YCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgdGhpcy5lcnJvcihgW0V4Y2Vs5o+S5Lu2XSDlr7zlh7rlpLHotKU6ICR7ZXJyfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcblxyXG4gICAgLy8g6I635Y+W55uu5b2V5Lit55qE5omA5pyJRXhjZWzmlofku7ZcclxuICAgIGdldEV4Y2VsRmlsZXNJbkRpcmVjdG9yeShkaXJQYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XHJcbiAgICAgICAgcmV0dXJuIGZzLnJlYWRkaXJTeW5jKGRpclBhdGgpXHJcbiAgICAgICAgICAgIC5maWx0ZXIoZmlsZSA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyDov4fmu6TpmpDol4/mlofku7bvvIjku6XngrnlvIDlpLTnmoTmlofku7bvvIlcclxuICAgICAgICAgICAgICAgIGlmIChmaWxlLnN0YXJ0c1dpdGgoJy4nKSB8fCBmaWxlLnN0YXJ0c1dpdGgoJ34nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNvbnN0IGV4dCA9IHBhdGguZXh0bmFtZShmaWxlKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChleHQgPT09ICcueGxzeCcgfHwgZXh0ID09PSAnLnhscycpICYmXHJcbiAgICAgICAgICAgICAgICAgICAgZnMuc3RhdFN5bmMocGF0aC5qb2luKGRpclBhdGgsIGZpbGUpKS5pc0ZpbGUoKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLm1hcChmaWxlID0+IHBhdGguam9pbihkaXJQYXRoLCBmaWxlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5aSE55CG5Y2V5LiqRXhjZWzmlofku7ZcclxuICAgIHByb2Nlc3NFeGNlbEZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIC8vIOWuieWFqOivu+WPluaJk+W8gOeKtuaAgeeahEV4Y2Vs5paH5Lu2XHJcbiAgICAgICAgICAgIGNvbnN0IHdvcmtib29rID0gdGhpcy5yZWFkRXhjZWxTYWZlbHkoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgICBjb25zdCBzaGVldE5hbWVzID0gd29ya2Jvb2suU2hlZXROYW1lcztcclxuXHJcbiAgICAgICAgICAgIC8vIOWvvOWHuuavj+S4quW3peS9nOihqFxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNoZWV0TmFtZSBvZiBzaGVldE5hbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNFeHBvcnRhYmxlU2hlZXQoc2hlZXROYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5leHBvcnRTaGVldCh3b3JrYm9vaywgc2hlZXROYW1lLCBmaWxlUGF0aCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDlpITnkIbmlofku7YgJHtwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKX0g5aSx6LSlOiAke2Vycn1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIOS7jiBidWZmZXIg6Kej5p6QIEV4Y2Vs77yM6YG/5YWNIHJlYWRGaWxlIOWcqCBXaW5kb3dzIOS4reaWh+i3r+W+hOS4i+Wksei0pSAqL1xyXG4gICAgcHJpdmF0ZSBwYXJzZUV4Y2VsQnVmZmVyKGJ1ZmZlcjogQnVmZmVyKTogYW55IHtcclxuICAgICAgICByZXR1cm4gWExTWC5yZWFkKGJ1ZmZlciwgeyB0eXBlOiAnYnVmZmVyJyB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiog6K+75Y+WIEV4Y2Vs77ya5LyY5YWI55u05o6l6K+777yM5aSx6LSl5pe25aSN5Yi25YiwIEFTQ0lJIOS4tOaXtuaWh+S7tuWGjeivuyAqL1xyXG4gICAgcmVhZEV4Y2VsU2FmZWx5KGZpbGVQYXRoOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgICAgIC8vIDEuIOebtOaOpeivu+WPlu+8iOaWh+S7tuacquWNoOeUqOaXtuacgOW/q++8iVxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCk7XHJcbiAgICAgICAgICAgIGlmIChidWZmZXIubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VFeGNlbEJ1ZmZlcihidWZmZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBjYXRjaCAoZGlyZWN0RXJyKSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDnm7TmjqXor7vlj5blpLHotKXvvIzlsJ3or5XlpI3liLblkI7or7vlj5Y6ICR7cGF0aC5iYXNlbmFtZShmaWxlUGF0aCl9ICgke2RpcmVjdEVycn0pYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyAyLiDlpI3liLbliLDnuq8gQVNDSUkg5Li05pe26Lev5b6E77yI6YG/5YWN5Lit5paH5paH5Lu25ZCN5a+86Ie0IHhsc3gg5bqT5peg5rOV6K6/6Zeu77yJXHJcbiAgICAgICAgY29uc3QgdGVtcFBhdGggPSBwYXRoLmpvaW4ob3MudG1wZGlyKCksIGBleGNlbC10ZW1wLSR7RGF0ZS5ub3coKX0tJHtwcm9jZXNzLnBpZH0ueGxzeGApO1xyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBmcy5jb3B5RmlsZVN5bmMoZmlsZVBhdGgsIHRlbXBQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHRlbXBTdGF0cyA9IGZzLnN0YXRTeW5jKHRlbXBQYXRoKTtcclxuICAgICAgICAgICAgaWYgKHRlbXBTdGF0cy5zaXplID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ+S4tOaXtuaWh+S7tuWkp+Wwj+S4ujDvvIzlpI3liLblj6/og73mnKrlrozmiJAnKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gZnMucmVhZEZpbGVTeW5jKHRlbXBQYXRoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VFeGNlbEJ1ZmZlcihidWZmZXIpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg6K+75Y+WRXhjZWzlpLHotKU6ICR7ZXJyLm1lc3NhZ2UgfHwgZXJyfWApO1xyXG4gICAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyh0ZW1wUGF0aCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBmcy51bmxpbmtTeW5jKHRlbXBQYXRoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOaXoOazleWIoOmZpOS4tOaXtuaWh+S7tjogJHt0ZW1wUGF0aH0gLSAke2V9YCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5a+85Ye65Y2V5Liq5bel5L2c6KGoXHJcbiAgICBleHBvcnRTaGVldCh3b3JrYm9vazogYW55LCBzaGVldE5hbWU6IHN0cmluZywgZmlsZVBhdGg6IHN0cmluZykge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHdvcmtzaGVldCA9IHdvcmtib29rLlNoZWV0c1tzaGVldE5hbWVdO1xyXG4gICAgICAgICAgICBjb25zdCBqc29uRGF0YSA9IFhMU1gudXRpbHMuc2hlZXRfdG9fanNvbih3b3Jrc2hlZXQsIHsgaGVhZGVyOiAxIH0pO1xyXG5cclxuICAgICAgICAgICAgLy8g5qOA5p+l5piv5ZCm5pyJ6Laz5aSf55qE6KGo5aS06KGM77yI6Iez5bCRM+ihjO+8muWtl+auteWQjeOAgeexu+Wei+OAgeivtOaYju+8iVxyXG4gICAgICAgICAgICBpZiAoanNvbkRhdGEubGVuZ3RoIDwgMykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOW3peS9nOihqCBcIiR7c2hlZXROYW1lfVwiIOaVsOaNruS4jei2s++8jOi3s+i/h+WvvOWHuiAo5paH5Lu2OiAke3BhdGguYmFzZW5hbWUoZmlsZVBhdGgpfSnnmoQke3NoZWV0TmFtZX1gKTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzRXhwb3J0YWJsZVNoZWV0KHNoZWV0TmFtZSkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDlt6XkvZzooaggXCIke3NoZWV0TmFtZX1cIiDlkI3np7DmoLzlvI/plJnor6/vvIzot7Pov4flr7zlh7ogKOaWh+S7tjogJHtwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKX0pYCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNOYW1lID0gdGhpcy5nZXRTaGVldEV4cG9ydE5hbWUoc2hlZXROYW1lKTtcclxuXHJcbiAgICAgICAgICAgIC8vIOaPkOWPluihqOWktOS/oeaBr1xyXG4gICAgICAgICAgICBjb25zdCBoZWFkZXJzID0ge1xyXG4gICAgICAgICAgICAgICAgZmllbGRzOiBqc29uRGF0YVswXSxcclxuICAgICAgICAgICAgICAgIHR5cGVzOiBqc29uRGF0YVsxXSxcclxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uczoganNvbkRhdGFbMl1cclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIC8vIOS7juesrDTooYzlvIDlp4vmmK/mlbDmja5cclxuICAgICAgICAgICAgY29uc3QgZGF0YVJvd3MgPSBqc29uRGF0YS5zbGljZSgzKSBhcyBhbnlbXVtdO1xyXG5cclxuICAgICAgICAgICAgLy8g55Sf5oiQSlNPTuaVsOaNrlxyXG4gICAgICAgICAgICBjb25zdCBqc29uUmVzdWx0ID0gdGhpcy5nZW5lcmF0ZUpzb25EYXRhKGRhdGFSb3dzLCBoZWFkZXJzKTtcclxuXHJcbiAgICAgICAgICAgIC8vIOeUn+aIkFRT5o6l5Y+jXHJcbiAgICAgICAgICAgIGNvbnN0IHRzSW50ZXJmYWNlID0gdGhpcy5nZW5lcmF0ZVRTSW50ZXJmYWNlKHNOYW1lLCBoZWFkZXJzKTtcclxuXHJcbiAgICAgICAgICAgIC8vIOeUn+aIkOaWh+S7tuWQjVxyXG4gICAgICAgICAgICBjb25zdCBzYWZlU2hlZXROYW1lID0gdGhpcy5tYWtlU2FmZUZpbGVOYW1lKHNOYW1lKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGpzb25GaWxlTmFtZSA9IGAke3NhZmVTaGVldE5hbWV9Lmpzb25gO1xyXG4gICAgICAgICAgICAvL2NvbnN0IHRzRmlsZU5hbWUgPSBgSVRhYmxlJHtzYWZlU2hlZXROYW1lfS50c2A7XHJcbiAgICAgICAgICAgIGNvbnN0IHRzRmlsZU5hbWUgPSBgQXV0b1RhYmxlLnRzYDtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGpzb25FeHBvcnREaXIgPSB0aGlzLnJlc29sdmVKc29uRXhwb3J0RGlyKHNOYW1lKTtcclxuICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGpzb25FeHBvcnREaXIpKSB7XHJcbiAgICAgICAgICAgICAgICBmcy5ta2RpclN5bmMoanNvbkV4cG9ydERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIOWGmeWFpUpTT07mlofku7ZcclxuICAgICAgICAgICAgaWYgKGpzb25FeHBvcnREaXIpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGpzb25QYXRoID0gcGF0aC5qb2luKGpzb25FeHBvcnREaXIsIGpzb25GaWxlTmFtZSk7XHJcbiAgICAgICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKGpzb25QYXRoLCBKU09OLnN0cmluZ2lmeShqc29uUmVzdWx0LCBudWxsLCA0KSwgJ3V0Zi04Jyk7XHJcbiAgICAgICAgICAgICAgICBtZW1iZXJzaGlwQWRkKHRoaXMuanNvblJlZnJlc2hQYXRocywganNvbkV4cG9ydERpcik7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0xhbmdFeHBvcnROYW1lKHNOYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlU3RhbGVMYW5nSnNvbkluRmlyc3QoanNvbkZpbGVOYW1lKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8g5YaZ5YWlVFPmlofku7ZcclxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnRzRXhwb3J0UGF0aCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdHNQYXRoID0gcGF0aC5qb2luKHRoaXMuY29uZmlnLnRzRXhwb3J0UGF0aCwgdHNGaWxlTmFtZSk7XHJcbiAgICAgICAgICAgICAgICBsZXQgdHNDb250ZW50ID0gXCJcIjtcclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmModHNQYXRoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0c0NvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmModHNQYXRoLCAndXRmLTgnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLndhcm4oYFtFeGNlbOaPkuS7tl0g6K+75Y+WVFPmlofku7blpLHotKU6ICR7ZXJyfWApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKHRzQ29udGVudCA9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdHNDb250ZW50ID0gXCJkZWNsYXJlIGdsb2JhbCB7XFxuXFxufVxcbmV4cG9ydCB7IH07XCI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5leHRyYWN0RnVsbEludGVyZmFjZUJsb2NrKHRzQ29udGVudCwgXCJJVGFibGVcIiArIHNOYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRzQ29udGVudCA9IHRoaXMucmVwbGFjZUludGVyZmFjZUJsb2NrKHRzQ29udGVudCwgXCJJVGFibGVcIiArIHNOYW1lLCB0c0ludGVyZmFjZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRzQ29udGVudCA9IHRzQ29udGVudC5yZXBsYWNlKC9cXH1cXHI/XFxuZXhwb3J0IFxceyBcXH07JC8sIHRzSW50ZXJmYWNlICsgXCJ9XFxuZXhwb3J0IHsgfTtcIik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0c0NvbnRlbnQgPSB0aGlzLm5vcm1hbGl6ZUF1dG9UYWJsZUJsYW5rTGluZXModHNDb250ZW50KTtcclxuICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmModHNQYXRoLCB0c0NvbnRlbnQsICd1dGYtOCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg5bel5L2c6KGoIFwiJHtzaGVldE5hbWV9XCIg5a+85Ye65aSx6LSlICjmlofku7Y6ICR7cGF0aC5iYXNlbmFtZShmaWxlUGF0aCl9KTogJHtlcnJ9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog6L2s5LmJ5q2j5YiZ54m55q6K5a2X56ymXHJcbiAgICAgKi9cclxuICAgIGVzY2FwZVJlZ0V4cChzdHI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog57K+5YeG5p+l5om+5o6l5Y+j5aOw5piO6KGM77yI5YWo5a2X5Yy56YWN77yJXHJcbiAgICAgKi9cclxuICAgIGZpbmRJbnRlcmZhY2VEZWNsYXJhdGlvbkxpbmUoZmlsZUNvbnRlbnQ6IHN0cmluZywgaW50ZXJmYWNlTmFtZTogc3RyaW5nKToge1xyXG4gICAgICAgIGxpbmVTdGFydDogbnVtYmVyO1xyXG4gICAgICAgIGxpbmVFbmQ6IG51bWJlcjtcclxuICAgICAgICBsaW5lQ29udGVudDogc3RyaW5nO1xyXG4gICAgfSB8IG51bGwge1xyXG4gICAgICAgIC8vIOS9v+eUqOWNleivjei+ueeVjCBcXGIg56Gu5L+d5YWo5a2X5Yy56YWNXHJcbiAgICAgICAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKFxyXG4gICAgICAgICAgICBgXFxcXGJpbnRlcmZhY2VcXFxccyske3RoaXMuZXNjYXBlUmVnRXhwKGludGVyZmFjZU5hbWUpfVxcXFxiKD86XFxcXHMqPFtePl0qPik/XFxcXHMqW1xcXFx7XFxcXG5dYCxcclxuICAgICAgICAgICAgJ2cnXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgbGV0IG1hdGNoO1xyXG4gICAgICAgIHdoaWxlICgobWF0Y2ggPSByZWdleC5leGVjKGZpbGVDb250ZW50KSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgLy8g5om+5Yiw5Yy56YWN5L2N572u77yM56Gu5a6a5a6M5pW06KGMXHJcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoU3RhcnQgPSBtYXRjaC5pbmRleDtcclxuXHJcbiAgICAgICAgICAgIC8vIOWQkeWJjeaJvuWIsOihjOW8gOWni1xyXG4gICAgICAgICAgICBjb25zdCBsaW5lU3RhcnQgPSBmaWxlQ29udGVudC5sYXN0SW5kZXhPZignXFxuJywgbWF0Y2hTdGFydCAtIDEpICsgMTtcclxuXHJcbiAgICAgICAgICAgIC8vIOWQkeWQjuaJvuWIsOihjOe7k+adn1xyXG4gICAgICAgICAgICBjb25zdCBsaW5lRW5kID0gZmlsZUNvbnRlbnQuaW5kZXhPZignXFxuJywgbWF0Y2hTdGFydCk7XHJcbiAgICAgICAgICAgIGNvbnN0IGFjdHVhbExpbmVFbmQgPSBsaW5lRW5kID09PSAtMSA/IGZpbGVDb250ZW50Lmxlbmd0aCA6IGxpbmVFbmQ7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBsaW5lQ29udGVudCA9IGZpbGVDb250ZW50LnN1YnN0cmluZyhsaW5lU3RhcnQsIGFjdHVhbExpbmVFbmQpO1xyXG5cclxuICAgICAgICAgICAgLy8g6aqM6K+B77ya56Gu5L+d6L+Z5LiA6KGM56Gu5a6e5piv5oiR5Lus55qE55uu5qCH5o6l5Y+jXHJcbiAgICAgICAgICAgIGlmIChsaW5lQ29udGVudC50cmltKCkuc3RhcnRzV2l0aChgaW50ZXJmYWNlICR7aW50ZXJmYWNlTmFtZX1gKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICBsaW5lU3RhcnQsXHJcbiAgICAgICAgICAgICAgICAgICAgbGluZUVuZDogYWN0dWFsTGluZUVuZCxcclxuICAgICAgICAgICAgICAgICAgICBsaW5lQ29udGVudFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDmj5Dlj5blrozmlbTnmoTmjqXlj6PlnZfvvIjljIXmi6zkuIrmlrnms6jph4rvvIlcclxuICAgICAqL1xyXG4gICAgZXh0cmFjdEZ1bGxJbnRlcmZhY2VCbG9jayhmaWxlQ29udGVudDogc3RyaW5nLCBpbnRlcmZhY2VOYW1lOiBzdHJpbmcpOiB7XHJcbiAgICAgICAgc3RhcnQ6IG51bWJlcjtcclxuICAgICAgICBlbmQ6IG51bWJlcjtcclxuICAgICAgICBjb250ZW50OiBzdHJpbmc7XHJcbiAgICB9IHwgbnVsbCB7XHJcbiAgICAgICAgY29uc3QgaW50ZXJmYWNlTGluZSA9IHRoaXMuZmluZEludGVyZmFjZURlY2xhcmF0aW9uTGluZShmaWxlQ29udGVudCwgaW50ZXJmYWNlTmFtZSk7XHJcbiAgICAgICAgaWYgKCFpbnRlcmZhY2VMaW5lKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gPT09IOWQkeWJjeafpeaJvui/nue7reeahOazqOmHiuWdlyA9PT1cclxuICAgICAgICBsZXQgYmxvY2tTdGFydCA9IGludGVyZmFjZUxpbmUubGluZVN0YXJ0O1xyXG4gICAgICAgIGxldCBjdXJyZW50UG9zID0gaW50ZXJmYWNlTGluZS5saW5lU3RhcnQ7XHJcblxyXG4gICAgICAgIHdoaWxlIChjdXJyZW50UG9zID4gMCkge1xyXG4gICAgICAgICAgICBjb25zdCBwcmV2TGluZUVuZCA9IGN1cnJlbnRQb3MgLSAxO1xyXG4gICAgICAgICAgICBjb25zdCBwcmV2TGluZVN0YXJ0ID0gZmlsZUNvbnRlbnQubGFzdEluZGV4T2YoJ1xcbicsIHByZXZMaW5lRW5kIC0gMSkgKyAxO1xyXG4gICAgICAgICAgICBjb25zdCBwcmV2TGluZSA9IGZpbGVDb250ZW50LnN1YnN0cmluZyhwcmV2TGluZVN0YXJ0LCBwcmV2TGluZUVuZCkudHJpbSgpO1xyXG5cclxuICAgICAgICAgICAgLy8g5qOA5p+l5piv5ZCm5Li65rOo6YeK6KGM5oiW56m66KGMXHJcbiAgICAgICAgICAgIGlmIChwcmV2TGluZSA9PT0gJycgfHxcclxuICAgICAgICAgICAgICAgIHByZXZMaW5lLnN0YXJ0c1dpdGgoJy8vJykgfHxcclxuICAgICAgICAgICAgICAgIHByZXZMaW5lLnN0YXJ0c1dpdGgoJy8qJykgfHxcclxuICAgICAgICAgICAgICAgIHByZXZMaW5lLnN0YXJ0c1dpdGgoJyonKSkge1xyXG4gICAgICAgICAgICAgICAgY3VycmVudFBvcyA9IHByZXZMaW5lU3RhcnQ7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBibG9ja1N0YXJ0ID0gY3VycmVudFBvcztcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoY3VycmVudFBvcyA9PT0gMCkge1xyXG4gICAgICAgICAgICBibG9ja1N0YXJ0ID0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vID09PSDlkJHlkI7mn6Xmib7mjqXlj6PkvZPnu5PmnZ8gPT09XHJcbiAgICAgICAgLy8g5om+5YiwIGludGVyZmFjZSDooYzkuK3nmoTlvIDmi6zlj7fkvY3nva5cclxuICAgICAgICBjb25zdCBvcGVuQnJhY2VJbmRleCA9IGludGVyZmFjZUxpbmUubGluZUNvbnRlbnQuaW5kZXhPZigneycpO1xyXG4gICAgICAgIGxldCBzdGFydFBvcyA9IGludGVyZmFjZUxpbmUubGluZVN0YXJ0O1xyXG4gICAgICAgIGxldCBicmFjZUNvdW50ID0gMDtcclxuXHJcbiAgICAgICAgaWYgKG9wZW5CcmFjZUluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgICAvLyDlvIDmi6zlj7flnKjlkIzkuIDooYxcclxuICAgICAgICAgICAgc3RhcnRQb3MgPSBpbnRlcmZhY2VMaW5lLmxpbmVTdGFydCArIG9wZW5CcmFjZUluZGV4O1xyXG4gICAgICAgICAgICBicmFjZUNvdW50ID0gMTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyDlvIDmi6zlj7flnKjkuIvkuIDooYzvvIzmib7liLDnrKzkuIDkuKoge1xyXG4gICAgICAgICAgICBjb25zdCBuZXh0T3BlbkJyYWNlID0gZmlsZUNvbnRlbnQuaW5kZXhPZigneycsIGludGVyZmFjZUxpbmUubGluZUVuZCk7XHJcbiAgICAgICAgICAgIGlmIChuZXh0T3BlbkJyYWNlID09PSAtMSkgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgICAgIHN0YXJ0UG9zID0gbmV4dE9wZW5CcmFjZTtcclxuICAgICAgICAgICAgYnJhY2VDb3VudCA9IDE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgcG9zID0gc3RhcnRQb3MgKyAxOyAvLyDot7Pov4cge1xyXG5cclxuICAgICAgICB3aGlsZSAocG9zIDwgZmlsZUNvbnRlbnQubGVuZ3RoICYmIGJyYWNlQ291bnQgPiAwKSB7XHJcbiAgICAgICAgICAgIGlmIChmaWxlQ29udGVudFtwb3NdID09PSAneycpIHtcclxuICAgICAgICAgICAgICAgIGJyYWNlQ291bnQrKztcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChmaWxlQ29udGVudFtwb3NdID09PSAnfScpIHtcclxuICAgICAgICAgICAgICAgIGJyYWNlQ291bnQtLTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBwb3MrKztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChicmFjZUNvdW50ICE9PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsOyAvLyDmi6zlj7fkuI3ljLnphY1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIOWQnuaOiSB9IOWQjue0p+i3n+eahOaNouihjO+8jOmBv+WFjeabv+aNouaXtiBuZXdCbG9jayDlho3luKYgXFxuIOWvvOiHtOepuuihjOe0r+WKoFxyXG4gICAgICAgIGxldCBibG9ja0VuZCA9IHBvcztcclxuICAgICAgICBpZiAoZmlsZUNvbnRlbnRbYmxvY2tFbmRdID09PSAnXFxyJykgYmxvY2tFbmQrKztcclxuICAgICAgICBpZiAoZmlsZUNvbnRlbnRbYmxvY2tFbmRdID09PSAnXFxuJykgYmxvY2tFbmQrKztcclxuXHJcbiAgICAgICAgY29uc3QgZnVsbENvbnRlbnQgPSBmaWxlQ29udGVudC5zdWJzdHJpbmcoYmxvY2tTdGFydCwgYmxvY2tFbmQpO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBzdGFydDogYmxvY2tTdGFydCxcclxuICAgICAgICAgICAgZW5kOiBibG9ja0VuZCxcclxuICAgICAgICAgICAgY29udGVudDogZnVsbENvbnRlbnRcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog5Y675o6J5o6l5Y+j5LmL6Ze0IC8gZGVjbGFyZSBnbG9iYWwg5pyr5bC+5aSa5L2Z56m66KGM77yI55Sf5oiQ5pe25piT57Sv5Yqg77yJXHJcbiAgICAgKi9cclxuICAgIG5vcm1hbGl6ZUF1dG9UYWJsZUJsYW5rTGluZXMoY29udGVudDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBsZXQgb3V0ID0gY29udGVudC5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpO1xyXG4gICAgICAgIC8vIOiLpeivr+W4puWFpeacquino+WGs+WGsueqge+8iOmAmuW4uOaYr+epuuihjCB2cyDml6DnqbrooYzvvInvvIzkuKLmjonlhrLnqoHmoIforrBcclxuICAgICAgICBvdXQgPSBvdXQucmVwbGFjZSgvXjw8PDw8PDwgLitcXG4oPzouKlxcbikqPz09PT09PT1cXG4oPzouKlxcbikqPz4+Pj4+Pj4gLitcXG4vZ20sICcnKTtcclxuICAgICAgICAvLyDmjqXlj6Pnu5PmnZ8gfSDlkI7lj6rkv53nlZnkuIDkuKrmjaLooYzvvIzlho3mjqXkuIvkuIDmjqXlj6Pms6jph4rmiJYgZ2xvYmFsIOe7k+adnyB9XHJcbiAgICAgICAgb3V0ID0gb3V0LnJlcGxhY2UoLyhcXG4gezR9XFx9KVxcbig/OlsgXFx0XSpcXG4pKyg/PVsgXFx0XSooPzpcXC9cXCpcXCp8XFx9KSkvZywgJyQxXFxuJyk7XHJcbiAgICAgICAgLy8g5paH5Lu25pyr5bC+IGV4cG9ydCDliY3kuZ/kuI3nlZnnqbrooYxcclxuICAgICAgICBvdXQgPSBvdXQucmVwbGFjZSgvXFxuKD86WyBcXHRdKlxcbikrKFxcfVxcbmV4cG9ydCBcXHsgXFx9OylcXHMqJC9nLCAnXFxuJDFcXG4nKTtcclxuICAgICAgICByZXR1cm4gb3V0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog5a6M5YWo5pu/5o2i5o6l5Y+j5Z2X77yI5YWo5a2X5Yy56YWN77yM57K+5YeG5pu/5o2i77yJXHJcbiAgICAgKi9cclxuICAgIHJlcGxhY2VJbnRlcmZhY2VCbG9jayhcclxuICAgICAgICBmaWxlQ29udGVudDogc3RyaW5nLFxyXG4gICAgICAgIGludGVyZmFjZU5hbWU6IHN0cmluZyxcclxuICAgICAgICBuZXdJbnRlcmZhY2VCbG9jazogc3RyaW5nXHJcbiAgICApOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGJsb2NrSW5mbyA9IHRoaXMuZXh0cmFjdEZ1bGxJbnRlcmZhY2VCbG9jayhmaWxlQ29udGVudCwgaW50ZXJmYWNlTmFtZSk7XHJcblxyXG4gICAgICAgIGlmICghYmxvY2tJbmZvKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg4p2MIOaOpeWPoyBcIiR7aW50ZXJmYWNlTmFtZX1cIiDmnKrmib7liLDvvIHor7fmo4Dmn6XlkI3np7DmmK/lkKbmraPnoa7jgIJgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIOmqjOivge+8muehruS/neaPkOWPlueahOWdl+ehruWunuWPquWMheWQq+ebruagh+aOpeWPo1xyXG4gICAgICAgIGNvbnN0IGludGVyZmFjZUxpbmVzID0gYmxvY2tJbmZvLmNvbnRlbnQuc3BsaXQoJ1xcbicpO1xyXG4gICAgICAgIGNvbnN0IGludGVyZmFjZURlY2xMaW5lcyA9IGludGVyZmFjZUxpbmVzLmZpbHRlcihsaW5lID0+XHJcbiAgICAgICAgICAgIGxpbmUudHJpbSgpLnN0YXJ0c1dpdGgoJ2ludGVyZmFjZSAnKVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGlmIChpbnRlcmZhY2VEZWNsTGluZXMubGVuZ3RoICE9PSAxKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg4p2MIOaJvuWIsOWkmuS4qiBpbnRlcmZhY2Ug5aOw5piO77yM5Y+v6IO95Yy56YWN6ZSZ6K+v77yBYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWludGVyZmFjZURlY2xMaW5lc1swXS5pbmNsdWRlcyhgaW50ZXJmYWNlICR7aW50ZXJmYWNlTmFtZX1gKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOKdjCDljLnphY3liLDplJnor6/nmoTmjqXlj6PlkI3np7DvvIFgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vY29uc29sZS5sb2coYOKchSDnsr7lh4bljLnphY3liLDmjqXlj6MgXCIke2ludGVyZmFjZU5hbWV9XCJgKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgZmlsZUNvbnRlbnQuc3Vic3RyaW5nKDAsIGJsb2NrSW5mby5zdGFydCkgK1xyXG4gICAgICAgICAgICBuZXdJbnRlcmZhY2VCbG9jayArXHJcbiAgICAgICAgICAgIGZpbGVDb250ZW50LnN1YnN0cmluZyhibG9ja0luZm8uZW5kKVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g6K6+572u5paH5Lu255uR5ZCsXHJcbiAgICBzZXR1cEZpbGVXYXRjaGVyKCkge1xyXG4gICAgICAgIHRoaXMuc3RvcEZpbGVXYXRjaGVyKCk7XHJcbiAgICAgICAgdGhpcy5sb2FkQ29uZmlnKCk7XHJcblxyXG4gICAgICAgIGlmICghdGhpcy5jb25maWcuYXV0b0V4cG9ydCkge1xyXG4gICAgICAgICAgICB0aGlzLmxvZygnW0V4Y2Vs5o+S5Lu2XSDoh6rliqjlr7zlh7rlt7LlhbPpl63vvIzot7Pov4fmlofku7bnm5HlkKwnKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5leGNlbFBhdGgpIHJldHVybjtcclxuXHJcbiAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHRoaXMuY29uZmlnLmV4Y2VsUGF0aCkpIHtcclxuICAgICAgICAgICAgdGhpcy5lcnJvcihgW0V4Y2Vs5o+S5Lu2XSDnm5HlkKznm67lvZXkuI3lrZjlnKg6ICR7dGhpcy5jb25maWcuZXhjZWxQYXRofWApO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAvLyDkvb/nlKjmm7Tlj6/pnaDnmoTnm5HlkKzmlrnlvI9cclxuICAgICAgICAgICAgdGhpcy5maWxlV2F0Y2hlciA9IGZzLndhdGNoKHRoaXMuY29uZmlnLmV4Y2VsUGF0aCwge1xyXG4gICAgICAgICAgICAgICAgcmVjdXJzaXZlOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcclxuICAgICAgICAgICAgfSwgYXN5bmMgKGV2ZW50VHlwZSwgZmlsZW5hbWUpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICghZmlsZW5hbWUpIHJldHVybjtcclxuICAgICAgICAgICAgICAgIHRoaXMubG9hZENvbmZpZygpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5hdXRvRXhwb3J0KSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICAgICAgLy8g56Gu5L+d5piv5a2X56ym5LiyXHJcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlTmFtZVN0ciA9IHR5cGVvZiBmaWxlbmFtZSA9PT0gJ3N0cmluZycgPyBmaWxlbmFtZSA6IGZpbGVuYW1lICsgXCJcIjtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGV4dCA9IHBhdGguZXh0bmFtZShmaWxlTmFtZVN0cikudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoZXh0ID09PSAnLnhsc3gnIHx8IGV4dCA9PT0gJy54bHMnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4odGhpcy5jb25maWcuZXhjZWxQYXRoLCBmaWxlTmFtZVN0cik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIOmineWklumqjOivge+8muehruS/neaYr+aWh+S7tuS4lOWtmOWcqFxyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcy5leGlzdHNTeW5jKGZpbGVQYXRoKSAmJiBmcy5zdGF0U3luYyhmaWxlUGF0aCkuaXNGaWxlKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKGBbRXhjZWzmj5Lku7ZdIOajgOa1i+WIsOaWh+S7tuWPmOabtDogJHtmaWxlTmFtZVN0cn0gKCR7ZXZlbnRUeXBlfSlgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDkvb/nlKjnu4jmnoHph43or5XmnLrliLZcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOmHjeivleasoeaVsOWinuWKoOWIsDjvvIzln7rnoYDlu7bov58x56eSXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NFeGNlbEZpbGVXaXRoUmV0cnkoZmlsZVBhdGgsIDgsIDEwMDApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDpqozor4Hmlofku7bnirbmgIHml7blh7rplJk6ICR7ZXJyfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAvLyDlpITnkIbnm5HlkKzplJnor69cclxuICAgICAgICAgICAgaWYgKHRoaXMuZmlsZVdhdGNoZXIgJiYgdHlwZW9mIHRoaXMuZmlsZVdhdGNoZXIub24gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZmlsZVdhdGNoZXIub24oJ2Vycm9yJywgKGVycm9yOiBFcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IoYFtFeGNlbOaPkuS7tl0g5paH5Lu255uR5ZCs6ZSZ6K+vOiAke2Vycm9yfWApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyDlsJ3or5Xph43mlrDorr7nva7nm5HlkKxcclxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9wRmlsZVdhdGNoZXIoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR1cEZpbGVXYXRjaGVyKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSwgMTUwMDApO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMubG9nKCdbRXhjZWzmj5Lku7ZdIOW3suWQr+WKqEV4Y2Vs55uu5b2V55uR5ZCs77yI57uI5p6B54mI77yJJyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZXJyb3IoYFtFeGNlbOaPkuS7tl0g55uu5b2V55uR5ZCs5aSx6LSlOiAke2Vycn1gKTtcclxuXHJcbiAgICAgICAgICAgIC8vIOWwneivlemHjeaWsOiuvue9ruebkeWQrFxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc3RvcEZpbGVXYXRjaGVyKCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldHVwRmlsZVdhdGNoZXIoKTtcclxuICAgICAgICAgICAgfSwgMjAwMDApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyDluKbph43or5XmnLrliLblpITnkIZFeGNlbOaWh+S7tu+8iOiHquWKqOWvvOWHuu+8iVxyXG4gICAgcHJvY2Vzc0V4Y2VsRmlsZVdpdGhSZXRyeShmaWxlUGF0aDogc3RyaW5nLCBtYXhSZXRyaWVzOiBudW1iZXIgPSA4LCBiYXNlRGVsYXk6IG51bWJlciA9IDEwMDApIHtcclxuICAgICAgICB0aGlzLmVucXVldWVFeHBvcnQoKCkgPT4gdGhpcy5wcm9jZXNzRXhjZWxGaWxlV2l0aFJldHJ5SW50ZXJuYWwoZmlsZVBhdGgsIG1heFJldHJpZXMsIGJhc2VEZWxheSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiDkuLLooYzmiafooYzlr7zlh7rvvIzpgb/lhY3lubblj5HlhpkgQXV0b1RhYmxlLnRzICovXHJcbiAgICBwcml2YXRlIGVucXVldWVFeHBvcnQodGFzazogKCkgPT4gdm9pZCkge1xyXG4gICAgICAgIHRoaXMuZXhwb3J0UXVldWUucHVzaCh0YXNrKTtcclxuICAgICAgICBpZiAoIXRoaXMuaXNFeHBvcnRpbmcpIHtcclxuICAgICAgICAgICAgdGhpcy5ydW5OZXh0RXhwb3J0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcnVuTmV4dEV4cG9ydCgpIHtcclxuICAgICAgICBjb25zdCB0YXNrID0gdGhpcy5leHBvcnRRdWV1ZS5zaGlmdCgpO1xyXG4gICAgICAgIGlmICghdGFzaykge1xyXG4gICAgICAgICAgICB0aGlzLmlzRXhwb3J0aW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5pc0V4cG9ydGluZyA9IHRydWU7XHJcbiAgICAgICAgdGFzaygpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgcHJvY2Vzc0V4Y2VsRmlsZVdpdGhSZXRyeUludGVybmFsKGZpbGVQYXRoOiBzdHJpbmcsIG1heFJldHJpZXM6IG51bWJlciA9IDgsIGJhc2VEZWxheTogbnVtYmVyID0gMTAwMCkge1xyXG4gICAgICAgIGxldCBhdHRlbXB0ID0gMDtcclxuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xyXG5cclxuICAgICAgICBjb25zdCB0cnlQcm9jZXNzID0gKCkgPT4ge1xyXG4gICAgICAgICAgICBhdHRlbXB0Kys7XHJcbiAgICAgICAgICAgIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xyXG4gICAgICAgICAgICBjb25zdCBkZWxheSA9IGJhc2VEZWxheSAqIE1hdGgubWluKDEuNSAqKiAoYXR0ZW1wdCAtIDEpLCA0KTsgLy8g5oyH5pWw6YCA6YG/77yM5L2G5LiK6ZmQ5Li6NOWAjeWfuuehgOW7tui/n1xyXG5cclxuICAgICAgICAgICAgdGhpcy5sb2coYFtFeGNlbOaPkuS7tl0g5aSE55CG5paH5Lu2IFwiJHtwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKX1cIiAtIOWwneivlSAke2F0dGVtcHR9LyR7bWF4UmV0cmllc30gKOW7tui/nyAke01hdGgucm91bmQoZGVsYXkpfW1zLCDlt7LogJfml7YgJHtNYXRoLnJvdW5kKGVsYXBzZWQgLyAxMDAwKX1zKWApO1xyXG5cclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIOmineWkluajgOafpeaWh+S7tuaYr+WQpuWPr+ivu1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXRzID0gZnMuc3RhdFN5bmMoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0cy5zaXplID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIuaWh+S7tuWkp+Wwj+S4ujDvvIzlj6/og73ku43lnKjlhpnlhaVcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyDmo4Dmn6Xmlofku7bmnIDlkI7kv67mlLnml7bpl7TvvIznoa7kv53kuI3mmK/liJrooqvkv67mlLlcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVBZ2UgPSBub3cgLSBzdGF0cy5tdGltZU1zO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlQWdlIDwgMjAwMCkgeyAvLyDmlofku7bkv67mlLnml7bpl7TlsJHkuo4y56eS77yM5Y+v6IO96L+Y5Zyo5YaZ5YWlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg5paH5Lu25Yia6KKr5L+u5pS5ICgke01hdGgucm91bmQoZmlsZUFnZSl9bXPliY0p77yM5Y+v6IO95LuN5Zyo5YaZ5YWlYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NFeGNlbEZpbGUoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvdGFsVGltZSA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZyZXNoQXNzZXREYXRhYmFzZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3VjY2VzcyhgW0V4Y2Vs5o+S5Lu2XSDmlofku7YgXCIke3BhdGguYmFzZW5hbWUoZmlsZVBhdGgpfVwiIOiHquWKqOWvvOWHuuaIkOWKnyAo5oC76ICX5pe2ICR7TWF0aC5yb3VuZCh0b3RhbFRpbWUgLyAxMDAwKX1zLCDlsJ3or5UgJHthdHRlbXB0fS8ke21heFJldHJpZXN9KWApO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucnVuTmV4dEV4cG9ydCgpO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8g6K+m57uG6K6w5b2V6ZSZ6K+vXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOWwneivlSAke2F0dGVtcHR9IOWksei0pTogJHtlcnIubWVzc2FnZSB8fCBlcnJ9YCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIOajgOafpeaYr+WQpuaYr+aWh+S7tumUgeWumuaIluadg+mZkOmUmeivr1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzRmlsZUxvY2tFcnJvciA9IGVyci5tZXNzYWdlICYmIChcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ0VQRVJNJykgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ0VCVVNZJykgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ3Blcm1pc3Npb24nKSB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnIubWVzc2FnZS5pbmNsdWRlcygnbG9ja2VkJykgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ0VBQ0NFUycpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlLmluY2x1ZGVzKCdmaWxlIHNpemUgMCcpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlLmluY2x1ZGVzKCfliJrooqvkv67mlLknKVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0ZpbGVMb2NrRXJyb3IgJiYgYXR0ZW1wdCA8IG1heFJldHJpZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8g6K6h566X5LiL5LiA5qyh5bCd6K+V55qE5bu26L+f77yI5oyH5pWw6YCA6YG/77yJXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHREZWxheSA9IGJhc2VEZWxheSAqIE1hdGgubWluKDEuNSAqKiBhdHRlbXB0LCA0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOaWh+S7tiBcIiR7cGF0aC5iYXNlbmFtZShmaWxlUGF0aCl9XCIg5Y+v6IO95LuN5Zyo5L+d5a2Y5Lit77yM5bCG5ZyoICR7TWF0aC5yb3VuZChuZXh0RGVsYXkpfW1zIOWQjumHjeivlSAo5bCd6K+VICR7YXR0ZW1wdCArIDF9LyR7bWF4UmV0cmllc30pYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQodHJ5UHJvY2VzcywgbmV4dERlbGF5KTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0b3RhbFRpbWUgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9yKGBbRXhjZWzmj5Lku7ZdIOaWh+S7tiBcIiR7cGF0aC5iYXNlbmFtZShmaWxlUGF0aCl9XCIg6Ieq5Yqo5a+85Ye65aSx6LSlICjmgLvogJfml7YgJHtNYXRoLnJvdW5kKHRvdGFsVGltZSAvIDEwMDApfXMpOiAke2Vycn1gKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIOWmguaenOaYr+aWh+S7tumUgeWumumUmeivr+S9huW3sui+vuWIsOacgOWkp+mHjeivleasoeaVsO+8jOaPkOS+m+WFt+S9k+W7uuiurlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaWxlTG9ja0Vycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9yKGBbRXhjZWzmj5Lku7ZdIOW7uuiurjog56Gu5L+dRXhjZWzlrozlhajkv53lrZjlkI7lho3ov5vooYzkv67mlLnvvIzmiJblop7liqDph43or5XmrKHmlbDlkozlu7bov59gKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJ1bk5leHRFeHBvcnQoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sIGRlbGF5KTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0cnlQcm9jZXNzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5YGc5q2i5paH5Lu255uR5ZCs77yI5pu05paw77yJXHJcbiAgICBzdG9wRmlsZVdhdGNoZXIoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZmlsZVdhdGNoZXIpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIC8vIOS9v+eUqOexu+Wei+aWreiogOehruS/neiwg+eUqGNsb3Nl5pa55rOVXHJcbiAgICAgICAgICAgICAgICAodGhpcy5maWxlV2F0Y2hlciBhcyBhbnkpLmNsb3NlKCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZpbGVXYXRjaGVyID0gbnVsbDtcclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOWBnOatouebkeWQrOaXtuWHuumUmTogJHtlfWApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcud2F0Y2hlcikge1xyXG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuY29uZmlnLndhdGNoZXIpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcud2F0Y2hlciA9IG51bGw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5sb2coJ1tFeGNlbOaPkuS7tl0g5bey5YGc5q2iRXhjZWzmlofku7bnm5HlkKwnKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8g55Sf5oiQSlNPTuaVsOaNrlxyXG4gICAgZ2VuZXJhdGVKc29uRGF0YShkYXRhUm93czogYW55W11bXSwgaGVhZGVyczogYW55KTogYW55W10ge1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IHJvdyBvZiBkYXRhUm93cykge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNEYXRhUm93KHJvdywgaGVhZGVycy5maWVsZHMpKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgb2JqOiBhbnkgPSB7fTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGVhZGVycy5maWVsZHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gaGVhZGVycy5maWVsZHNbaV07XHJcbiAgICAgICAgICAgICAgICBjb25zdCB0eXBlID0gaGVhZGVycy50eXBlc1tpXTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoZmllbGQpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHJvd1tpXSAhPT0gdW5kZWZpbmVkID8gcm93W2ldIDogdGhpcy5nZXREZWZhdWx0VmFsdWUodHlwZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgb2JqW2ZpZWxkXSA9IHRoaXMuY29udmVydFZhbHVlKHZhbHVlLCB0eXBlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmVzdWx0LnB1c2gob2JqKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIOi3s+i/h+WFqOepuuihjCAqL1xyXG4gICAgcHJpdmF0ZSBpc0RhdGFSb3cocm93OiBhbnlbXSwgZmllbGRzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICghcm93IHx8IHJvdy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpZWxkcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IGZpZWxkc1tpXTtcclxuICAgICAgICAgICAgaWYgKCFmaWVsZCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcm93W2ldO1xyXG4gICAgICAgICAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCAmJiBTdHJpbmcodmFsdWUpLnRyaW0oKSAhPT0gJycpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKiog5Yik5pat5Y2V5YWD5qC85piv5ZCm5Li656m6ICovXHJcbiAgICBwcml2YXRlIGlzRW1wdHlWYWx1ZSh2YWx1ZTogYW55KTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUudHJpbSgpID09PSAnJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5qC55o2u57G75Z6L6I635Y+W6buY6K6k5YC8XHJcbiAgICBnZXREZWZhdWx0VmFsdWUodHlwZTogc3RyaW5nKTogYW55IHtcclxuICAgICAgICBpZiAoIXR5cGUpIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgICBjb25zdCBjbGVhblR5cGUgPSB0eXBlLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xyXG4gICAgICAgIHN3aXRjaCAoY2xlYW5UeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ2ludCc6XHJcbiAgICAgICAgICAgIGNhc2UgJ2Zsb2F0JzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgICAgICBjYXNlICdib29sZWFuJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgY2FzZSAnaW50W10nOlxyXG4gICAgICAgICAgICBjYXNlICdmbG9hdFtdJzpcclxuICAgICAgICAgICAgY2FzZSAnc3RyaW5nW10nOlxyXG4gICAgICAgICAgICBjYXNlICdhbnlbXSc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvLyDnsbvlnovovazmjaJcclxuICAgIGNvbnZlcnRWYWx1ZSh2YWx1ZTogYW55LCB0eXBlOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgICAgIGlmICh0aGlzLmlzRW1wdHlWYWx1ZSh2YWx1ZSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGVmYXVsdFZhbHVlKHR5cGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY2xlYW5UeXBlID0gdHlwZS50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgc3dpdGNoIChjbGVhblR5cGUpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2ludCc6IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBuID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNOYU4obikgPyAwIDogbjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNhc2UgJ2Zsb2F0Jzoge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG4gPSBwYXJzZUZsb2F0KHZhbHVlKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNOYU4obikgPyAwIDogbjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNhc2UgJ2pzb24nOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHZhbHVlKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyB8fCB2YWx1ZSA9PT0gMTtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2ludFtdJzpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZUFycmF5KHZhbHVlLCAnaW50Jyk7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdmbG9hdFtdJzpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZUFycmF5KHZhbHVlLCAnZmxvYXQnKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZ1tdJzpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZUFycmF5KHZhbHVlLCAnc3RyaW5nJyk7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdhbnlbXSc6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VBcnJheSh2YWx1ZSwgJ2FueScpO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIHRoaXMud2FybihgW0V4Y2Vs5o+S5Lu2XSDnsbvlnovovazmjaLlpLHotKUgWyR7dHlwZX1dOiAke3ZhbHVlfSAtICR7ZX1gKTtcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyDop6PmnpDmlbDnu4RcclxuICAgIHBhcnNlQXJyYXkodmFsdWU6IGFueSwgdGFyZ2V0VHlwZTogc3RyaW5nKTogYW55W10ge1xyXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xyXG5cclxuICAgICAgICAvLyDlsJ3or5XliIblibLlrZfnrKbkuLJcclxuICAgICAgICBsZXQgaXRlbXMgPSBbXTtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBpdGVtcyA9IHZhbHVlLnNwbGl0KC9bLDsjXFxzXVxccyovKS5maWx0ZXIodiA9PiB2KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpdGVtcyA9IFt2YWx1ZV07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gaXRlbXMubWFwKGl0ZW0gPT4ge1xyXG4gICAgICAgICAgICBpZiAodGFyZ2V0VHlwZSA9PT0gJ2FueScpIHtcclxuICAgICAgICAgICAgICAgIC8vIOiHquWKqOivhuWIq+exu+Wei1xyXG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihpdGVtKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhaXNOYU4ocGFyc2VGbG9hdChpdGVtKSkgPyBwYXJzZUZsb2F0KGl0ZW0pIDogcGFyc2VJbnQoaXRlbSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoaXRlbS50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZScgfHwgaXRlbS50b0xvd2VyQ2FzZSgpID09PSAnZmFsc2UnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0udG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIOaMh+Wumuexu+Wei+i9rOaNolxyXG4gICAgICAgICAgICBzd2l0Y2ggKHRhcmdldFR5cGUpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2ludCc6IHJldHVybiBwYXJzZUludChpdGVtKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ2Zsb2F0JzogcmV0dXJuIHBhcnNlRmxvYXQoaXRlbSk7XHJcbiAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOiByZXR1cm4gU3RyaW5nKGl0ZW0pO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDogcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBnZW5lcmF0ZVRTSW50ZXJmYWNlU3RhcnQoc2hlZXROYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGludGVyZmFjZU5hbWUgPSBgSVRhYmxlJHtzaGVldE5hbWV9YDtcclxuICAgICAgICBjb25zdCBzYWZlU2hlZXROYW1lID0gYCR7dGhpcy5tYWtlU2FmZUZpbGVOYW1lKHNoZWV0TmFtZSl9YDtcclxuXHJcbiAgICAgICAgbGV0IHRzQ29udGVudCA9IGAgICAgLyoqXFxuICAgICAqICR7c2FmZVNoZWV0TmFtZX0g6YWN572u5pWw5o2uXFxuICAgICovXFxuYDtcclxuICAgICAgICB0c0NvbnRlbnQgKz0gYCAgICBpbnRlcmZhY2UgJHtpbnRlcmZhY2VOYW1lfSB7XFxuYDtcclxuICAgICAgICByZXR1cm4gdHNDb250ZW50O1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOeUn+aIkFRT5o6l5Y+jXHJcbiAgICBnZW5lcmF0ZVRTSW50ZXJmYWNlKHNoZWV0TmFtZTogc3RyaW5nLCBoZWFkZXJzOiBhbnkpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGludGVyZmFjZU5hbWUgPSBgSVRhYmxlJHtzaGVldE5hbWV9YDtcclxuICAgICAgICBjb25zdCBzYWZlU2hlZXROYW1lID0gYCR7dGhpcy5tYWtlU2FmZUZpbGVOYW1lKHNoZWV0TmFtZSl9YDtcclxuXHJcbiAgICAgICAgbGV0IHRzQ29udGVudCA9IGAgICAgLyoqXFxuICAgICAqICR7c2FmZVNoZWV0TmFtZX0g6YWN572u5pWw5o2uXFxuICAgICovXFxuYDtcclxuICAgICAgICB0c0NvbnRlbnQgKz0gYCAgICBpbnRlcmZhY2UgJHtpbnRlcmZhY2VOYW1lfSB7XFxuYDtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWFkZXJzLmZpZWxkcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IGhlYWRlcnMuZmllbGRzW2ldO1xyXG4gICAgICAgICAgICBjb25zdCB0eXBlID0gaGVhZGVycy50eXBlc1tpXTtcclxuICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBoZWFkZXJzLmRlc2NyaXB0aW9uc1tpXSB8fCAn5a2X5q616K+05piOJztcclxuXHJcbiAgICAgICAgICAgIGlmIChmaWVsZCkge1xyXG4gICAgICAgICAgICAgICAgdHNDb250ZW50ICs9IGAgICAgICAgIC8qKiAke2Rlc2NyaXB0aW9ufSAqL1xcbmA7XHJcbiAgICAgICAgICAgICAgICB0c0NvbnRlbnQgKz0gYCAgICAgICAgcmVhZG9ubHkgJHtmaWVsZH06ICR7dGhpcy5jb252ZXJ0VG9UU1R5cGUodHlwZSl9O1xcbmA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRzQ29udGVudCArPSBgICAgIH1cXG5gO1xyXG4gICAgICAgIHJldHVybiB0c0NvbnRlbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g6L2s5o2i5Li6VFPnsbvlnotcclxuICAgIGNvbnZlcnRUb1RTVHlwZShleGNlbFR5cGU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKCFleGNlbFR5cGUpIHJldHVybiAnYW55JztcclxuXHJcbiAgICAgICAgY29uc3QgdHlwZSA9IGV4Y2VsVHlwZS50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcclxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcclxuICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnc3RyaW5nJztcclxuICAgICAgICAgICAgY2FzZSAnaW50JzpcclxuICAgICAgICAgICAgY2FzZSAnZmxvYXQnOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdudW1iZXInO1xyXG4gICAgICAgICAgICBjYXNlICdib29sZWFuJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnYm9vbGVhbic7XHJcbiAgICAgICAgICAgIGNhc2UgJ2ludFtdJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnbnVtYmVyW10nO1xyXG4gICAgICAgICAgICBjYXNlICdmbG9hdFtdJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnbnVtYmVyW10nO1xyXG4gICAgICAgICAgICBjYXNlICdzdHJpbmdbXSc6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3N0cmluZ1tdJztcclxuICAgICAgICAgICAgY2FzZSAnYW55W10nOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICcobnVtYmVyIHwgc3RyaW5nIHwgYm9vbGVhbilbXSc7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2FueSc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIOi9rOaNouS4ulBhc2NhbENhc2VcclxuICAgIHRvUGFzY2FsQ2FzZShzdHI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8oXFx3KShcXHcqKS9nLCAoXywgZzEsIGcyKSA9PlxyXG4gICAgICAgICAgICBnMS50b1VwcGVyQ2FzZSgpICsgZzIudG9Mb3dlckNhc2UoKVxyXG4gICAgICAgICkucmVwbGFjZSgvW15hLXpBLVowLTldL2csICcnKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyDliJvlu7rlronlhajnmoTmlofku7blkI1cclxuICAgIG1ha2VTYWZlRmlsZU5hbWUobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOV9dL2csICdfJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5pel5b+X6L6T5Ye6XHJcbiAgICBsb2cobWVzc2FnZTogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2cobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgZXJyb3IobWVzc2FnZTogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICB3YXJuKG1lc3NhZ2U6IHN0cmluZykge1xyXG4gICAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICBzdWNjZXNzKG1lc3NhZ2U6IHN0cmluZykge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKG1lc3NhZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOa2iOaBr+WkhOeQhlxyXG4gICAgbWVzc2FnZXMgPSB7XHJcbiAgICAgICAgJ2V4Y2VsLXRvLWpzb24tdHM6ZXhwb3J0LW1hbnVhbCc6ICgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5leHBvcnRNYW51YWwoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5Yi35paw6LWE5rqQ566h55CG5ZmoXHJcbiAgICBhc3luYyByZWZyZXNoQXNzZXREYXRhYmFzZSgpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCBwYXRocyA9IG1lbWJlcnNoaXBGcm9tQXJyYXkoW1xyXG4gICAgICAgICAgICAgICAgLi4ubWVtYmVyc2hpcFRvQXJyYXkodGhpcy5qc29uUmVmcmVzaFBhdGhzKSxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmpzb25FeHBvcnRQYXRoLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubGFuZ0pzb25FeHBvcnRQYXRoLFxyXG4gICAgICAgICAgICBdKTtcclxuXHJcbiAgICAgICAgICAgIGZvciAoY29uc3Qgc3lzdGVtUGF0aCBvZiBtZW1iZXJzaGlwVG9BcnJheShwYXRocykpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRiUGF0aCA9IHRoaXMuY29udmVydFRvRGJQYXRoKHN5c3RlbVBhdGgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGRiUGF0aCAmJiBkYlBhdGguc3RhcnRzV2l0aCgnZGI6Ly8nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IEVkaXRvci5NZXNzYWdlLnJlcXVlc3QoJ2Fzc2V0LWRiJywgJ3JlZnJlc2gtYXNzZXQnLCBkYlBhdGgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCB0c0RiUGF0aCA9IHRoaXMuY29udmVydFRvRGJQYXRoKHRoaXMuY29uZmlnLnRzRXhwb3J0UGF0aCk7XHJcbiAgICAgICAgICAgIGlmICh0c0RiUGF0aCAmJiB0c0RiUGF0aC5zdGFydHNXaXRoKCdkYjovLycpKSB7XHJcbiAgICAgICAgICAgICAgICBhd2FpdCBFZGl0b3IuTWVzc2FnZS5yZXF1ZXN0KCdhc3NldC1kYicsICdyZWZyZXNoLWFzc2V0JywgdHNEYlBhdGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLnN1Y2Nlc3MoJ1tFeGNlbOaPkuS7tl0g6LWE5rqQ5Yi35paw6K+35rGC5bey5Y+R6YCBJyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZXJyb3IoYFtFeGNlbOaPkuS7tl0g6LWE5rqQ5Yi35paw5aSx6LSlOiAke2Vycn1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5bCG57O757uf6Lev5b6E6L2s5o2i5Li6Q29jb3PnmoRkYui3r+W+hFxyXG4gICAgY29udmVydFRvRGJQYXRoKHN5c3RlbVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKCFzeXN0ZW1QYXRoKSByZXR1cm4gJyc7XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIC8vIOiOt+WPlumhueebrui3r+W+hFxyXG4gICAgICAgICAgICBjb25zdCBwcm9qZWN0UGF0aCA9IEVkaXRvci5Qcm9qZWN0LnBhdGg7XHJcblxyXG4gICAgICAgICAgICAvLyDop4TojIPljJbot6/lvoTvvIjnu5/kuIDkvb/nlKjmraPmlpzmnaDvvIlcclxuICAgICAgICAgICAgc3lzdGVtUGF0aCA9IHN5c3RlbVBhdGgucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xyXG4gICAgICAgICAgICBjb25zdCBub3JtYWxpemVkUHJvamVjdFBhdGggPSBwcm9qZWN0UGF0aC5yZXBsYWNlKC9cXFxcL2csICcvJyk7XHJcblxyXG4gICAgICAgICAgICAvLyDnoa7kv53ot6/lvoTku6Uv57uT5bC+XHJcbiAgICAgICAgICAgIGNvbnN0IHByb2plY3RQYXRoV2l0aFNsYXNoID0gbm9ybWFsaXplZFByb2plY3RQYXRoLmVuZHNXaXRoKCcvJylcclxuICAgICAgICAgICAgICAgID8gbm9ybWFsaXplZFByb2plY3RQYXRoXHJcbiAgICAgICAgICAgICAgICA6IG5vcm1hbGl6ZWRQcm9qZWN0UGF0aCArICcvJztcclxuXHJcbiAgICAgICAgICAgIC8vIOajgOafpeaYr+WQpuWcqOmhueebruebruW9leWGhVxyXG4gICAgICAgICAgICBpZiAoc3lzdGVtUGF0aC5zdGFydHNXaXRoKHByb2plY3RQYXRoV2l0aFNsYXNoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8g6K6h566X55u45a+56Lev5b6EXHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBzeXN0ZW1QYXRoLnN1YnN0cmluZyhwcm9qZWN0UGF0aFdpdGhTbGFzaC5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGBkYjovLyR7cmVsYXRpdmVQYXRofWA7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIOWmguaenOi3r+W+hOWMheWQq2Fzc2V0c+ebruW9le+8jOWwneivleebtOaOpei9rOaNolxyXG4gICAgICAgICAgICBpZiAoc3lzdGVtUGF0aC5pbmNsdWRlcygnL2Fzc2V0cy8nKSB8fCBzeXN0ZW1QYXRoLmluY2x1ZGVzKCdcXFxcYXNzZXRzXFxcXCcpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhc3NldHNJbmRleCA9IHN5c3RlbVBhdGgudG9Mb3dlckNhc2UoKS5pbmRleE9mKCcvYXNzZXRzLycpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFzc2V0c0luZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbGF0aXZlVG9Bc3NldHMgPSBzeXN0ZW1QYXRoLnN1YnN0cmluZyhhc3NldHNJbmRleCArIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBgZGI6Ly8ke3JlbGF0aXZlVG9Bc3NldHN9YDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy53YXJuKGBbRXhjZWzmj5Lku7ZdIOi3r+W+hOS4jeWcqOmhueebruWGhe+8jOWPr+iDveaXoOazleato+ehruWIt+aWsDogJHtzeXN0ZW1QYXRofWApO1xyXG4gICAgICAgICAgICByZXR1cm4gc3lzdGVtUGF0aDtcclxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgICAgICAgdGhpcy5lcnJvcihgW0V4Y2Vs5o+S5Lu2XSDot6/lvoTovazmjaLlpLHotKU6ICR7ZXJyfWApO1xyXG4gICAgICAgICAgICByZXR1cm4gc3lzdGVtUGF0aDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBleGNlbFRvSnNvblBsdWdpbiA9IG5ldyBFeGNlbFRvSnNvblBsdWdpbigpOyJdfQ==
|