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.
 
 
 
 

615 lines
78 KiB

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.methods = void 0;
exports.load = load;
exports.unload = unload;
// @ts-ignore
const package_json_1 = __importDefault(require("../package.json"));
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const os_1 = require("os");
const ws_server_1 = require("./ws-server");
const mcp_server_1 = require("./mcp-server");
const DEFAULT_PORT = 33000;
/** 固定静态连接令牌:不做动态生成,保证脚本/节点令牌与插件始终一致。 */
const STATIC_TOKEN = 'www.yyka.cn';
let server = null;
let logBuffer = [];
/** 面板已消费到的缓冲位置:queryLog 改为增量取走而非清空,避免饿死 MCP 的非破坏性 getLogs。 */
let logCursor = 0;
const serverToken = STATIC_TOKEN;
let mcpHost = null;
const pending = new Map();
let requestSeq = 0;
function ensureServer() {
if (!server) {
server = new ws_server_1.WsServer();
}
return server;
}
function getServerState() {
var _a, _b, _c, _d, _e, _f;
const info = (_a = server === null || server === void 0 ? void 0 : server.clientInfo) !== null && _a !== void 0 ? _a : null;
return {
running: (_b = server === null || server === void 0 ? void 0 : server.isRunning) !== null && _b !== void 0 ? _b : false,
port: (_c = server === null || server === void 0 ? void 0 : server.boundPort) !== null && _c !== void 0 ? _c : 0,
clients: (_d = server === null || server === void 0 ? void 0 : server.clients) !== null && _d !== void 0 ? _d : 0,
clientType: (_e = info === null || info === void 0 ? void 0 : info.type) !== null && _e !== void 0 ? _e : '',
clientUrl: (_f = info === null || info === void 0 ? void 0 : info.url) !== null && _f !== void 0 ? _f : '',
};
}
function pushLog(item) {
logBuffer.push(item);
while (logBuffer.length > 200) {
logBuffer.shift();
if (logCursor > 0) {
logCursor--;
}
}
}
/** 客户端类型 → 中文标签(日志用)。 */
function typeLabel(type) {
switch (type) {
case 'h5':
return '浏览器预览';
case 'editor':
return '编辑器预览';
case 'simulator':
return '模拟器';
case 'device':
return '真机';
case 'unknown':
default:
return '未知来源';
}
}
/** 从项目 settings 中递归查找数值端口。 */
function findNumericPort(cfg) {
if (!cfg || typeof cfg !== 'object') {
return 0;
}
if (typeof cfg.port === 'number' && cfg.port > 0) {
return cfg.port;
}
if (typeof cfg.port === 'string' && !Number.isNaN(Number(cfg.port))) {
return Number(cfg.port);
}
for (const k of Object.keys(cfg)) {
const v = cfg[k];
if (v && typeof v === 'object') {
const p = findNumericPort(v);
if (p > 0) {
return p;
}
}
}
return 0;
}
/**
* 读取当前项目的预览配置,得出浏览器预港口/URL。
* 用于面板内嵌 iframe 预览的默认地址。
*/
function getPreviewInfo() {
var _a;
const projectPath = (_a = Editor.Project) === null || _a === void 0 ? void 0 : _a.path;
const candidates = ['settings/preview.json', 'settings/v2/packages/preview.json'];
if (projectPath) {
for (const rel of candidates) {
try {
const p = (0, path_1.join)(projectPath, rel);
if (!(0, fs_extra_1.existsSync)(p)) {
continue;
}
const cfg = (0, fs_extra_1.readJsonSync)(p);
const port = findNumericPort(cfg);
if (port > 0) {
return { host: 'localhost', port, url: `http://localhost:${port}/`, found: p };
}
}
catch (_b) {
// 忽略解析失败,尝试下一个候选文件
}
}
}
return { host: 'localhost', port: 7456, url: 'http://localhost:7456/', found: '' };
}
/** 处理来自游戏侧的消息:优先匹配 pending 请求,否则进入日志缓冲。 */
function handleIncoming(data) {
var _a;
const m = data && typeof data === 'object' ? data : null;
if (m && typeof m.requestId === 'number' && pending.has(m.requestId)) {
const p = pending.get(m.requestId);
pending.delete(m.requestId);
if (p.timer)
clearTimeout(p.timer);
p.resolve((_a = m.data) !== null && _a !== void 0 ? _a : m);
return;
}
// 命令回包/握手等内部协议消息不进入日志,避免 requestId/response/hello 刷屏
if (m && (m.evt === 'response' || m.evt === 'request' || m.evt === 'hello')) {
return;
}
pushLog(data);
}
/** 按限制条数与级别读取最近日志(不清空缓冲,供面板/MCP 使用)。 */
function getLogsInternal(limit, level) {
const items = [];
for (let i = logBuffer.length - 1; i >= 0 && items.length < limit; i--) {
const it = logBuffer[i];
if (!it || typeof it !== 'object') {
continue;
}
// 过滤掉心跳/握手/预览帧等噪声,只保留控制台与系统消息
if (it.evt !== 'console' && it.evt !== 'sys') {
continue;
}
if (level && it.evt === 'console' && it.level !== level) {
continue;
}
items.unshift(it);
}
return items;
}
/** 返回 MCP 服务状态与连接配置(URL + 令牌)。 */
function getMcpState() {
var _a, _b;
return {
running: (_a = mcpHost === null || mcpHost === void 0 ? void 0 : mcpHost.isRunning) !== null && _a !== void 0 ? _a : false,
port: (_b = mcpHost === null || mcpHost === void 0 ? void 0 : mcpHost.boundPort) !== null && _b !== void 0 ? _b : 0,
token: serverToken,
url: (mcpHost === null || mcpHost === void 0 ? void 0 : mcpHost.isRunning) ? `http://127.0.0.1:${mcpHost.boundPort}/mcp` : '',
};
}
/** 向游戏侧桥接脚本发送一条请求,并等待其回包。 */
function callGame(cmd, payload, timeout = 5000) {
return new Promise((resolve, reject) => {
if (!server || !server.isRunning) {
reject(new Error('WS 服务未运行,请先启动服务'));
return;
}
const requestId = ++requestSeq;
const timer = setTimeout(() => {
if (pending.has(requestId)) {
pending.delete(requestId);
reject(new Error(`命令超时(>${timeout}ms): ${cmd}`));
}
}, timeout);
pending.set(requestId, { resolve, reject, timer });
server.broadcast({ requestId, cmd, payload });
});
}
/** 获取宿主机第一个非内网 IPv4 地址(用于注入桥接脚本,供模拟器/真机通过局域网连上插件服务)。 */
function getHostLanIP() {
var _a;
// 优先返回内网私有段地址(Wi-Fi/有线网卡),避免选到虚拟机或 VPN 虚拟网卡导致真机连不通
let fallback = '';
try {
for (const name of Object.keys((0, os_1.networkInterfaces)())) {
for (const net of (_a = (0, os_1.networkInterfaces)()[name]) !== null && _a !== void 0 ? _a : []) {
if (net.family === 'IPv4' && !net.internal) {
const a = net.address.split('.').map(Number);
const isPrivate = a[0] === 10 ||
(a[0] === 172 && a[1] >= 16 && a[1] <= 31) ||
(a[0] === 192 && a[1] === 168);
if (isPrivate) {
return net.address;
}
if (!fallback) {
fallback = net.address;
}
}
}
}
}
catch (_b) {
/* ignore */
}
return fallback;
}
/**
* @zh 为扩展的主进程的注册方法
*/
/** 收集目录下所有 .scene 文件。 */
function collectSceneFiles(dir, out) {
let entries;
try {
entries = (0, fs_extra_1.readdirSync)(dir, { withFileTypes: true });
}
catch (_a) {
return;
}
for (const e of entries) {
const p = (0, path_1.join)(dir, e.name);
if (e.isDirectory()) {
collectSceneFiles(p, out);
}
else if (e.isFile() && e.name.endsWith('.scene')) {
out.push(p);
}
}
}
/** 遍历场景 JSON 中的节点树,对匹配指定脚本 uuid 的组件执行回调。 */
function walkSceneComponents(sceneJson, compUuid, cb) {
const walkNode = (node) => {
if (!node || typeof node !== 'object') {
return;
}
if (node.__type__ === 'cc.Node') {
for (const c of node._components || []) {
if (c && c.__type__ === compUuid) {
cb(c);
}
}
for (const ch of node._children || []) {
walkNode(ch);
}
}
};
walkNode(sceneJson && sceneJson.scene);
}
exports.methods = {
openPanel() {
Editor.Panel.open(package_json_1.default.name);
},
openPreviewPanel() {
Editor.Panel.open(`${package_json_1.default.name}.preview`);
},
/**
* 启动 WS 服务。返回当前服务状态。
*/
async startServer(port = DEFAULT_PORT) {
const ws = ensureServer();
ws.token = serverToken;
try {
if (!ws.isRunning) {
ws.on('message', (_client, data) => handleIncoming(data));
ws.on('connection', (_client, info) => pushLog({ evt: 'sys', msg: `客户端已连接 (${typeLabel(info === null || info === void 0 ? void 0 : info.type)})` }));
ws.on('disconnect', (_client, info) => pushLog({ evt: 'sys', msg: `客户端已断开 (${typeLabel(info === null || info === void 0 ? void 0 : info.type)})` }));
ws.on('auth-fail', (got, url) => pushLog({ evt: 'sys', msg: `连接被拒绝:客户端令牌(${got}) ≠ 服务端令牌(${serverToken})` }));
await ws.start(port);
}
}
catch (err) {
pushLog({ evt: 'sys', msg: `启动服务失败: ${String(err)}` });
}
return getServerState();
},
/**
* 停止 WS 服务。返回当前服务状态。
*/
async stopServer() {
if (server) {
await server.stop();
}
return getServerState();
},
getServerState() {
return getServerState();
},
/**
* 返回固定连接令牌(静态 token)。
*/
getToken() {
return serverToken;
},
/**
* 读取当前项目预览配置得出的预港口/URL(供面板内嵌 iframe 用)。
*/
getPreviewInfo() {
return getPreviewInfo();
},
/**
* 读取当前项目设计分辨率(Project Settings → general.designResolution)。
* 首选编辑器内置 `project/query-config`(实时读配置缓存),多模块/按键都试一遍;
* 失败再退回到读 settings/v2/packages/project.json 文件,兜底 960×640。
*/
async getProjectsSettings() {
var _a;
try {
const modules = ['general', 'engine', 'project'];
for (const mod of modules) {
try {
const d = await Editor.Message.request('project', 'query-config', mod, 'designResolution');
if (d && Number(d.width) > 0 && Number(d.height) > 0) {
return { designResolution: { width: Number(d.width), height: Number(d.height) } };
}
}
catch (_b) {
// 该模块无此配置,尝试下一个
}
}
}
catch (_c) {
// 继续走文件兜底
}
const projectPath = (_a = Editor.Project) === null || _a === void 0 ? void 0 : _a.path;
const candidates = [
'settings/v2/packages/project.json',
'settings/project.json',
];
if (projectPath) {
for (const rel of candidates) {
try {
const p = (0, path_1.join)(projectPath, rel);
if (!(0, fs_extra_1.existsSync)(p))
continue;
const cfg = (0, fs_extra_1.readJsonSync)(p);
const d = cfg && cfg.general && cfg.general.designResolution;
if (d && Number(d.width) > 0 && Number(d.height) > 0) {
return { designResolution: { width: Number(d.width), height: Number(d.height) } };
}
}
catch (_d) {
// 忽略解析失败,尝试下一个候选文件
}
}
}
return { designResolution: { width: 960, height: 640 } };
},
/**
* 面板向游戏侧桥接脚本广播一条 fire-and-forget 命令。
* args: { cmd: string, payload?: any }
*/
sendCommand(args) {
if (server) {
server.broadcast({ cmd: args === null || args === void 0 ? void 0 : args.cmd, payload: args === null || args === void 0 ? void 0 : args.payload });
}
return getServerState();
},
/**
* 面板请求游戏侧数据:向游戏发带 requestId 的命令并等待回包。
* args: { cmd: string, payload?: any, timeout?: number }
*/
async queryCommand(args) {
var _a;
const r = await callGame(args === null || args === void 0 ? void 0 : args.cmd, args === null || args === void 0 ? void 0 : args.payload, (_a = args === null || args === void 0 ? void 0 : args.timeout) !== null && _a !== void 0 ? _a : 5000);
return r;
},
/**
* 取回自上次查询以来收到的消息(游戏 → 面板)。按游标增量读取,不破坏缓冲。
*/
queryLog() {
const batch = logBuffer.slice(logCursor);
logCursor = logBuffer.length;
return batch;
},
/**
* 读取最近日志(不清空缓冲),供 MCP/AI Agent 使用。
* args: { limit?: number, level?: 'all'|'log'|'warn'|'error' }
*/
getLogs(args) {
const limit = Math.max(1, Math.min(200, Number(args === null || args === void 0 ? void 0 : args.limit) || 50));
const level = (args === null || args === void 0 ? void 0 : args.level) === 'log' || (args === null || args === void 0 ? void 0 : args.level) === 'warn' || (args === null || args === void 0 ? void 0 : args.level) === 'error' ? args.level : '';
return getLogsInternal(limit, level);
},
/**
* 启动 MCP 服务(HTTP Streamable,供 Codex 等 AI Agent 连接)。
*/
async startMcp(port = mcp_server_1.MCP_DEFAULT_PORT) {
if (!mcpHost) {
mcpHost = new mcp_server_1.McpHttpServer();
}
try {
if (!mcpHost.isRunning) {
const token = serverToken;
await mcpHost.start(port, token, {
callGame,
getServerState,
getToken: () => serverToken,
getLogs: (l, lv) => getLogsInternal(l, lv),
});
pushLog({ evt: 'sys', msg: `MCP 服务已启动: http://127.0.0.1:${mcpHost.boundPort}/mcp` });
}
}
catch (err) {
pushLog({ evt: 'sys', msg: `MCP 服务启动失败: ${String(err)}` });
}
return getMcpState();
},
/**
* 停止 MCP 服务。
*/
async stopMcp() {
if (mcpHost) {
await mcpHost.stop();
pushLog({ evt: 'sys', msg: 'MCP 服务已停止' });
}
return getMcpState();
},
/**
* 返回 MCP 服务状态与连接配置(URL + 令牌)。
*/
getMcpState() {
return getMcpState();
},
/**
* 把游戏侧桥接脚本 RuntimeBridge.ts 自动安装到当前项目的 assets 目录。
*/
async installBridge() {
var _a;
const projectPath = (_a = Editor.Project) === null || _a === void 0 ? void 0 : _a.path;
if (!projectPath) {
return { ok: false, msg: '无法获取项目路径(Editor.Project.path 为空)' };
}
const src = (0, path_1.join)(__dirname, '../runtime-bridge-sample/RuntimeBridge.ts');
const assetsDir = (0, path_1.join)(projectPath, 'assets');
if (!(0, fs_extra_1.existsSync)(src)) {
return { ok: false, msg: `未找到桥接脚本模板: ${src}` };
}
if (!(0, fs_extra_1.existsSync)(assetsDir)) {
return { ok: false, msg: `找不到项目的 assets 目录: ${assetsDir}` };
}
const dest = (0, path_1.join)(assetsDir, 'RuntimeBridge.ts');
const overwrote = (0, fs_extra_1.existsSync)(dest);
const currentToken = serverToken;
// 保留用户自定义 host/port(如真机调试时改为电脑 IP),避免每次覆盖被重置。
// 优先取场景中已存在常驻节点组件的现值(用户最近可能直接在节点上配置),
// 其次取已安装脚本文件里的默认值。
let keepHost = '';
let keepPort = 0;
if (overwrote) {
try {
const oldContent = (0, fs_extra_1.readFileSync)(dest, 'utf-8');
const hm = /host\s*=\s*'([^']*)'/.exec(oldContent);
const pm = /port\s*=\s*(\d+)/.exec(oldContent);
if (hm) {
keepHost = hm[1];
}
if (pm) {
keepPort = Number(pm[1]);
}
}
catch (_b) {
/* 读取失败则用模板默认值 */
}
}
// 解析桥接脚本组件 uuid,用于在场景文件中定位已存在的 RuntimeBridge 组件
let compUuid = '';
const metaPath = dest + '.meta';
try {
if ((0, fs_extra_1.existsSync)(metaPath)) {
const meta = (0, fs_extra_1.readJsonSync)(metaPath);
compUuid = (meta && meta.uuid) || '';
}
}
catch (_c) {
/* 忽略 meta 读取失败 */
}
let sceneFiles = [];
if (compUuid) {
try {
collectSceneFiles(assetsDir, sceneFiles);
// 第一遍:以已存在常驻节点组件上的 host/port 为准(用户配置),覆盖脚本旧值
for (const sp of sceneFiles) {
try {
const sj = (0, fs_extra_1.readJsonSync)(sp);
walkSceneComponents(sj, compUuid, (comp) => {
if (typeof comp.host === 'string' && comp.host) {
keepHost = comp.host;
}
if (typeof comp.port === 'number' && comp.port > 0) {
keepPort = comp.port;
}
});
}
catch (_d) {
/* 单个场景解析失败跳过 */
}
}
}
catch (_e) {
/* 扫描失败则跳过场景同步 */
}
}
// 桥接脚本内置固定令牌 www.yyka.cn,无需注入;
// 仅把 BRIDGE_VERSION 同步为插件版本号,避免面板显示过时版本
const srcContent = (0, fs_extra_1.readFileSync)(src, 'utf-8');
let injected = srcContent.replace(/BRIDGE_VERSION = '[^']*'/, `BRIDGE_VERSION = '${package_json_1.default.version}'`);
// 默认连接地址:用户配置过 host 则保留(如真机调试时自定义的电脑 IP);
// 否则自动注入宿主机局域网 IP —— 固定 127.0.0.1 时真机/模拟器连的是设备自身回环,无法接通插件服务
const lanIP = getHostLanIP();
if (keepHost) {
injected = injected.replace('host = DEFAULT_HOST;', `host = '${keepHost}';`);
}
else if (lanIP) {
injected = injected.replace('host = DEFAULT_HOST;', `host = '${lanIP}';`);
}
if (keepPort) {
injected = injected.replace('port = DEFAULT_PORT;', `port = ${keepPort};`);
}
(0, fs_extra_1.writeFileSync)(dest, injected, 'utf-8');
try {
await Editor.Message.request('asset-db', 'refresh-asset', dest);
}
catch (err) {
console.warn('[yyka-runtime-inspector] refresh-asset failed:', err);
}
// 第二遍:把已存在常驻节点的 host/port 同步为最新配置;
// token 已改为脚本内置常量,顺带清掉旧版本场景里残留的 token 字段,避免误导
if (compUuid) {
for (const sp of sceneFiles) {
try {
const sj = (0, fs_extra_1.readJsonSync)(sp);
let changed = false;
walkSceneComponents(sj, compUuid, (comp) => {
if (keepHost) {
comp.host = keepHost;
}
if (keepPort) {
comp.port = keepPort;
}
if (typeof comp.token !== 'undefined') {
delete comp.token;
changed = true;
}
if (keepHost || keepPort) {
changed = true;
}
});
if (changed) {
(0, fs_extra_1.writeJsonSync)(sp, sj, { spaces: 2 });
console.log(`[yyka-runtime-inspector] 已同步常驻节点属性: ${sp}`);
try {
await Editor.Message.request('asset-db', 'refresh-asset', sp);
}
catch (_f) {
/* ignore */
}
}
}
catch (_g) {
/* 单个场景同步失败跳过 */
}
}
}
return { ok: true, path: dest, overwrote, token: currentToken, scenes: sceneFiles.length };
},
/**
* 通知游戏侧高亮/遮罩指定节点。id 为空串则清除。
*/
async highlightNode(id, mode = 'highlight') {
try {
const res = await callGame('highlight', { id: id || '', mode: mode === 'mask' ? 'mask' : 'highlight' }, 3000);
return res;
}
catch (err) {
return { error: String(err) };
}
},
};
/**
* @zh 扩展启动时自动拉起 WS 服务,便于游戏侧随时连接。
*/
function load() {
console.log('[yyka-runtime-inspector] load, starting ws server...');
// 令牌为固定静态值,服务启动时自动带上鉴权
exports.methods.startServer();
// 每次打开插件自动安装最新桥接脚本(保留用户自定义 host/port),保证游戏侧脚本与插件版本同步
exports.methods.installBridge().then((res) => {
if (res && res.ok) {
pushLog({ evt: 'sys', msg: `桥接脚本${res.overwrote ? '已更新' : '已安装'}: ${res.path}` });
}
else if (res && res.msg) {
console.warn('[yyka-runtime-inspector] auto installBridge skipped:', res.msg);
}
}).catch((err) => {
console.warn('[yyka-runtime-inspector] auto installBridge failed:', err);
});
}
/**
* @zh 卸载扩展时关闭 WS 服务。
*/
function unload() {
if (server) {
server.stop();
server = null;
}
if (mcpHost) {
mcpHost.stop();
mcpHost = null;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NvdXJjZS9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQWdsQkEsb0JBY0M7QUFLRCx3QkFTQztBQTVtQkQsYUFBYTtBQUNiLG1FQUEwQztBQUMxQyx1Q0FBNkc7QUFDN0csK0JBQTRCO0FBQzVCLDJCQUF1QztBQUN2QywyQ0FBdUM7QUFDdkMsNkNBQStEO0FBRS9ELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQztBQUUzQix3Q0FBd0M7QUFDeEMsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDO0FBRW5DLElBQUksTUFBTSxHQUFvQixJQUFJLENBQUM7QUFDbkMsSUFBSSxTQUFTLEdBQWMsRUFBRSxDQUFDO0FBQzlCLDhEQUE4RDtBQUM5RCxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDbEIsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDO0FBQ2pDLElBQUksT0FBTyxHQUF5QixJQUFJLENBQUM7QUFRekMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQXNCLENBQUM7QUFDOUMsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBRW5CLFNBQVMsWUFBWTtJQUNqQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixNQUFNLEdBQUcsSUFBSSxvQkFBUSxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLGNBQWM7O0lBQ25CLE1BQU0sSUFBSSxHQUFHLE1BQUEsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLFVBQVUsbUNBQUksSUFBSSxDQUFDO0lBQ3hDLE9BQU87UUFDSCxPQUFPLEVBQUUsTUFBQSxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsU0FBUyxtQ0FBSSxLQUFLO1FBQ25DLElBQUksRUFBRSxNQUFBLE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRSxTQUFTLG1DQUFJLENB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QUMsS0FBSyxDQUFDLENBQUMsR0FBWSxFQUFFLEVBQUU7UUFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxxREFBcUQsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM3RSxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLE1BQU07SUFDbEIsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNULE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDbEIsQ0FBQztJQUNELElBQUksT0FBTyxFQUFFLENBQUM7UUFDVixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZixPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ25CLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWlnbm9yZVxuaW1wb3J0IHBhY2thZ2VKU09OIGZyb20gJy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHJlYWRKc29uU3luYywgcmVhZGRpclN5bmMsIHdyaXRlRmlsZVN5bmMsIHdyaXRlSnNvblN5bmMgfSBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBuZXR3b3JrSW50ZXJmYWNlcyB9IGZyb20gJ29zJztcbmltcG9ydCB7IFdzU2VydmVyIH0gZnJvbSAnLi93cy1zZXJ2ZXInO1xuaW1wb3J0IHsgTWNwSHR0cFNlcnZlciwgTUNQX0RFRkFVTFRfUE9SVCB9IGZyb20gJy4vbWNwLXNlcnZlcic7XG5cbmNvbnN0IERFRkFVTFRfUE9SVCA9IDMzMDAwO1xuXG4vKiog5Zu65a6a6Z2Z5oCB6L+e5o6l5Luk54mM77ya5LiN5YGa5Yqo5oCB55Sf5oiQ77yM5L+d6K+B6ISa5pysL+iKgueCueS7pOeJjOS4juaPkuS7tuWni+e7iOS4gOiHtOOAgiAqL1xuY29uc3QgU1RBVElDX1RPS0VOID0gJ3d3dy55eWthLmNuJztcblxubGV0IHNlcnZlcjogV3NTZXJ2ZXIgfCBudWxsID0gbnVsbDtcbmxldCBsb2dCdWZmZXI6IHVua25vd25bXSA9IFtdO1xuLyoqIOmdouadv+W3sua2iOi0ueWIsOeahOe8k+WGsuS9jee9ru+8mnF1ZXJ5TG9nIOaUueS4uuWinumHj+WPlui1sOiAjOmdnua4heepuu+8jOmBv+WFjemlv+atuyBNQ1Ag55qE6Z2e56C05Z2P5oCnIGdldExvZ3PjgIIgKi9cbmxldCBsb2dDdXJzb3IgPSAwO1xuY29uc3Qgc2VydmVyVG9rZW4gPSBTVEFUSUNfVE9LRU47XG5sZXQgbWNwSG9zdDogTWNwSHR0cFNlcnZlciB8IG51bGwgPSBudWxsO1xuXG4vLyDor7fmsYIv5ZON5bqU77ya6Z2i5p2/5Y+R5Ye65bimIHJlcXVlc3RJZCDnmoTlkb3ku6TvvIznrYnmuLjmiI/kvqfmoaXmjqXohJrmnKzlm57ljIXlkI4gcmVzb2x2ZeOAglxuaW50ZXJmYWNlIFBlbmRpbmdSZXEge1xuICAgIHJlc29sdmU6ICh2OiBhbnkpID0+IHZvaWQ7XG4gICAgcmVqZWN0OiAoZTogRXJyb3IpID0+IHZvaWQ7XG4gICAgdGltZXI6IGFueTtcbn1cbmNvbnN0IHBlbmRpbmcgPSBuZXcgTWFwPG51bWJlciwgUGVuZGluZ1JlcT4oKTtcbmxldCByZXF1ZXN0U2VxID0gMDtcblxuZnVuY3Rpb24gZW5zdXJlU2VydmVyKCk6IFdzU2VydmVyIHtcbiAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICBzZXJ2ZXIgPSBuZXcgV3NTZXJ2ZXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlcnZlcjtcbn1cblxuZnVuY3Rpb24gZ2V0U2VydmVyU3RhdGUoKSB7XG4gICAgY29uc3QgaW5mbyA9IHNlcnZlcj8uY2xpZW50SW5mbyA/PyBudWxsO1xuICAgIHJldHVybiB7XG4gICAgICAgIHJ1bm5pbmc6IHNlcnZlcj8uaXNSdW5uaW5nID8/IGZhbHNlLFxuICAgICAgICBwb3J0OiBzZXJ2ZXI/LmJvdW5kUG9ydCA/PyAwLFxuICAgICAgICBjbGllbnRzOiBzZXJ2ZXI/LmNsaWVudHMgPz8gMCxcbiAgICAgICAgY2xpZW50VHlwZTogaW5mbz8udHlwZSA/PyAnJyxcbiAgICAgICAgY2xpZW50VXJsOiBpbmZvPy51cmwgPz8gJycsXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcHVzaExvZyhpdGVtOiB1bmtub3duKSB7XG4gICAgbG9nQnVmZmVyLnB1c2goaXRlbSk7XG4gICAgd2hpbGUgKGxvZ0J1ZmZlci5sZW5ndGggPiAyMDApIHtcbiAgICAgICAgbG9nQnVmZmVyLnNoaWZ0KCk7XG4gICAgICAgIGlmIChsb2dDdXJzb3IgPiAwKSB7XG4gICAgICAgICAgICBsb2dDdXJzb3ItLTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqIOWuouaIt+err+exu+WeiyDihpIg5Lit5paH5qCH562+77yI5pel5b+X55So77yJ44CCICovXG5mdW5jdGlvbiB0eXBlTGFiZWwodHlwZT86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ2g1JzpcbiAgICAgICAgICAgIHJldHVybiAn5rWP6KeI5Zmo6aKE6KeIJztcbiAgICAgICAgY2FzZSAnZWRpdG9yJzpcbiAgICAgICAgICAgIHJldHVybiAn57yW6L6R5Zmo6aKE6KeIJztcbiAgICAgICAgY2FzZSAnc2ltdWxhdG9yJzpcbiAgICAgICAgICAgIHJldHVybiAn5qih5ouf5ZmoJztcbiAgICAgICAgY2FzZSAnZGV2aWNlJzpcbiAgICAgICAgICAgIHJldHVybiAn55yf5py6JztcbiAgICAgICAgY2FzZSAndW5rbm93bic6XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gJ+acquefpeadpea6kCc7XG4gICAgfVxufVxuXG4vKiog5LuO6aG555uuIHNldHRpbmdzIOS4remAkuW9kuafpeaJvuaVsOWAvOerr+WPo+OAgiAqL1xuZnVuY3Rpb24gZmluZE51bWVyaWNQb3J0KGNmZzogYW55KTogbnVtYmVyIHtcbiAgICBpZiAoIWNmZyB8fCB0eXBlb2YgY2ZnICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjZmcucG9ydCA9PT0gJ251bWJlcicgJiYgY2ZnLnBvcnQgPiAwKSB7XG4gICAgICAgIHJldHVybiBjZmcucG9ydDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjZmcucG9ydCA9PT0gJ3N0cmluZycgJiYgIU51bWJlci5pc05hTihOdW1iZXIoY2ZnLnBvcnQpKSkge1xuICAgICAgICByZXR1cm4gTnVtYmVyKGNmZy5wb3J0KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKGNmZykpIHtcbiAgICAgICAgY29uc3QgdiA9IGNmZ1trXTtcbiAgICAgICAgaWYgKHYgJiYgdHlwZW9mIHYgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBjb25zdCBwID0gZmluZE51bWVyaWNQb3J0KHYpO1xuICAgICAgICAgICAgaWYgKHAgPiAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5cbi8qKlxuICog6K+75Y+W5b2T5YmN6aG555uu55qE6aKE6KeI6YWN572u77yM5b6X5Ye65rWP6KeI5Zmo6aKE5riv5Y+jL1VSTOOAglxuICog55So5LqO6Z2i5p2/5YaF5bWMIGlmcmFtZSDpooTop4jnmoTpu5jorqTlnLDlnYDjgIJcbiAqL1xuZnVuY3Rpb24gZ2V0UHJldmlld0luZm8oKTogeyBob3N0OiBzdHJpbmc7IHBvcnQ6IG51bWJlcjsgdXJsOiBzdHJpbmc7IGZvdW5kOiBzdHJpbmcgfSB7XG4gICAgY29uc3QgcHJvamVjdFBhdGggPSAoRWRpdG9yIGFzIGFueSkuUHJvamVjdD8ucGF0aDtcbiAgICBjb25zdCBjYW5kaWRhdGVzID0gWydzZXR0aW5ncy9wcmV2aWV3Lmpzb24nLCAnc2V0dGluZ3MvdjIvcGFja2FnZXMvcHJldmlldy5qc29uJ107XG4gICAgaWYgKHByb2plY3RQYXRoKSB7XG4gICAgICAgIGZvciAoY29uc3QgcmVsIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcCA9IGpvaW4ocHJvamVjdFBhdGgsIHJlbCk7XG4gICAgICAgICAgICAgICAgaWYgKCFleGlzdHNTeW5jKHApKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBjZmcgPSByZWFkSnNvblN5bmMocCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcG9ydCA9IGZpbmROdW1lcmljUG9ydChjZmcpO1xuICAgICAgICAgICAgICAgIGlmIChwb3J0ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBob3N0OiAnbG9jYWxob3N0JywgcG9ydCwgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDoke3BvcnR9L2AsIGZvdW5kOiBwIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgLy8g5b+955Wl6Kej5p6Q5aSx6LSl77yM5bCd6K+V5LiL5LiA5Liq5YCZ6YCJ5paH5Lu2XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgaG9zdDogJ2xvY2FsaG9zdCcsIHBvcnQ6IDc0NTYsIHVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NzQ1Ni8nLCBmb3VuZDogJycgfTtcbn1cblxuLyoqIOWkhOeQhuadpeiHqua4uOaIj+S+p+eahOa2iOaBr++8muS8mOWFiOWMuemFjSBwZW5kaW5nIOivt+axgu+8jOWQpuWImei/m+WFpeaXpeW/l+e8k+WGsuOAgiAqL1xuZnVuY3Rpb24gaGFuZGxlSW5jb21pbmcoZGF0YTogdW5rbm93bikge1xuICAgIGNvbnN0IG0gPSBkYXRhICYmIHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyA/IChkYXRhIGFzIGFueSkgOiBudWxsO1xuICAgIGlmIChtICYmIHR5cGVvZiBtLnJlcXVlc3RJZCA9PT0gJ251bWJlcicgJiYgcGVuZGluZy5oYXMobS5yZXF1ZXN0SWQpKSB7XG4gICAgICAgIGNvbnN0IHAgPSBwZW5kaW5nLmdldChtLnJlcXVlc3RJZCkhO1xuICAgICAgICBwZW5kaW5nLmRlbGV0ZShtLnJlcXVlc3RJZCk7XG4gICAgICAgIGlmIChwLnRpbWVyKSBjbGVhclRpbWVvdXQocC50aW1lcik7XG4gICAgICAgIHAucmVzb2x2ZShtLmRhdGEgPz8gbSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8g5ZG95Luk5Zue5YyFL+aPoeaJi+etieWGhemDqOWNj+iurua2iOaBr+S4jei/m+WFpeaXpeW/l++8jOmBv+WFjSByZXF1ZXN0SWQvcmVzcG9uc2UvaGVsbG8g5Yi35bGPXG4gICAgaWYgKG0gJiYgKG0uZXZ0ID09PSAncmVzcG9uc2UnIHx8IG0uZXZ0ID09PSAncmVxdWVzdCcgfHwgbS5ldnQgPT09ICdoZWxsbycpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcHVzaExvZyhkYXRhKTtcbn1cblxuLyoqIOaMiemZkOWItuadoeaVsOS4jue6p+WIq+ivu+WPluacgOi/keaXpeW/l++8iOS4jea4heepuue8k+WGsu+8jOS+m+mdouadvy9NQ1Ag5L2/55So77yJ44CCICovXG5mdW5jdGlvbiBnZXRMb2dzSW50ZXJuYWwobGltaXQ6IG51bWJlciwgbGV2ZWw6IHN0cmluZyk6IHVua25vd25bXSB7XG4gICAgY29uc3QgaXRlbXM6IHVua25vd25bXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSBsb2dCdWZmZXIubGVuZ3RoIC0gMTsgaSA+PSAwICYmIGl0ZW1zLmxlbmd0aCA8IGxpbWl0OyBpLS0pIHtcbiAgICAgICAgY29uc3QgaXQ6IGFueSA9IGxvZ0J1ZmZlcltpXTtcbiAgICAgICAgaWYgKCFpdCB8fCB0eXBlb2YgaXQgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyDov4fmu6Tmjonlv4Pot7Mv5o+h5omLL+mihOiniOW4p+etieWZquWjsO+8jOWPquS/neeVmeaOp+WItuWPsOS4juezu+e7n+a2iOaBr1xuICAgICAgICBpZiAoaXQuZXZ0ICE9PSAnY29uc29sZScgJiYgaXQuZXZ0ICE9PSAnc3lzJykge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxldmVsICYmIGl0LmV2dCA9PT0gJ2NvbnNvbGUnICYmIGl0LmxldmVsICE9PSBsZXZlbCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaXRlbXMudW5zaGlmdChpdCk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtcztcbn1cblxuLyoqIOi/lOWbniBNQ1Ag5pyN5Yqh54q25oCB5LiO6L+e5o6l6YWN572u77yIVVJMICsg5Luk54mM77yJ44CCICovXG5mdW5jdGlvbiBnZXRNY3BTdGF0ZSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBydW5uaW5nOiBtY3BIb3N0Py5pc1J1bm5pbmcgPz8gZmFsc2UsXG4gICAgICAgIHBvcnQ6IG1jcEhvc3Q/LmJvdW5kUG9ydCA/PyAwLFxuICAgICAgICB0b2tlbjogc2VydmVyVG9rZW4sXG4gICAgICAgIHVybDogbWNwSG9zdD8uaXNSdW5uaW5nID8gYGh0dHA6Ly8xMjcuMC4wLjE6JHttY3BIb3N0LmJvdW5kUG9ydH0vbWNwYCA6ICcnLFxuICAgIH07XG59XG5cbi8qKiDlkJHmuLjmiI/kvqfmoaXmjqXohJrmnKzlj5HpgIHkuIDmnaHor7fmsYLvvIzlubbnrYnlvoXlhbblm57ljIXjgIIgKi9cbmZ1bmN0aW9uIGNhbGxHYW1lKGNtZDogc3RyaW5nLCBwYXlsb2FkPzogdW5rbm93biwgdGltZW91dCA9IDUwMDApOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGlmICghc2VydmVyIHx8ICFzZXJ2ZXIuaXNSdW5uaW5nKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdXUyDmnI3liqHmnKrov5DooYzvvIzor7flhYjlkK/liqjmnI3liqEnKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVxdWVzdElkID0gKytyZXF1ZXN0U2VxO1xuICAgICAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHBlbmRpbmcuaGFzKHJlcXVlc3RJZCkpIHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nLmRlbGV0ZShyZXF1ZXN0SWQpO1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYOWRveS7pOi2heaXtig+JHt0aW1lb3V0fW1zKTogJHtjbWR9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0aW1lb3V0KTtcbiAgICAgICAgcGVuZGluZy5zZXQocmVxdWVzdElkLCB7IHJlc29sdmUsIHJlamVjdCwgdGltZXIgfSk7XG4gICAgICAgIHNlcnZlci5icm9hZGNhc3QoeyByZXF1ZXN0SWQsIGNtZCwgcGF5bG9hZCB9KTtcbiAgICB9KTtcbn1cblxuLyoqIOiOt+WPluWuv+S4u+acuuesrOS4gOS4qumdnuWGhee9kSBJUHY0IOWcsOWdgO+8iOeUqOS6juazqOWFpeahpeaOpeiEmuacrO+8jOS+m+aooeaLn+WZqC/nnJ/mnLrpgJrov4flsYDln5/nvZHov57kuIrmj5Lku7bmnI3liqHvvInjgIIgKi9cbmZ1bmN0aW9uIGdldEhvc3RMYW5JUCgpOiBzdHJpbmcge1xuICAgIC8vIOS8mOWFiOi/lOWbnuWGhee9keengeacieauteWcsOWdgO+8iFdpLUZpL+aciee6v+e9keWNoe+8ie+8jOmBv+WFjemAieWIsOiZmuaLn+acuuaIliBWUE4g6Jma5ouf572R5Y2h5a+86Ie055yf5py66L+e5LiN6YCaXG4gICAgbGV0IGZhbGxiYWNrID0gJyc7XG4gICAgdHJ5IHtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKG5ldHdvcmtJbnRlcmZhY2VzKCkpKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5ldCBvZiBuZXR3b3JrSW50ZXJmYWNlcygpW25hbWVdID8/IFtdKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5ldC5mYW1pbHkgPT09ICdJUHY0JyAmJiAhbmV0LmludGVybmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGEgPSBuZXQuYWRkcmVzcy5zcGxpdCgnLicpLm1hcChOdW1iZXIpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1ByaXZhdGUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgYVswXSA9PT0gMTAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIChhWzBdID09PSAxNzIgJiYgYVsxXSA+PSAxNiAmJiBhWzFdIDw9IDMxKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKGFbMF0gPT09IDE5MiAmJiBhWzFdID09PSAxNjgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNQcml2YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV0LmFkZHJlc3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2sgPSBuZXQuYWRkcmVzcztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgICAvKiBpZ25vcmUgKi9cbiAgICB9XG4gICAgcmV0dXJuIGZhbGxiYWNrO1xufVxuXG4vKipcbiAqIEB6aCDkuLrmianlsZXnmoTkuLvov5vnqIvnmoTms6jlhozmlrnms5VcbiAqL1xuLyoqIOaUtumbhuebruW9leS4i+aJgOaciSAuc2NlbmUg5paH5Lu244CCICovXG5mdW5jdGlvbiBjb2xsZWN0U2NlbmVGaWxlcyhkaXI6IHN0cmluZywgb3V0OiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGxldCBlbnRyaWVzO1xuICAgIHRyeSB7XG4gICAgICAgIGVudHJpZXMgPSByZWFkZGlyU3luYyhkaXIsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGUgb2YgZW50cmllcykge1xuICAgICAgICBjb25zdCBwID0gam9pbihkaXIsIGUubmFtZSk7XG4gICAgICAgIGlmIChlLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgIGNvbGxlY3RTY2VuZUZpbGVzKHAsIG91dCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZS5pc0ZpbGUoKSAmJiBlLm5hbWUuZW5kc1dpdGgoJy5zY2VuZScpKSB7XG4gICAgICAgICAgICBvdXQucHVzaChwKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqIOmBjeWOhuWcuuaZryBKU09OIOS4reeahOiKgueCueagke+8jOWvueWMuemFjeaMh+WumuiEmuacrCB1dWlkIOeahOe7hOS7tuaJp+ihjOWbnuiwg+OAgiAqL1xuZnVuY3Rpb24gd2Fsa1NjZW5lQ29tcG9uZW50cyhzY2VuZUpzb246IGFueSwgY29tcFV1aWQ6IHN0cmluZywgY2I6IChjb21wOiBhbnkpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCB3YWxrTm9kZSA9IChub2RlOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKCFub2RlIHx8IHR5cGVvZiBub2RlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLl9fdHlwZV9fID09PSAnY2MuTm9kZScpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYyBvZiBub2RlLl9jb21wb25lbnRzIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgaWYgKGMgJiYgYy5fX3R5cGVfXyA9PT0gY29tcFV1aWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2IoYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCBjaCBvZiBub2RlLl9jaGlsZHJlbiB8fCBbXSkge1xuICAgICAgICAgICAgICAgIHdhbGtOb2RlKGNoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgd2Fsa05vZGUoc2NlbmVKc29uICYmIHNjZW5lSnNvbi5zY2VuZSk7XG59XG5cbmV4cG9ydCBjb25zdCBtZXRob2RzOiB7IFtrZXk6IHN0cmluZ106ICguLi5hbnk6IGFueSkgPT4gYW55IH0gPSB7XG4gICAgb3BlblBhbmVsKCkge1xuICAgICAgICBFZGl0b3IuUGFuZWwub3BlbihwYWNrYWdlSlNPTi5uYW1lKTtcbiAgICB9LFxuXG4gICAgb3BlblByZXZpZXdQYW5lbCgpIHtcbiAgICAgICAgRWRpdG9yLlBhbmVsLm9wZW4oYCR7cGFja2FnZUpTT04ubmFtZX0ucHJldmlld2ApO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiDlkK/liqggV1Mg5pyN5Yqh44CC6L+U5Zue5b2T5YmN5pyN5Yqh54q25oCB44CCXG4gICAgICovXG4gICAgYXN5bmMgc3RhcnRTZXJ2ZXIocG9ydDogbnVtYmVyID0gREVGQVVMVF9QT1JUKSB7XG4gICAgICAgIGNvbnN0IHdzID0gZW5zdXJlU2VydmVyKCk7XG4gICAgICAgIHdzLnRva2VuID0gc2VydmVyVG9rZW47XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIXdzLmlzUnVubmluZykge1xuICAgICAgICAgICAgICAgIHdzLm9uKCdtZXNzYWdlJywgKF9jbGllbnQsIGRhdGEpID0+IGhhbmRsZUluY29taW5nKGRhdGEpKTtcbiAgICAgICAgICAgICAgICB3cy5vbignY29ubmVjdGlvbicsIChfY2xpZW50LCBpbmZvKSA9PiBwdXNoTG9nKHsgZXZ0OiAnc3lzJywgbXNnOiBg5a6i5oi356uv5bey6L+e5o6lICgke3R5cGVMYWJlbChpbmZvPy50eXBlKX0pYCB9KSk7XG4gICAgICAgICAgICAgICAgd3Mub24oJ2Rpc2Nvbm5lY3QnLCAoX2NsaWVudCwgaW5mbykgPT4gcHVzaExvZyh7IGV2dDogJ3N5cycsIG1zZzogYOWuouaIt+err+W3suaWreW8gCAoJHt0eXBlTGFiZWwoaW5mbz8udHlwZSl9KWAgfSkpO1xuICAgICAgICAgICAgICAgIHdzLm9uKCdhdXRoLWZhaWwnLCAoZ290OiBzdHJpbmcsIHVybDogc3RyaW5nKSA9PlxuICAgICAgICAgICAgICAgICAgICBwdXNoTG9nKHsgZXZ0OiAnc3lzJywgbXNnOiBg6L+e5o6l6KKr5ouS57ud77ya5a6i5oi356uv5Luk54mMKCR7Z290fSkg4omgIOacjeWKoeerr+S7pOeJjCgke3NlcnZlclRva2VufSlgIH0pKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB3cy5zdGFydChwb3J0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBwdXNoTG9nKHsgZXZ0OiAnc3lzJywgbXNnOiBg5ZCv5Yqo5pyN5Yqh5aSx6LSlOiAke1N0cmluZyhlcnIpfWAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdldFNlcnZlclN0YXRlKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOWBnOatoiBXUyDmnI3liqHjgILov5Tlm57lvZPliY3mnI3liqHnirbmgIHjgIJcbiAgICAgKi9cbiAgICBhc3luYyBzdG9wU2VydmVyKCkge1xuICAgICAgICBpZiAoc2VydmVyKSB7XG4gICAgICAgICAgICBhd2FpdCBzZXJ2ZXIuc3RvcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnZXRTZXJ2ZXJTdGF0ZSgpO1xuICAgIH0sXG5cbiAgICBnZXRTZXJ2ZXJTdGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIGdldFNlcnZlclN0YXRlKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOi/lOWbnuWbuuWumui/nuaOpeS7pOeJjO+8iOmdmeaAgSB0b2tlbu+8ieOAglxuICAgICAqL1xuICAgIGdldFRva2VuKCkge1xuICAgICAgICByZXR1cm4gc2VydmVyVG9rZW47XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOivu+WPluW9k+WJjemhueebrumihOiniOmFjee9ruW+l+WHuueahOmihOa4r+WPoy9VUkzvvIjkvpvpnaLmnb/lhoXltYwgaWZyYW1lIOeUqO+8ieOAglxuICAgICAqL1xuICAgIGdldFByZXZpZXdJbmZvKCkge1xuICAgICAgICByZXR1cm4gZ2V0UHJldmlld0luZm8oKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICog6K+75Y+W5b2T5YmN6aG555uu6K6+6K6h5YiG6L6o546H77yIUHJvamVjdCBTZXR0aW5ncyDihpIgZ2VuZXJhbC5kZXNpZ25SZXNvbHV0aW9u77yJ44CCXG4gICAgICog6aaW6YCJ57yW6L6R5Zmo5YaF572uIGBwcm9qZWN0L3F1ZXJ5LWNvbmZpZ2DvvIjlrp7ml7bor7vphY3nva7nvJPlrZjvvInvvIzlpJrmqKHlnZcv5oyJ6ZSu6YO96K+V5LiA6YGN77ybXG4gICAgICog5aSx6LSl5YaN6YCA5Zue5Yiw6K+7IHNldHRpbmdzL3YyL3BhY2thZ2VzL3Byb2plY3QuanNvbiDmlofku7bvvIzlhZzlupUgOTYww5c2NDDjgIJcbiAgICAgKi9cbiAgICBhc3luYyBnZXRQcm9qZWN0c1NldHRpbmdzKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgbW9kdWxlcyA9IFsnZ2VuZXJhbCcsICdlbmdpbmUnLCAncHJvamVjdCddO1xuICAgICAgICAgICAgZm9yIChjb25zdCBtb2Qgb2YgbW9kdWxlcykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGQgPSBhd2FpdCBFZGl0b3IuTWVzc2FnZS5yZXF1ZXN0KCdwcm9qZWN0JyBhcyBhbnksICdxdWVyeS1jb25maWcnIGFzIGFueSwgbW9kLCAnZGVzaWduUmVzb2x1dGlvbicpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZCAmJiBOdW1iZXIoZC53aWR0aCkgPiAwICYmIE51bWJlcihkLmhlaWdodCkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBkZXNpZ25SZXNvbHV0aW9uOiB7IHdpZHRoOiBOdW1iZXIoZC53aWR0aCksIGhlaWdodDogTnVtYmVyKGQuaGVpZ2h0KSB9IH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgLy8g6K+l5qih5Z2X5peg5q2k6YWN572u77yM5bCd6K+V5LiL5LiA5LiqXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIOe7p+e7rei1sOaWh+S7tuWFnOW6lVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByb2plY3RQYXRoID0gKEVkaXRvciBhcyBhbnkpLlByb2plY3Q/LnBhdGg7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZXMgPSBbXG4gICAgICAgICAgICAnc2V0dGluZ3MvdjIvcGFja2FnZXMvcHJvamVjdC5qc29uJyxcbiAgICAgICAgICAgICdzZXR0aW5ncy9wcm9qZWN0Lmpzb24nLFxuICAgICAgICBdO1xuICAgICAgICBpZiAocHJvamVjdFBhdGgpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVsIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwID0gam9pbihwcm9qZWN0UGF0aCwgcmVsKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNTeW5jKHApKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2ZnID0gcmVhZEpzb25TeW5jKHApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkID0gY2ZnICYmIGNmZy5nZW5lcmFsICYmIGNmZy5nZW5lcmFsLmRlc2lnblJlc29sdXRpb247XG4gICAgICAgICAgICAgICAgICAgIGlmIChkICYmIE51bWJlcihkLndpZHRoKSA+IDAgJiYgTnVtYmVyKGQuaGVpZ2h0KSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGRlc2lnblJlc29sdXRpb246IHsgd2lkdGg6IE51bWJlcihkLndpZHRoKSwgaGVpZ2h0OiBOdW1iZXIoZC5oZWlnaHQpIH0gfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICAvLyDlv73nlaXop6PmnpDlpLHotKXvvIzlsJ3or5XkuIvkuIDkuKrlgJnpgInmlofku7ZcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgZGVzaWduUmVzb2x1dGlvbjogeyB3aWR0aDogOTYwLCBoZWlnaHQ6IDY0MCB9IH07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOmdouadv+WQkea4uOaIj+S+p+ahpeaOpeiEmuacrOW5v+aSreS4gOadoSBmaXJlLWFuZC1mb3JnZXQg5ZG95Luk44CCXG4gICAgICogYXJnczogeyBjbWQ6IHN0cmluZywgcGF5bG9hZD86IGFueSB9XG4gICAgICovXG4gICAgc2VuZENvbW1hbmQoYXJnczogeyBjbWQ6IHN0cmluZzsgcGF5bG9hZD86IHVua25vd24gfSkge1xuICAgICAgICBpZiAoc2VydmVyKSB7XG4gICAgICAgICAgICBzZXJ2ZXIuYnJvYWRjYXN0KHsgY21kOiBhcmdzPy5jbWQsIHBheWxvYWQ6IGFyZ3M/LnBheWxvYWQgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdldFNlcnZlclN0YXRlKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOmdouadv+ivt+axgua4uOaIj+S+p+aVsOaNru+8muWQkea4uOaIj+WPkeW4piByZXF1ZXN0SWQg55qE5ZG95Luk5bm2562J5b6F5Zue5YyF44CCXG4gICAgICogYXJnczogeyBjbWQ6IHN0cmluZywgcGF5bG9hZD86IGFueSwgdGltZW91dD86IG51bWJlciB9XG4gICAgICovXG4gICAgYXN5bmMgcXVlcnlDb21tYW5kKGFyZ3M6IHsgY21kOiBzdHJpbmc7IHBheWxvYWQ/OiB1bmtub3duOyB0aW1lb3V0PzogbnVtYmVyIH0pIHtcbiAgICAgICAgY29uc3QgciA9IGF3YWl0IGNhbGxHYW1lKGFyZ3M/LmNtZCwgYXJncz8ucGF5bG9hZCwgYXJncz8udGltZW91dCA/PyA1MDAwKTtcbiAgICAgICAgcmV0dXJuIHI7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOWPluWbnuiHquS4iuasoeafpeivouS7peadpeaUtuWIsOeahOa2iOaBr++8iOa4uOaIjyDihpIg6Z2i5p2/77yJ44CC5oyJ5ri45qCH5aKe6YeP6K+75Y+W77yM5LiN56C05Z2P57yT5Yay44CCXG4gICAgICovXG4gICAgcXVlcnlMb2coKSB7XG4gICAgICAgIGNvbnN0IGJhdGNoID0gbG9nQnVmZmVyLnNsaWNlKGxvZ0N1cnNvcik7XG4gICAgICAgIGxvZ0N1cnNvciA9IGxvZ0J1ZmZlci5sZW5ndGg7XG4gICAgICAgIHJldHVybiBiYXRjaDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICog6K+75Y+W5pyA6L+R5pel5b+X77yI5LiN5riF56m657yT5Yay77yJ77yM5L6bIE1DUC9BSSBBZ2VudCDkvb/nlKjjgIJcbiAgICAgKiBhcmdzOiB7IGxpbWl0PzogbnVtYmVyLCBsZXZlbD86ICdhbGwnfCdsb2cnfCd3YXJuJ3wnZXJyb3InIH1cbiAgICAgKi9cbiAgICBnZXRMb2dzKGFyZ3M6IHsgbGltaXQ/OiBudW1iZXI7IGxldmVsPzogc3RyaW5nIH0pIHtcbiAgICAgICAgY29uc3QgbGltaXQgPSBNYXRoLm1heCgxLCBNYXRoLm1pbigyMDAsIE51bWJlcihhcmdzPy5saW1pdCkgfHwgNTApKTtcbiAgICAgICAgY29uc3QgbGV2ZWwgPSBhcmdzPy5sZXZlbCA9PT0gJ2xvZycgfHwgYXJncz8ubGV2ZWwgPT09ICd3YXJuJyB8fCBhcmdzPy5sZXZlbCA9PT0gJ2Vycm9yJyA/IGFyZ3MubGV2ZWwgOiAnJztcbiAgICAgICAgcmV0dXJuIGdldExvZ3NJbnRlcm5hbChsaW1pdCwgbGV2ZWwpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiDlkK/liqggTUNQIOacjeWKoe+8iEhUVFAgU3RyZWFtYWJsZe+8jOS+myBDb2RleCDnrYkgQUkgQWdlbnQg6L+e5o6l77yJ44CCXG4gICAgICovXG4gICAgYXN5bmMgc3RhcnRNY3AocG9ydDogbnVtYmVyID0gTUNQX0RFRkFVTFRfUE9SVCkge1xuICAgICAgICBpZiAoIW1jcEhvc3QpIHtcbiAgICAgICAgICAgIG1jcEhvc3QgPSBuZXcgTWNwSHR0cFNlcnZlcigpO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIW1jcEhvc3QuaXNSdW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdG9rZW4gPSBzZXJ2ZXJUb2tlbjtcbiAgICAgICAgICAgICAgICBhd2FpdCBtY3BIb3N0LnN0YXJ0KHBvcnQsIHRva2VuLCB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxHYW1lLFxuICAgICAgICAgICAgICAgICAgICBnZXRTZXJ2ZXJTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0VG9rZW46ICgpID0+IHNlcnZlclRva2VuLFxuICAgICAgICAgICAgICAgICAgICBnZXRMb2dzOiAobDogbnVtYmVyLCBsdjogc3RyaW5nKSA9PiBnZXRMb2dzSW50ZXJuYWwobCwgbHYpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHB1c2hMb2coeyBldnQ6ICdzeXMnLCBtc2c6IGBNQ1Ag5pyN5Yqh5bey5ZCv5YqoOiBodHRwOi8vMTI3LjAuMC4xOiR7bWNwSG9zdC5ib3VuZFBvcnR9L21jcGAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcHVzaExvZyh7IGV2dDogJ3N5cycsIG1zZzogYE1DUCDmnI3liqHlkK/liqjlpLHotKU6ICR7U3RyaW5nKGVycil9YCB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ2V0TWNwU3RhdGUoKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICog5YGc5q2iIE1DUCDmnI3liqHjgIJcbiAgICAgKi9cbiAgICBhc3luYyBzdG9wTWNwKCkge1xuICAgICAgICBpZiAobWNwSG9zdCkge1xuICAgICAgICAgICAgYXdhaXQgbWNwSG9zdC5zdG9wKCk7XG4gICAgICAgICAgICBwdXNoTG9nKHsgZXZ0OiAnc3lzJywgbXNnOiAnTUNQIOacjeWKoeW3suWBnOatoicgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdldE1jcFN0YXRlKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIOi/lOWbniBNQ1Ag5pyN5Yqh54q25oCB5LiO6L+e5o6l6YWN572u77yIVVJMICsg5Luk54mM77yJ44CCXG4gICAgICovXG4gICAgZ2V0TWNwU3RhdGUoKSB7XG4gICAgICAgIHJldHVybiBnZXRNY3BTdGF0ZSgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiDmiormuLjmiI/kvqfmoaXmjqXohJrmnKwgUnVudGltZUJyaWRnZS50cyDoh6rliqjlronoo4XliLDlvZPliY3pobnnm67nmoQgYXNzZXRzIOebruW9leOAglxuICAgICAqL1xuICAgIGFzeW5jIGluc3RhbGxCcmlkZ2UoKSB7XG4gICAgICAgIGNvbnN0IHByb2plY3RQYXRoID0gKEVkaXRvciBhcyBhbnkpLlByb2plY3Q/LnBhdGg7XG4gICAgICAgIGlmICghcHJvamVjdFBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgbXNnOiAn5peg5rOV6I635Y+W6aG555uu6Lev5b6E77yIRWRpdG9yLlByb2plY3QucGF0aCDkuLrnqbrvvIknIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3JjID0gam9pbihfX2Rpcm5hbWUsICcuLi9ydW50aW1lLWJyaWRnZS1zYW1wbGUvUnVudGltZUJyaWRnZS50cycpO1xuICAgICAgICBjb25zdCBhc3NldHNEaXIgPSBqb2luKHByb2plY3RQYXRoLCAnYXNzZXRzJyk7XG4gICAgICAgIGlmICghZXhpc3RzU3luYyhzcmMpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBvazogZmFsc2UsIG1zZzogYOacquaJvuWIsOahpeaOpeiEmuacrOaooeadvzogJHtzcmN9YCB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghZXhpc3RzU3luYyhhc3NldHNEaXIpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBvazogZmFsc2UsIG1zZzogYOaJvuS4jeWIsOmhueebrueahCBhc3NldHMg55uu5b2VOiAke2Fzc2V0c0Rpcn1gIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVzdCA9IGpvaW4oYXNzZXRzRGlyLCAnUnVudGltZUJyaWRnZS50cycpO1xuICAgICAgICBjb25zdCBvdmVyd3JvdGUgPSBleGlzdHNTeW5jKGRlc3QpO1xuICAgICAgICBjb25zdCBjdXJyZW50VG9rZW4gPSBzZXJ2ZXJUb2tlbjtcbiAgICAgICAgLy8g5L+d55WZ55So5oi36Ieq5a6a5LmJIGhvc3QvcG9ydO+8iOWmguecn+acuuiwg+ivleaXtuaUueS4uueUteiEkSBJUO+8ie+8jOmBv+WFjeavj+asoeimhuebluiiq+mHjee9ruOAglxuICAgICAgICAvLyDkvJjlhYjlj5blnLrmma/kuK3lt7LlrZjlnKjluLjpqbvoioLngrnnu4Tku7bnmoTnjrDlgLzvvIjnlKjmiLfmnIDov5Hlj6/og73nm7TmjqXlnKjoioLngrnkuIrphY3nva7vvInvvIxcbiAgICAgICAgLy8g5YW25qyh5Y+W5bey5a6J6KOF6ISa5pys5paH5Lu26YeM55qE6buY6K6k5YC844CCXG4gICAgICAgIGxldCBrZWVwSG9zdCA9ICcnO1xuICAgICAgICBsZXQga2VlcFBvcnQgPSAwO1xuICAgICAgICBpZiAob3Zlcndyb3RlKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9sZENvbnRlbnQgPSByZWFkRmlsZVN5bmMoZGVzdCwgJ3V0Zi04Jyk7XG4gICAgICAgICAgICAgICAgY29uc3QgaG0gPSAvaG9zdFxccyo9XFxzKicoW14nXSopJy8uZXhlYyhvbGRDb250ZW50KTtcbiAgICAgICAgICAgICAgICBjb25zdCBwbSA9IC9wb3J0XFxzKj1cXHMqKFxcZCspLy5leGVjKG9sZENvbnRlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChobSkge1xuICAgICAgICAgICAgICAgICAgICBrZWVwSG9zdCA9IGhtWzFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocG0pIHtcbiAgICAgICAgICAgICAgICAgICAga2VlcFBvcnQgPSBOdW1iZXIocG1bMV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgIC8qIOivu+WPluWksei0peWImeeUqOaooeadv+m7mOiupOWAvCAqL1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIOino+aekOahpeaOpeiEmuacrOe7hOS7tiB1dWlk77yM55So5LqO5Zyo5Zy65pmv5paH5Lu25Lit5a6a5L2N5bey5a2Y5Zyo55qEIFJ1bnRpbWVCcmlkZ2Ug57uE5Lu2XG4gICAgICAgIGxldCBjb21wVXVpZCA9ICcnO1xuICAgICAgICBjb25zdCBtZXRhUGF0aCA9IGRlc3QgKyAnLm1ldGEnO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGV4aXN0c1N5bmMobWV0YVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWV0YSA9IHJlYWRKc29uU3luYyhtZXRhUGF0aCk7XG4gICAgICAgICAgICAgICAgY29tcFV1aWQgPSAobWV0YSAmJiBtZXRhLnV1aWQpIHx8ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8qIOW/veeVpSBtZXRhIOivu+WPluWksei0pSAqL1xuICAgICAgICB9XG4gICAgICAgIGxldCBzY2VuZUZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBpZiAoY29tcFV1aWQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29sbGVjdFNjZW5lRmlsZXMoYXNzZXRzRGlyLCBzY2VuZUZpbGVzKTtcbiAgICAgICAgICAgICAgICAvLyDnrKzkuIDpgY3vvJrku6Xlt7LlrZjlnKjluLjpqbvoioLngrnnu4Tku7bkuIrnmoQgaG9zdC9wb3J0IOS4uuWHhu+8iOeUqOaIt+mFjee9ru+8ie+8jOimhuebluiEmuacrOaXp+WAvFxuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc3Agb2Ygc2NlbmVGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2ogPSByZWFkSnNvblN5bmMoc3ApO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2Fsa1NjZW5lQ29tcG9uZW50cyhzaiwgY29tcFV1aWQsIChjb21wKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb21wLmhvc3QgPT09ICdzdHJpbmcnICYmIGNvbXAuaG9zdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwSG9zdCA9IGNvbXAuaG9zdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb21wLnBvcnQgPT09ICdudW1iZXInICYmIGNvbXAucG9ydCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcFBvcnQgPSBjb21wLnBvcnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICAgICAgLyog5Y2V5Liq5Zy65pmv6Kej5p6Q5aSx6LSl6Lez6L+HICovXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAvKiDmiavmj4/lpLHotKXliJnot7Pov4flnLrmma/lkIzmraUgKi9cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyDmoaXmjqXohJrmnKzlhoXnva7lm7rlrprku6TniYwgd3d3Lnl5a2EuY27vvIzml6DpnIDms6jlhaXvvJtcbiAgICAgICAgLy8g5LuF5oqKIEJSSURHRV9WRVJTSU9OIOWQjOatpeS4uuaPkuS7tueJiOacrOWPt++8jOmBv+WFjemdouadv+aYvuekuui/h+aXtueJiOacrFxuICAgICAgICBjb25zdCBzcmNDb250ZW50ID0gcmVhZEZpbGVTeW5jKHNyYywgJ3V0Zi04Jyk7XG4gICAgICAgIGxldCBpbmplY3RlZCA9IHNyY0NvbnRlbnQucmVwbGFjZSgvQlJJREdFX1ZFUlNJT04gPSAnW14nXSonLywgYEJSSURHRV9WRVJTSU9OID0gJyR7cGFja2FnZUpTT04udmVyc2lvbn0nYCk7XG4gICAgICAgIC8vIOm7mOiupOi/nuaOpeWcsOWdgO+8mueUqOaIt+mFjee9rui/hyBob3N0IOWImeS/neeVme+8iOWmguecn+acuuiwg+ivleaXtuiHquWumuS5ieeahOeUteiEkSBJUO+8ie+8m1xuICAgICAgICAvLyDlkKbliJnoh6rliqjms6jlhaXlrr/kuLvmnLrlsYDln5/nvZEgSVAg4oCU4oCUIOWbuuWumiAxMjcuMC4wLjEg5pe255yf5py6L+aooeaLn+WZqOi/nueahOaYr+iuvuWkh+iHqui6q+WbnueOr++8jOaXoOazleaOpemAmuaPkuS7tuacjeWKoVxuICAgICAgICBjb25zdCBsYW5JUCA9IGdldEhvc3RMYW5JUCgpO1xuICAgICAgICBpZiAoa2VlcEhvc3QpIHtcbiAgICAgICAgICAgIGluamVjdGVkID0gaW5qZWN0ZWQucmVwbGFjZSgnaG9zdCA9IERFRkFVTFRfSE9TVDsnLCBgaG9zdCA9ICcke2tlZXBIb3N0fSc7YCk7XG4gICAgICAgIH0gZWxzZSBpZiAobGFuSVApIHtcbiAgICAgICAgICAgIGluamVjdGVkID0gaW5qZWN0ZWQucmVwbGFjZSgnaG9zdCA9IERFRkFVTFRfSE9TVDsnLCBgaG9zdCA9ICcke2xhbklQfSc7YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtlZXBQb3J0KSB7XG4gICAgICAgICAgICBpbmplY3RlZCA9IGluamVjdGVkLnJlcGxhY2UoJ3BvcnQgPSBERUZBVUxUX1BPUlQ7JywgYHBvcnQgPSAke2tlZXBQb3J0fTtgKTtcbiAgICAgICAgfVxuICAgICAgICB3cml0ZUZpbGVTeW5jKGRlc3QsIGluamVjdGVkLCAndXRmLTgnKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IEVkaXRvci5NZXNzYWdlLnJlcXVlc3QoJ2Fzc2V0LWRiJywgJ3JlZnJlc2gtYXNzZXQnLCBkZXN0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1t5eWthLXJ1bnRpbWUtaW5zcGVjdG9yXSByZWZyZXNoLWFzc2V0IGZhaWxlZDonLCBlcnIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIOesrOS6jOmBje+8muaKiuW3suWtmOWcqOW4uOmpu+iKgueCueeahCBob3N0L3BvcnQg5ZCM5q2l5Li65pyA5paw6YWN572u77ybXG4gICAgICAgIC8vIHRva2VuIOW3suaUueS4uuiEmuacrOWGhee9ruW4uOmHj++8jOmhuuW4pua4heaOieaXp+eJiOacrOWcuuaZr+mHjOaui+eVmeeahCB0b2tlbiDlrZfmrrXvvIzpgb/lhY3or6/lr7xcbiAgICAgICAgaWYgKGNvbXBVdWlkKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNwIG9mIHNjZW5lRmlsZXMpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzaiA9IHJlYWRKc29uU3luYyhzcCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHdhbGtTY2VuZUNvbXBvbmVudHMoc2osIGNvbXBVdWlkLCAoY29tcCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtlZXBIb3N0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcC5ob3N0ID0ga2VlcEhvc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoa2VlcFBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wLnBvcnQgPSBrZWVwUG9ydDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29tcC50b2tlbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgY29tcC50b2tlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZWVwSG9zdCB8fCBrZWVwUG9ydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlSnNvblN5bmMoc3AsIHNqLCB7IHNwYWNlczogMiB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbeXlrYS1ydW50aW1lLWluc3BlY3Rvcl0g5bey5ZCM5q2l5bi46am76IqC54K55bGe5oCnOiAke3NwfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBFZGl0b3IuTWVzc2FnZS5yZXF1ZXN0KCdhc3NldC1kYicsICdyZWZyZXNoLWFzc2V0Jywgc3ApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogaWdub3JlICovXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgLyog5Y2V5Liq5Zy65pmv5ZCM5q2l5aSx6LSl6Lez6L+HICovXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG9rOiB0cnVlLCBwYXRoOiBkZXN0LCBvdmVyd3JvdGUsIHRva2VuOiBjdXJyZW50VG9rZW4sIHNjZW5lczogc2NlbmVGaWxlcy5sZW5ndGggfTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICog6YCa55+l5ri45oiP5L6n6auY5LquL+mBrue9qeaMh+WumuiKgueCueOAgmlkIOS4uuepuuS4suWImea4hemZpOOAglxuICAgICAqL1xuICAgIGFzeW5jIGhpZ2hsaWdodE5vZGUoaWQ6IHN0cmluZywgbW9kZTogc3RyaW5nID0gJ2hpZ2hsaWdodCcpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGNhbGxHYW1lKCdoaWdobGlnaHQnLCB7IGlkOiBpZCB8fCAnJywgbW9kZTogbW9kZSA9PT0gJ21hc2snID8gJ21hc2snIDogJ2hpZ2hsaWdodCcgfSwgMzAwMCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGVycm9yOiBTdHJpbmcoZXJyKSB9O1xuICAgICAgICB9XG4gICAgfSxcbn07XG5cbi8qKlxuICogQHpoIOaJqeWxleWQr+WKqOaXtuiHquWKqOaLiei1tyBXUyDmnI3liqHvvIzkvr/kuo7muLjmiI/kvqfpmo/ml7bov57mjqXjgIJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvYWQoKSB7XG4gICAgY29uc29sZS5sb2coJ1t5eWthLXJ1bnRpbWUtaW5zcGVjdG9yXSBsb2FkLCBzdGFydGluZyB3cyBzZXJ2ZXIuLi4nKTtcbiAgICAvLyDku6TniYzkuLrlm7rlrprpnZnmgIHlgLzvvIzmnI3liqHlkK/liqjml7boh6rliqjluKbkuIrpibTmnYNcbiAgICBtZXRob2RzLnN0YXJ0U2VydmVyKCk7XG4gICAgLy8g5q+P5qyh5omT5byA5o+S5Lu26Ieq5Yqo5a6J6KOF5pyA5paw5qGl5o6l6ISa5pys77yI5L+d55WZ55So5oi36Ieq5a6a5LmJIGhvc3QvcG9ydO+8ie+8jOS/neivgea4uOaIj+S+p+iEmuacrOS4juaPkuS7tueJiOacrOWQjOatpVxuICAgIG1ldGhvZHMuaW5zdGFsbEJyaWRnZSgpLnRoZW4oKHJlczogeyBvaz86IGJvb2xlYW47IG92ZXJ3cm90ZT86IGJvb2xlYW47IHBhdGg/OiBzdHJpbmc7IG1zZz86IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIGlmIChyZXMgJiYgcmVzLm9rKSB7XG4gICAgICAgICAgICBwdXNoTG9nKHsgZXZ0OiAnc3lzJywgbXNnOiBg5qGl5o6l6ISa5pysJHtyZXMub3Zlcndyb3RlID8gJ+W3suabtOaWsCcgOiAn5bey5a6J6KOFJ306ICR7cmVzLnBhdGh9YCB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXMgJiYgcmVzLm1zZykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbeXlrYS1ydW50aW1lLWluc3BlY3Rvcl0gYXV0byBpbnN0YWxsQnJpZGdlIHNraXBwZWQ6JywgcmVzLm1zZyk7XG4gICAgICAgIH1cbiAgICB9KS5jYXRjaCgoZXJyOiB1bmtub3duKSA9PiB7XG4gICAgICAgIGNvbnNvbGUud2FybignW3l5a2EtcnVudGltZS1pbnNwZWN0b3JdIGF1dG8gaW5zdGFsbEJyaWRnZSBmYWlsZWQ6JywgZXJyKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAemgg5Y246L295omp5bGV5pe25YWz6ZetIFdTIOacjeWKoeOAglxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5sb2FkKCkge1xuICAgIGlmIChzZXJ2ZXIpIHtcbiAgICAgICAgc2VydmVyLnN0b3AoKTtcbiAgICAgICAgc2VydmVyID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKG1jcEhvc3QpIHtcbiAgICAgICAgbWNwSG9zdC5zdG9wKCk7XG4gICAgICAgIG1jcEhvc3QgPSBudWxsO1xuICAgIH1cbn0iXX0=