drawdown-svg-render
Version:
Svg renderer for drawdown diagrams
444 lines (371 loc) • 52.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Renderer = exports.MIN_WIDTH = exports.PADDING = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _d3Selection = require('d3-selection');
var _d3Zoom = require('d3-zoom');
var _d3Drag = require('d3-drag');
var _d3Hierarchy = require('d3-hierarchy');
var _link = require('./link');
var _shape = require('./shape');
var _arrowLabel = require('./arrow-label');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var PADDING = exports.PADDING = 10;
var MIN_WIDTH = exports.MIN_WIDTH = 100;
var LINE_HEIGHT = 20;
var LINK_STYLE_STRAIGHT = 'STRAIGHT';
var LINK_STYLE_CURVED = 'CURVED';
var NODE_STYLE_AUTO = 'AUTO';
var NODE_STYLE_RECTANGLE = 'RECTANGLE';
var NODE_STYLE_CIRCLE = 'CIRCLE';
var NODE_STYLE_ELLIPSE = 'ELLIPSE';
var NODE_STYLE_DIAMOND = 'DIAMOND';
var Renderer = exports.Renderer = function () {
function Renderer() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$onDidChangeLayou = _ref.onDidChangeLayout,
onDidChangeLayout = _ref$onDidChangeLayou === undefined ? function () {} : _ref$onDidChangeLayou,
_ref$onDidDragOrZoom = _ref.onDidDragOrZoom,
onDidDragOrZoom = _ref$onDidDragOrZoom === undefined ? function () {} : _ref$onDidDragOrZoom,
_ref$onDidRender = _ref.onDidRender,
onDidRender = _ref$onDidRender === undefined ? function (svg) {} : _ref$onDidRender,
_ref$diagramLayout = _ref.diagramLayout,
diagramLayout = _ref$diagramLayout === undefined ? {} : _ref$diagramLayout,
_ref$nodesStyle = _ref.nodesStyle,
nodesStyle = _ref$nodesStyle === undefined ? NODE_STYLE_AUTO : _ref$nodesStyle,
_ref$autoCenter = _ref.autoCenter,
autoCenter = _ref$autoCenter === undefined ? false : _ref$autoCenter;
_classCallCheck(this, Renderer);
this.onDidChangeLayout = onDidChangeLayout;
this.onDidDragOrZoom = onDidDragOrZoom;
this.onDidRender = onDidRender;
this.diagramLayout = diagramLayout;
this.nodesStyle = nodesStyle;
this.autoCenter = autoCenter;
}
_createClass(Renderer, [{
key: 'render',
value: function render(container, diagram) {
var layout = void 0;
if (this.diagramLayout[diagram.hash]) {
layout = this.diagramLayout[diagram.hash];
} else {
layout = this.autoLayout(diagram);
}
var _createScene = this.createScene(container, diagram, layout),
_createScene2 = _slicedToArray(_createScene, 2),
svg = _createScene2[0],
scene = _createScene2[1];
this.createDiagram(svg, scene, diagram, layout);
//fix text selection on user interaction
scene.selectAll('text').on('mousedown', function () {
(0, _d3Selection.select)('.dd-link-handle').classed('active', false);
_d3Selection.event.stopPropagation();
});
this.updateLinks(scene);
this.updateTimelines(scene);
this.onDidDragOrZoom(svg.node());
this.onDidRender(svg.node());
}
}, {
key: 'createScene',
value: function createScene(container, diagram, layout) {
var renderer = this;
var w = container.clientWidth;
var h = container.clientHeight;
var svg = (0, _d3Selection.select)(container).append('svg').attr('class', 'dd-diagram').attr("width", w).attr("height", 200).on('mousedown', function () {
(0, _d3Selection.select)(this).classed('focused', true);
_d3Selection.event.stopPropagation();
});
var workarea = svg.append('g').attr('class', 'workarea');
if (this.autoCenter) {
workarea.attr('transform', 'translate(' + w / 2 + ' ' + 0.02 * h + ')');
}
var scene = workarea.append('g').attr('class', 'scene').attr('transform', function () {
if (layout.transform) {
return 'translate(' + layout.transform.x + ' ' + layout.transform.y + ') scale(' + layout.transform.k + ')';
} else {
return 'translate(0 0) scale(1)';
}
});
scene.append('g').attr('class', 'dd-timelines');
scene.append('g').attr('class', 'dd-blocks');
scene.append('g').attr('class', 'dd-links');
this.createZoom(svg, scene, diagram, layout);
return [svg, scene];
}
}, {
key: 'createZoom',
value: function createZoom(svg, scene, diagram, layout) {
var renderer = this;
//set zoom behavior
svg.call((0, _d3Zoom.zoom)().scaleExtent([0.5, 1]).filter(function () {
if (!(0, _d3Selection.select)(this).classed('focused')) {
return false;
}
return !(_d3Selection.event.button || _d3Selection.event.shiftKey);
}).on('start', function () {
(0, _d3Selection.select)('.dd-link-handle').classed('active', false);
svg.selectAll('.selected').classed('selected', false);
}).on('zoom', function () {
diagram.transform = _d3Selection.event.transform;
scene.attr("transform", _d3Selection.event.transform);
renderer.onDidDragOrZoom(this);
}).on('end', function () {
renderer.onDidChangeLayout(diagram);
}));
//Setup zoom-and-drag behavior and initial transform
var it = (0, _d3Zoom.zoomTransform)(svg.node()); //initial transform
if (layout.transform) {
it = it.translate(layout.transform.x, layout.transform.y);
it = it.scale(layout.transform.k);
}
//a little bit hakish, but I want to set the zoom state
//without actually transforming the svg element
svg.node().__zoom = it;
// -----------------------------
// Setup Rect Selector
// -------------------------
svg.append('rect').attr('class', 'selector'); // <-- noobs often forget this comma :) Well, me also
(function () {
return; //This behavior is unstable for now. So bypass it.
var isSelecting = false;
var coords = {
x1: 0,
y1: 0,
x2: 0,
y2: 0
};
(0, _d3Selection.select)(document).on('mousedown', function () {
if (_d3Selection.event.target != svg.node()) {
return;
}
var screenM3x = svg.node().getScreenCTM();
coords.x1 = _d3Selection.event.x - screenM3x.e;
coords.y1 = _d3Selection.event.y - screenM3x.f;
isSelecting = true;
}).on('mousemove', function () {
if (!isSelecting) {
return;
}
var screenM3x = svg.node().getScreenCTM();
coords.x2 = _d3Selection.event.x - screenM3x.e;
coords.y2 = _d3Selection.event.y - screenM3x.f;
svg.classed('selecting', true);
svg.select('rect.selector').attr('x', Math.min(coords.x1, coords.x2)).attr('y', Math.min(coords.y1, coords.y2)).attr('width', Math.abs(coords.x1 - coords.x2)).attr('height', Math.abs(coords.y1 - coords.y2));
}).on('mouseup', function () {
if (!isSelecting) {
return;
}
isSelecting = false;
svg.classed('selecting', false);
var svgNode = svg.node();
var svgRect = svgNode.createSVGRect();
svgRect.x = Math.min(coords.x1, coords.x2);
svgRect.y = Math.min(coords.y1, coords.y2);
svgRect.width = Math.abs(coords.x1 - coords.x2);
svgRect.height = Math.abs(coords.y1 - coords.y2);
var list = svgNode.getIntersectionList(svgRect, svgNode);
var collection = [];
list.forEach(function (d) {
if (d.classList.contains('selectable')) {
collection.push(d);
d.classList.toggle('selected');
}
});
});
})();
}
/**
* Creates the diagram itself
* @param {d3selection} svg
* @param {d3selection} scene
* @param {object} diagram
* @param {object} layout
*/
}, {
key: 'createDiagram',
value: function createDiagram(svg, scene, diagram, layout) {
var renderer = this;
var nodeShape = (0, _shape.shapeGenerator)(this.nodesStyle);
//BLOCKS
var blocks = scene.select('.dd-blocks').selectAll('svg').data(diagram.blocks).enter().append('svg').attr('class', function (d) {
return 'dd-block dd-block-' + d.blockType.toLowerCase();
}).each(function (d) {
var lyt = layout.blocks[d.id] ? layout.blocks[d.id] : {};
d.layout = {
pos: lyt.pos ? _extends({}, lyt.pos) : { x: 0, y: 0 },
w: MIN_WIDTH, //lyt.w ? lyt.w : 0,
h: lyt.h ? lyt.h : 0,
links: lyt.links ? _extends({}, lyt.links) : { t: [], r: [], b: [], l: [] }
};
}).attr('x', function (d) {
return d.layout.pos.x;
}).attr('y', function (d) {
return d.layout.pos.y;
})
// .attr('width', d => d.layout.w)
// .attr('height', d => d.layout.h)
.call((0, _d3Drag.drag)().subject(function (d) {
return d.layout.pos;
}).on('drag', function (d) {
d.layout.pos.x = _d3Selection.event.x;
d.layout.pos.y = _d3Selection.event.y;
(0, _d3Selection.select)(this).attr("x", d.layout.pos.x).attr("y", d.layout.pos.y);
renderer.updateLinks(scene);
renderer.updateTimelines(scene);
renderer.onDidDragOrZoom(svg.node());
}).on('end', function () {
renderer.onDidChangeLayout(diagram);
}));
blocks.append('path');
blocks.append('text').attr('y', PADDING).html(function (d) {
return d.content;
});
blocks.each(function (d) {
var block = (0, _d3Selection.select)(this);
var text = block.select('text');
var path = block.select('path');
var lyt = layout.blocks[d.id];
var width = lyt ? lyt.w : MIN_WIDTH;
renderer.wrap(d.content, text.node(), width);
var bbox = text.node().getBBox();
d.layout.w = MIN_WIDTH;
d.layout.h = bbox.height;
text.attr('transform', 'translate(' + -bbox.width / 2 + ' ' + -bbox.height / 2 + ')');
path.attr('d', nodeShape);
block.attr('overflow', 'auto');
bbox = path.node().getBBox();
d.layout.bbw = bbox.width;
d.layout.bbh = bbox.height;
});
var links = scene.select('.dd-links').selectAll('g').data(diagram.links).enter().append('g').attr('class', 'dd-link').each(function (d) {
var link = (0, _d3Selection.select)(this);
link.append('path').attr('class', 'dd-link-tail').datum(d);
if (d.rh) {
link.append('path').attr('class', 'dd-link-head dd-link-head-right').datum(d);
}
if (d.lh) {
link.append('path').attr('class', 'dd-link-head dd-link-head-left').datum(d);
}
link.append('text').attr('class', 'dd-link-label').datum(d);
});
var timelines = scene.select('.dd-timelines').selectAll('line').data(diagram.blocks).enter().append('line').attr('class', 'dd-timeline');
}
/**
* Used to redraw the links between nodes
* @param d3Selection scene The scene container
*/
}, {
key: 'updateLinks',
value: function updateLinks(scene) {
var yStart = 0; //Used only in links of type "MESSAGE"
scene.selectAll('.dd-block').each(function (d) {
var y = d.layout.pos.y + d.layout.h + 50;
yStart = Math.max(yStart, y);
});
var links = scene.selectAll('.dd-link').each(function (d) {
var link = (0, _d3Selection.select)(this);
var tail = link.select('.dd-link-tail');
var leftHead = link.select('.dd-link-head-left');
var rightHead = link.select('.dd-link-head-right');
var label = link.select('.dd-link-label');
tail.attr('d', (0, _link.tailGenerator)(d.style, { yStart: yStart, ySeparation: 80 }));
rightHead.attr('d', _link.rightHead);
leftHead.attr('d', _link.leftHead);
(0, _arrowLabel.arrowLabel)(label, d, PADDING);
});
}
}, {
key: 'updateTimelines',
value: function updateTimelines(scene) {
var yStart = 0; //Used only in links of type "MESSAGE"
scene.selectAll('.dd-timeline').each(function (d) {
var y = d.layout.pos.y + d.layout.h + 50;
yStart = Math.max(yStart, y);
});
var yEnd = scene.selectAll('.dd-link').nodes().length * 80 + yStart;
scene.selectAll('.dd-timeline').attr('x1', function (d) {
return d.layout.pos.x;
}).attr('y1', function (d) {
return d.layout.pos.y + d.layout.h / 2;
}).attr('x2', function (d) {
return d.layout.pos.x;
}).attr('y2', yEnd);
}
}, {
key: 'wrap',
value: function wrap(text, textNode, width) {
//---clear previous---
textNode.innerHTML = '';
var textStyle = window.getComputedStyle(textNode);
var fontSize = parseFloat(textStyle.fontSize);
var words = text.split(' ');
var tSpan = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
tSpan.innerHTML = words.shift();
tSpan.setAttribute("y", fontSize);
tSpan.setAttribute("x", 0);
textNode.appendChild(tSpan);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = words[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var word = _step.value;
var currentText = tSpan.innerHTML;
tSpan.innerHTML += ' ' + word;
if (tSpan.getComputedTextLength() > width) {
tSpan.innerHTML = currentText;
tSpan = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
tSpan.setAttribute("x", 0);
tSpan.setAttribute("dy", fontSize);
tSpan.innerHTML = word;
textNode.appendChild(tSpan);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
}, {
key: 'autoLayout',
value: function autoLayout(diagram) {
var treeData = diagram.tree;
var root = (0, _d3Hierarchy.hierarchy)(treeData);
var tree = (0, _d3Hierarchy.tree)().nodeSize([3 * MIN_WIDTH, 1.3 * MIN_WIDTH])(root);
var layout = {
blocks: {}
};
root.each(function (d) {
var block = d.data.d;
if (!block) {
return;
}
layout.blocks[block.id] = {
pos: { x: d.x, y: d.y },
w: MIN_WIDTH,
h: 0,
links: { t: [], r: [], b: [], l: [] }
};
});
return layout;
}
}]);
return Renderer;
}();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oZWxwZXJzL1JlbmRlcmVyLmpzIl0sIm5hbWVzIjpbIlBBRERJTkciLCJNSU5fV0lEVEgiLCJMSU5FX0hFSUdIVCIsIkxJTktfU1RZTEVfU1RSQUlHSFQiLCJMSU5LX1NUWUxFX0NVUlZFRCIsIk5PREVfU1RZTEVfQVVUTyIsIk5PREVfU1RZTEVfUkVDVEFOR0xFIiwiTk9ERV9TVFlMRV9DSVJDTEUiLCJOT0RFX1NUWUxFX0VMTElQU0UiLCJOT0RFX1NUWUxFX0RJQU1PTkQiLCJSZW5kZXJlciIsIm9uRGlkQ2hhbmdlTGF5b3V0Iiwib25EaWREcmFnT3Jab29tIiwib25EaWRSZW5kZXIiLCJzdmciLCJkaWFncmFtTGF5b3V0Iiwibm9kZXNTdHlsZSIsImF1dG9DZW50ZXIiLCJjb250YWluZXIiLCJkaWFncmFtIiwibGF5b3V0IiwiaGFzaCIsImF1dG9MYXlvdXQiLCJjcmVhdGVTY2VuZSIsInNjZW5lIiwiY3JlYXRlRGlhZ3JhbSIsInNlbGVjdEFsbCIsIm9uIiwiY2xhc3NlZCIsImQzZXZlbnQiLCJzdG9wUHJvcGFnYXRpb24iLCJ1cGRhdGVMaW5rcyIsInVwZGF0ZVRpbWVsaW5lcyIsIm5vZGUiLCJyZW5kZXJlciIsInciLCJjbGllbnRXaWR0aCIsImgiLCJjbGllbnRIZWlnaHQiLCJhcHBlbmQiLCJhdHRyIiwid29ya2FyZWEiLCJ0cmFuc2Zvcm0iLCJ4IiwieSIsImsiLCJjcmVhdGVab29tIiwiY2FsbCIsInNjYWxlRXh0ZW50IiwiZmlsdGVyIiwiYnV0dG9uIiwic2hpZnRLZXkiLCJpdCIsInRyYW5zbGF0ZSIsInNjYWxlIiwiX196b29tIiwiaXNTZWxlY3RpbmciLCJjb29yZHMiLCJ4MSIsInkxIiwieDIiLCJ5MiIsImRvY3VtZW50IiwidGFyZ2V0Iiwic2NyZWVuTTN4IiwiZ2V0U2NyZWVuQ1RNIiwiZSIsImYiLCJzZWxlY3QiLCJNYXRoIiwibWluIiwiYWJzIiwic3ZnTm9kZSIsInN2Z1JlY3QiLCJjcmVhdGVTVkdSZWN0Iiwid2lkdGgiLCJoZWlnaHQiLCJsaXN0IiwiZ2V0SW50ZXJzZWN0aW9uTGlzdCIsImNvbGxlY3Rpb24iLCJmb3JFYWNoIiwiZCIsImNsYXNzTGlzdCIsImNvbnRhaW5zIiwicHVzaCIsInRvZ2dsZSIsIm5vZGVTaGFwZSIsImJsb2NrcyIsImRhdGEiLCJlbnRlciIsImJsb2NrVHlwZSIsInRvTG93ZXJDYXNlIiwiZWFjaCIsImx5dCIsImlkIiwicG9zIiwibGlua3MiLCJ0IiwiciIsImIiLCJsIiwic3ViamVjdCIsImh0bWwiLCJjb250ZW50IiwiYmxvY2siLCJ0ZXh0IiwicGF0aCIsIndyYXAiLCJiYm94IiwiZ2V0QkJveCIsImJidyIsImJiaCIsImxpbmsiLCJkYXR1bSIsInJoIiwibGgiLCJ0aW1lbGluZXMiLCJ5U3RhcnQiLCJtYXgiLCJ0YWlsIiwibGVmdEhlYWQiLCJyaWdodEhlYWQiLCJsYWJlbCIsInN0eWxlIiwieVNlcGFyYXRpb24iLCJsaW5rUmlnaHRIZWFkIiwibGlua0xlZnRIZWFkIiwieUVuZCIsIm5vZGVzIiwibGVuZ3RoIiwidGV4dE5vZGUiLCJpbm5lckhUTUwiLCJ0ZXh0U3R5bGUiLCJ3aW5kb3ciLCJnZXRDb21wdXRlZFN0eWxlIiwiZm9udFNpemUiLCJwYXJzZUZsb2F0Iiwid29yZHMiLCJzcGxpdCIsInRTcGFuIiwiY3JlYXRlRWxlbWVudE5TIiwic2hpZnQiLCJzZXRBdHRyaWJ1dGUiLCJhcHBlbmRDaGlsZCIsIndvcmQiLCJjdXJyZW50VGV4dCIsImdldENvbXB1dGVkVGV4dExlbmd0aCIsInRyZWVEYXRhIiwidHJlZSIsInJvb3QiLCJub2RlU2l6ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUFBOztBQUVBOztBQUNBOztBQUlBOztBQUVBOztBQU9BOztBQUVBOzs7O0FBRU8sSUFBTUEsNEJBQVUsRUFBaEI7QUFDQSxJQUFNQyxnQ0FBWSxHQUFsQjs7QUFFUCxJQUFNQyxjQUFjLEVBQXBCOztBQUdBLElBQU1DLHNCQUFzQixVQUE1QjtBQUNBLElBQU1DLG9CQUFv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QUFVLGFBQUs7QUFDYixZQUFJWSxRQUFRdkIsRUFBRU8sSUFBRixDQUFPUCxDQUFuQjtBQUNBLFlBQUksQ0FBQ3VCLEtBQUwsRUFBWTtBQUNWO0FBQ0Q7QUFDRHBGLGVBQU9tRSxNQUFQLENBQWNpQixNQUFNVixFQUFwQixJQUEwQjtBQUN4QkMsZUFBSyxFQUFDcEQsR0FBR3NDLEVBQUV0QyxDQUFOLEVBQVFDLEdBQUVxQyxFQUFFckMsQ0FBWixFQURtQjtBQUV4QlQsYUFBR2xDLFNBRnFCO0FBR3hCb0MsYUFBRyxDQUhxQjtBQUl4QjJELGlCQUFPLEVBQUNDLEdBQUcsRUFBSixFQUFPQyxHQUFHLEVBQVYsRUFBYUMsR0FBRyxFQUFoQixFQUFtQkMsR0FBRyxFQUF0QjtBQUppQixTQUExQjtBQU1ELE9BWEQ7O0FBYUEsYUFBT2hGLE1BQVA7QUFFRCIsImZpbGUiOiJSZW5kZXJlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNlbGVjdCBhcyBkM3NlbGVjdCB9IGZyb20gJ2QzLXNlbGVjdGlvbic7XG5pbXBvcnQgeyBzZWxlY3RBbGwgYXMgZDNzZWxlY3RBbGwgfSBmcm9tICdkMy1zZWxlY3Rpb24nO1xuaW1wb3J0IHsgem9vbSBhcyBkM3pvb20gfSBmcm9tICdkMy16b29tJztcbmltcG9ydCB7IGRyYWcgYXMgZDNkcmFnIH0gZnJvbSAnZDMtZHJhZyc7XG5pbXBvcnQgeyBldmVudCBhcyBkM2V2ZW50IH0gZnJvbSAnZDMtc2VsZWN0aW9uJztcbmltcG9ydCB7IHpvb21UcmFuc2Zvcm0gIGFzIGQzem9vbVRyYW5zZm9ybSB9IGZyb20gJ2QzLXpvb20nO1xuXG5pbXBvcnQgeyBoaWVyYXJjaHkgYXMgZDNIaWVyYXJjaHksIHRyZWUgYXMgZDNUcmVlIH0gZnJvbSAnZDMtaGllcmFyY2h5JztcblxuaW1wb3J0IHtcbiAgcmlnaHRIZWFkIGFzIGxpbmtSaWdodEhlYWQsXG4gIGxlZnRIZWFkIGFzIGxpbmtMZWZ0SGVhZCxcbiAgdGFpbEdlbmVyYXRvclxufSBmcm9tICcuL2xpbmsnO1xuXG5cbmltcG9ydCB7IHNoYXBlR2VuZXJhdG9yIH0gZnJvbSAnLi9zaGFwZSc7XG5cbmltcG9ydCB7IGFycm93TGFiZWwgfSBmcm9tICcuL2Fycm93LWxhYmVsJ1xuXG5leHBvcnQgY29uc3QgUEFERElORyA9IDEwO1xuZXhwb3J0IGNvbnN0IE1JTl9XSURUSCA9IDEwMDtcblxuY29uc3QgTElORV9IRUlHSFQgPSAyMDtcblxuXG5jb25zdCBMSU5LX1NUWUxFX1NUUkFJR0hUID0gJ1NUUkFJR0hUJztcbmNvbnN0IExJTktfU1RZTEVfQ1VSVkVEID0gJ0NVUlZFRCc7XG5cbmNvbnN0IE5PREVfU1RZTEVfQVVUTyA9ICdBVVRPJztcbmNvbnN0IE5PREVfU1RZTEVfUkVDVEFOR0xFID0gJ1JFQ1RBTkdMRSc7XG5jb25zdCBOT0RFX1NUWUxFX0NJUkNMRSA9ICdDSVJDTEUnO1xuY29uc3QgTk9ERV9TVFlMRV9FTExJUFNFID0gJ0VMTElQU0UnO1xuY29uc3QgTk9ERV9TVFlMRV9ESUFNT05EID0gJ0RJQU1PTkQnO1xuXG5leHBvcnQgY2xhc3MgUmVuZGVyZXIge1xuXG4gIGNvbnN0cnVjdG9yKHtcbiAgICAgIG9uRGlkQ2hhbmdlTGF5b3V0ID0gKCk9Pnt9LFxuICAgICAgb25EaWREcmFnT3Jab29tID0gKCk9Pnt9LFxuICAgICAgb25EaWRSZW5kZXIgPSAoc3ZnKT0+e30sXG4gICAgICBkaWFncmFtTGF5b3V0ID0ge30sXG4gICAgICBub2Rlc1N0eWxlID0gTk9ERV9TVFlMRV9BVVRPLFxuICAgICAgYXV0b0NlbnRlciA9IGZhbHNlLFxuICB9ID0ge30pIHtcbiAgICB0aGlzLm9uRGlkQ2hhbmdlTGF5b3V0ID0gb25EaWRDaGFuZ2VMYXlvdXQ7XG4gICAgdGhpcy5vbkRpZERyYWdPclpvb20gPSBvbkRpZERyYWdPclpvb207XG4gICAgdGhpcy5vbkRpZFJlbmRlciA9IG9uRGlkUmVuZGVyO1xuICAgIHRoaXMuZGlhZ3JhbUxheW91dCA9IGRpYWdyYW1MYXlvdXQ7XG4gICAgdGhpcy5ub2Rlc1N0eWxlID0gbm9kZXNTdHlsZTtcbiAgICB0aGlzLmF1dG9DZW50ZXIgPSBhdXRvQ2VudGVyO1xuICB9XG5cbiAgcmVuZGVyKGNvbnRhaW5lciwgZGlhZ3JhbSkge1xuXG4gICAgbGV0IGxheW91dDtcbiAgICBpZiAodGhpcy5kaWFncmFtTGF5b3V0W2RpYWdyYW0uaGFzaF0pIHtcbiAgICAgIGxheW91dCA9IHRoaXMuZGlhZ3JhbUxheW91dFtkaWFncmFtLmhhc2hdO1xuICAgIH0gZWxzZSB7XG4gICAgICBsYXlvdXQgPXRoaXMuYXV0b0xheW91dChkaWFncmFtKVxuICAgIH1cblxuICAgIGxldCBbc3ZnLCBzY2VuZV0gPSB0aGlzLmNyZWF0ZVNjZW5lKGNvbnRhaW5lciwgZGlhZ3JhbSwgbGF5b3V0KTtcblxuICAgIHRoaXMuY3JlYXRlRGlhZ3JhbShzdmcsIHNjZW5lLCBkaWFncmFtLCBsYXlvdXQpXG5cbiAgICAvL2ZpeCB0ZXh0IHNlbGVjdGlvbiBvbiB1c2VyIGludGVyYWN0aW9uXG4gICAgc2NlbmUuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgIC5vbignbW91c2Vkb3duJywgKCkgPT4ge1xuICAgICAgICBkM3NlbGVjdCgnLmRkLWxpbmstaGFuZGxlJykuY2xhc3NlZCgnYWN0aXZlJywgZmFsc2UpO1xuICAgICAgICBkM2V2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfSlcblxuICAgIHRoaXMudXBkYXRlTGlua3Moc2NlbmUpO1xuICAgIHRoaXMudXBkYXRlVGltZWxpbmVzKHNjZW5lKTtcbiAgICB0aGlzLm9uRGlkRHJhZ09yWm9vbShzdmcubm9kZSgpKTtcbiAgICB0aGlzLm9uRGlkUmVuZGVyKHN2Zy5ub2RlKCkpO1xuICB9XG5cbiAgY3JlYXRlU2NlbmUoY29udGFpbmVyLCBkaWFncmFtLCBsYXlvdXQpIHtcbiAgICBsZXQgcmVuZGVyZXIgPSB0aGlzO1xuICAgIGxldCB3ID0gY29udGFpbmVyLmNsaWVudFdpZHRoO1xuICAgIGxldCBoID0gY29udGFpbmVyLmNsaWVudEhlaWdodDtcblxuICAgIGxldCBzdmcgPSAgZDNzZWxlY3QoY29udGFpbmVyKS5hcHBlbmQoJ3N2ZycpXG4gICAgICAuYXR0cignY2xhc3MnLCAnZGQtZGlhZ3JhbScpXG4gICAgICAuYXR0cihcIndpZHRoXCIsIHcpXG4gICAgICAuYXR0cihcImhlaWdodFwiLCAyMDApXG4gICAgICAub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uKCl7XG4gICAgICAgIGQzc2VsZWN0KHRoaXMpLmNsYXNzZWQoJ2ZvY3VzZWQnLCB0cnVlKTtcbiAgICAgICAgZDNldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIH0pXG5cbiAgICBsZXQgd29ya2FyZWEgPSBzdmcuYXBwZW5kKCdnJylcbiAgICAgIC5hdHRyKCdjbGFzcycsICd3b3JrYXJlYScpO1xuXG4gICAgaWYgKHRoaXMuYXV0b0NlbnRlcikge1xuICAgICAgd29ya2FyZWEuYXR0cigndHJhbnNmb3JtJywgYHRyYW5zbGF0ZSgke3cvMn0gJHswLjAyKmh9KWApO1xuICAgIH1cblxuICAgIGxldCBzY2VuZSA9IHdvcmthcmVhLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdzY2VuZScpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAoKSA9PiB7XG4gICAgICAgICAgaWYgKGxheW91dC50cmFuc2Zvcm0pe1xuICAgICAgICAgICAgcmV0dXJuIGB0cmFuc2xhdGUoJHtsYXlvdXQudHJhbnNmb3JtLnh9ICR7bGF5b3V0LnRyYW5zZm9ybS55fSkgc2NhbGUoJHtsYXlvdXQudHJhbnNmb3JtLmt9KWBcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoMCAwKSBzY2FsZSgxKSdcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgc2NlbmUuYXBwZW5kKCdnJykuYXR0cignY2xhc3MnLCAnZGQtdGltZWxpbmVzJyk7XG4gICAgc2NlbmUuYXBwZW5kKCdnJykuYXR0cignY2xhc3MnLCAnZGQtYmxvY2tzJyk7XG4gICAgc2NlbmUuYXBwZW5kKCdnJykuYXR0cignY2xhc3MnLCAnZGQtbGlua3MnKTtcblxuICAgIHRoaXMuY3JlYXRlWm9vbShzdmcsIHNjZW5lLCBkaWFncmFtLCBsYXlvdXQpXG5cblxuICAgIHJldHVybiBbc3ZnLCBzY2VuZV07XG4gIH1cblxuICBjcmVhdGVab29tKHN2Zywgc2NlbmUsIGRpYWdyYW0sIGxheW91dCkge1xuICAgIGxldCByZW5kZXJlciA9IHRoaXM7XG4gICAgLy9zZXQgem9vbSBiZWhhdmlvclxuICAgIHN2Zy5jYWxsKGQzem9vbSgpLnNjYWxlRXh0ZW50KFswLjUsIDFdKVxuICAgICAgLmZpbHRlcihmdW5jdGlvbigpe1xuICAgICAgICAgIGlmICghZDNzZWxlY3QodGhpcykuY2xhc3NlZCgnZm9jdXNlZCcpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICByZXR1cm4gISAoZDNldmVudC5idXR0b24gfHwgZDNldmVudC5zaGlmdEtleSlcbiAgICAgICB9KVxuICAgICAgLm9uKCdzdGFydCcsICgpID0+IHtcbiAgICAgICAgZDNzZWxlY3QoJy5kZC1saW5rLWhhbmRsZScpLmNsYXNzZWQoJ2FjdGl2ZScsIGZhbHNlKTtcbiAgICAgICAgc3ZnLnNlbGVjdEFsbCgnLnNlbGVjdGVkJykuY2xhc3NlZCgnc2VsZWN0ZWQnLCBmYWxzZSlcbiAgICAgIH0pLm9uKCd6b29tJywgZnVuY3Rpb24oKXtcbiAgICAgICAgZGlhZ3JhbS50cmFuc2Zvcm0gPSBkM2V2ZW50LnRyYW5zZm9ybTtcbiAgICAgICAgc2NlbmUuYXR0cihcInRyYW5zZm9ybVwiLCBkM2V2ZW50LnRyYW5zZm9ybSk7XG4gICAgICAgIHJlbmRlcmVyLm9uRGlkRHJhZ09yWm9vbSh0aGlzKVxuICAgICAgfSkub24oJ2VuZCcsICgpID0+IHtcbiAgICAgICAgcmVuZGVyZXIub25EaWRDaGFuZ2VMYXlvdXQoZGlhZ3JhbSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvL1NldHVwIHpvb20tYW5kLWRyYWcgYmVoYXZpb3IgYW5kIGluaXRpYWwgdHJhbnNmb3JtXG4gICAgbGV0IGl0ID0gZDN6b29tVHJhbnNmb3JtKHN2Zy5ub2RlKCkpOyAvL2luaXRpYWwgdHJhbnNmb3JtXG4gICAgaWYgKGxheW91dC50cmFuc2Zvcm0pIHtcbiAgICAgIGl0ID0gaXQudHJhbnNsYXRlKGxheW91dC50cmFuc2Zvcm0ueCwgbGF5b3V0LnRyYW5zZm9ybS55KTtcbiAgICAgIGl0ID0gaXQuc2NhbGUobGF5b3V0LnRyYW5zZm9ybS5rKTtcbiAgICB9XG5cbiAgICAvL2EgbGl0dGxlIGJpdCBoYWtpc2gsIGJ1dCBJIHdhbnQgdG8gc2V0IHRoZSB6b29tIHN0YXRlXG4gICAgLy93aXRob3V0IGFjdHVhbGx5IHRyYW5zZm9ybWluZyB0aGUgc3ZnIGVsZW1lbnRcbiAgICBzdmcubm9kZSgpLl9fem9vbSA9IGl0O1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBTZXR1cCBSZWN0IFNlbGVjdG9yXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHN2Zy5hcHBlbmQoJ3JlY3QnKS5hdHRyKCdjbGFzcycsICdzZWxlY3RvcicpOyAvLyA8LS0gbm9vYnMgb2Z0ZW4gZm9yZ2V0IHRoaXMgY29tbWEgOikgV2VsbCwgbWUgYWxzb1xuXG4gICAgKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuOyAvL1RoaXMgYmVoYXZpb3IgaXMgdW5zdGFibGUgZm9yIG5vdy4gU28gYnlwYXNzIGl0LlxuICAgICAgdmFyIGlzU2VsZWN0aW5nID0gZmFsc2U7XG4gICAgICB2YXIgY29vcmRzID0ge1xuICAgICAgICB4MTogMCxcbiAgICAgICAgeTE6IDAsXG4gICAgICAgIHgyOiAwLFxuICAgICAgICB5MjogMFxuICAgICAgfVxuXG4gICAgICBkM3NlbGVjdChkb2N1bWVudClcbiAgICAgICAgLm9uKCdtb3VzZWRvd24nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAoZDNldmVudC50YXJnZXQgIT0gc3ZnLm5vZGUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsZXQgc2NyZWVuTTN4ID0gc3ZnLm5vZGUoKS5nZXRTY3JlZW5DVE0oKTtcbiAgICAgICAgICBjb29yZHMueDEgPSBkM2V2ZW50LnggLSBzY3JlZW5NM3guZTtcbiAgICAgICAgICBjb29yZHMueTEgPSBkM2V2ZW50LnkgLSBzY3JlZW5NM3guZjtcblxuICAgICAgICAgIGlzU2VsZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgfSkuXG4gICAgICAgIG9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAoIWlzU2VsZWN0aW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGxldCBzY3JlZW5NM3ggPSBzdmcubm9kZSgpLmdldFNjcmVlbkNUTSgpO1xuICAgICAgICAgIGNvb3Jkcy54MiA9IGQzZXZlbnQueCAtIHNjcmVlbk0zeC5lO1xuICAgICAgICAgIGNvb3Jkcy55MiA9IGQzZXZlbnQueSAtIHNjcmVlbk0zeC5mO1xuXG4gICAgICAgICAgc3ZnLmNsYXNzZWQoJ3NlbGVjdGluZycsIHRydWUpO1xuICAgICAgICAgIHN2Zy5zZWxlY3QoJ3JlY3Quc2VsZWN0b3InKVxuICAgICAgICAgICAgLmF0dHIoJ3gnLCBNYXRoLm1pbihjb29yZHMueDEsIGNvb3Jkcy54MikpXG4gICAgICAgICAgICAuYXR0cigneScsIE1hdGgubWluKGNvb3Jkcy55MSwgY29vcmRzLnkyKSlcbiAgICAgICAgICAgIC5hdHRyKCd3aWR0aCcsIE1hdGguYWJzKGNvb3Jkcy54MSAtIGNvb3Jkcy54MikpXG4gICAgICAgICAgICAuYXR0cignaGVpZ2h0JywgTWF0aC5hYnMoY29vcmRzLnkxIC0gY29vcmRzLnkyKSlcblxuICAgICAgICB9KVxuICAgICAgICAub24oJ21vdXNldXAnLCBmdW5jdGlvbigpe1xuICAgICAgICAgIGlmICghaXNTZWxlY3RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaXNTZWxlY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICBzdmcuY2xhc3NlZCgnc2VsZWN0aW5nJywgZmFsc2UpO1xuICAgICAgICAgIGxldCBzdmdOb2RlID0gc3ZnLm5vZGUoKTtcbiAgICAgICAgICBsZXQgc3ZnUmVjdCA9IHN2Z05vZGUuY3JlYXRlU1ZHUmVjdCgpO1xuICAgICAgICAgIHN2Z1JlY3QueCA9IE1hdGgubWluKGNvb3Jkcy54MSwgY29vcmRzLngyKTtcbiAgICAgICAgICBzdmdSZWN0LnkgPSBNYXRoLm1pbihjb29yZHMueTEsIGNvb3Jkcy55Mik7XG4gICAgICAgICAgc3ZnUmVjdC53aWR0aCA9IE1hdGguYWJzKGNvb3Jkcy54MSAtIGNvb3Jkcy54Mik7XG4gICAgICAgICAgc3ZnUmVjdC5oZWlnaHQgPSBNYXRoLmFicyhjb29yZHMueTEgLSBjb29yZHMueTIpO1xuXG4gICAgICAgICAgbGV0IGxpc3QgPSBzdmdOb2RlLmdldEludGVyc2VjdGlvbkxpc3Qoc3ZnUmVjdCwgc3ZnTm9kZSk7XG4gICAgICAgICAgbGV0IGNvbGxlY3Rpb24gPSBbXTtcbiAgICAgICAgICBsaXN0LmZvckVhY2goKGQpID0+IHtcbiAgICAgICAgICAgIGlmIChkLmNsYXNzTGlzdC5jb250YWlucygnc2VsZWN0YWJsZScpKSB7XG4gICAgICAgICAgICAgIGNvbGxlY3Rpb24ucHVzaChkKTtcbiAgICAgICAgICAgICAgZC5jbGFzc0xpc3QudG9nZ2xlKCdzZWxlY3RlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgIH0pKCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgZGlhZ3JhbSBpdHNlbGZcbiAgICogQHBhcmFtICB7ZDNzZWxlY3Rpb259IHN2Z1xuICAgKiBAcGFyYW0gIHtkM3NlbGVjdGlvbn0gc2NlbmVcbiAgICogQHBhcmFtICB7b2JqZWN0fSBkaWFncmFtXG4gICAqIEBwYXJhbSAge29iamVjdH0gbGF5b3V0XG4gICAqL1xuICBjcmVhdGVEaWFncmFtKHN2Zywgc2NlbmUsIGRpYWdyYW0sIGxheW91dCkge1xuICAgIGxldCByZW5kZXJlciA9IHRoaXM7XG4gICAgY29uc3Qgbm9kZVNoYXBlID0gc2hhcGVHZW5lcmF0b3IodGhpcy5ub2Rlc1N0eWxlKTtcbiAgICAvL0JMT0NLU1xuICAgIGxldCBibG9ja3MgPSBzY2VuZS5zZWxlY3QoJy5kZC1ibG9ja3MnKS5zZWxlY3RBbGwoJ3N2ZycpXG4gICAgICAuZGF0YShkaWFncmFtLmJsb2NrcykuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdzdmcnKVxuICAgICAgICAgIC5hdHRyKCdjbGFzcycsIGQ9PiAnZGQtYmxvY2sgZGQtYmxvY2stJyArIGQuYmxvY2tUeXBlLnRvTG93ZXJDYXNlKCkpXG4gICAgICAgICAgLmVhY2goZCA9PiB7XG4gICAgICAgICAgICAgIGxldCBseXQgPSBsYXlvdXQuYmxvY2tzW2QuaWRdID8gbGF5b3V0LmJsb2Nrc1tkLmlkXSA6IHt9O1xuICAgICAgICAgICAgICBkLmxheW91dCA9IHtcbiAgICAgICAgICAgICAgICBwb3M6IGx5dC5wb3MgPyB7Li4uIGx5dC5wb3N9IDoge3g6MCx5OjB9LFxuICAgICAgICAgICAgICAgIHc6IE1JTl9XSURUSCwgLy9seXQudyA/IGx5dC53IDogMCxcbiAgICAgICAgICAgICAgICBoOiBseXQuaCA/IGx5dC5oIDogMCxcbiAgICAgICAgICAgICAgICBsaW5rczogbHl0LmxpbmtzID8gey4uLiBseXQubGlua3N9IDoge3Q6IFtdLHI6IFtdLGI6IFtdLGw6IFtdfVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmF0dHIoJ3gnLCBkID0+IGQubGF5b3V0LnBvcy54KVxuICAgICAgICAgIC5hdHRyKCd5JywgZCA9PiBkLmxheW91dC5wb3MueSlcbiAgICAgICAgICAvLyAuYXR0cignd2lkdGgnLCBkID0+IGQubGF5b3V0LncpXG4gICAgICAgICAgLy8gLmF0dHIoJ2hlaWdodCcsIGQgPT4gZC5sYXlvdXQuaClcbiAgICAgICAgICAuY2FsbChkM2RyYWcoKVxuICAgICAgICAgICAgLnN1YmplY3QoZCA9PiBkLmxheW91dC5wb3MpXG4gICAgICAgICAgICAub24oJ2RyYWcnLCBmdW5jdGlvbihkKXtcblxuICAgICAgICAgICAgICBkLmxheW91dC5wb3MueCA9IGQzZXZlbnQueDtcbiAgICAgICAgICAgICAgZC5sYXlvdXQucG9zLnkgPSBkM2V2ZW50Lnk7XG4gICAgICAgICAgICAgIGQzc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLmF0dHIoXCJ4XCIsIGQubGF5b3V0LnBvcy54KVxuICAgICAgICAgICAgICAgIC5hdHRyKFwieVwiLCBkLmxheW91dC5wb3MueSk7XG4gICAgICAgICAgICAgIHJlbmRlcmVyLnVwZGF0ZUxpbmtzKHNjZW5lKTtcbiAgICAgICAgICAgICAgcmVuZGVyZXIudXBkYXRlVGltZWxpbmVzKHNjZW5lKTtcbiAgICAgICAgICAgICAgcmVuZGVyZXIub25EaWREcmFnT3Jab29tKHN2Zy5ub2RlKCkpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgICAgICAgIHJlbmRlcmVyLm9uRGlkQ2hhbmdlTGF5b3V0KGRpYWdyYW0pO1xuICAgICAgICAgICAgfSkpO1xuXG4gICAgYmxvY2tzLmFwcGVuZCgncGF0aCcpO1xuXG4gICAgYmxvY2tzLmFwcGVuZCgndGV4dCcpXG4gICAgICAuYXR0cigneScsIFBBRERJTkcpXG4gICAgICAuaHRtbChkID0+IGQuY29udGVudCk7XG5cbiAgICBibG9ja3MuZWFjaChmdW5jdGlvbihkKXtcbiAgICAgIGxldCBibG9jayA9IGQzc2VsZWN0KHRoaXMpO1xuICAgICAgbGV0IHRleHQgPSBibG9jay5zZWxlY3QoJ3RleHQnKTtcbiAgICAgIGxldCBwYXRoID0gYmxvY2suc2VsZWN0KCdwYXRoJyk7XG5cblxuICAgICAgbGV0IGx5dCA9IGxheW91dC5ibG9ja3NbZC5pZF07XG4gICAgICBsZXQgd2lkdGggPSBseXQgPyBseXQudyA6IE1JTl9XSURUSDtcblxuICAgICAgcmVuZGVyZXIud3JhcChkLmNvbnRlbnQsIHRleHQubm9kZSgpLCB3aWR0aClcbiAgICAgIGxldCBiYm94ID0gdGV4dC5ub2RlKCkuZ2V0QkJveCgpO1xuICAgICAgZC5sYXlvdXQudyA9IE1JTl9XSURUSDtcbiAgICAgIGQubGF5b3V0LmggPSBiYm94LmhlaWdodFxuXG5cbiAgICAgIHRleHQuYXR0cigndHJhbnNmb3JtJywgYHRyYW5zbGF0ZSgkey0oYmJveC53aWR0aCkgIC8gMn0gJHstKGJib3guaGVpZ2h0KS8yfSlgKVxuICAgICAgcGF0aC5hdHRyKCdkJywgbm9kZVNoYXBlKTtcbiAgICAgIGJsb2NrLmF0dHIoJ292ZXJmbG93JywgJ2F1dG8nKTtcblxuICAgICAgYmJveCA9IHBhdGgubm9kZSgpLmdldEJCb3goKTtcbiAgICAgIGQubGF5b3V0LmJidyA9IGJib3gud2lkdGg7XG4gICAgICBkLmxheW91dC5iYmggPSBiYm94LmhlaWdodDtcblxuICAgIH0pXG5cbiAgICBsZXQgbGlua3MgPSBzY2VuZS5zZWxlY3QoJy5kZC1saW5rcycpLnNlbGVjdEFsbCgnZycpXG4gICAgICAuZGF0YShkaWFncmFtLmxpbmtzKS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAgIC5hdHRyKCdjbGFzcycsICdkZC1saW5rJylcbiAgICAgICAgICAuZWFjaChmdW5jdGlvbihkKXtcbiAgICAgICAgICAgIGxldCBsaW5rID0gZDNzZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBsaW5rLmFwcGVuZCgncGF0aCcpLmF0dHIoJ2NsYXNzJywgJ2RkLWxpbmstdGFpbCcpLmRhdHVtKGQpO1xuICAgICAgICAgICAgaWYgKGQucmgpIHtcbiAgICAgICAgICAgICAgbGluay5hcHBlbmQoJ3BhdGgnKS5hdHRyKCdjbGFzcycsICdkZC1saW5rLWhlYWQgZGQtbGluay1oZWFkLXJpZ2h0JylcbiAgICAgICAgICAgICAgICAuZGF0dW0oZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZC5saCkge1xuICAgICAgICAgICAgICBsaW5rLmFwcGVuZCgncGF0aCcpLmF0dHIoJ2NsYXNzJywgJ2RkLWxpbmstaGVhZCBkZC1saW5rLWhlYWQtbGVmdCcpXG4gICAgICAgICAgICAgICAgLmRhdHVtKGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGluay5hcHBlbmQoJ3RleHQnKS5hdHRyKCdjbGFzcycsICdkZC1saW5rLWxhYmVsJykuZGF0dW0oZCk7XG4gICAgICAgICAgfSk7XG5cbiAgICBsZXQgdGltZWxpbmVzID0gc2NlbmUuc2VsZWN0KCcuZGQtdGltZWxpbmVzJykuc2VsZWN0QWxsKCdsaW5lJylcbiAgICAgIC5kYXRhKGRpYWdyYW0uYmxvY2tzKS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAgIC5hdHRyKCdjbGFzcycsICdkZC10aW1lbGluZScpO1xuICB9XG4gIC8qKlxuICAgKiBVc2VkIHRvIHJlZHJhdyB0aGUgbGlua3MgYmV0d2VlbiBub2Rlc1xuICAgKiBAcGFyYW0gIGQzU2VsZWN0aW9uIHNjZW5lIFRoZSBzY2VuZSBjb250YWluZXJcbiAgICovXG4gIHVwZGF0ZUxpbmtzKHNjZW5lKSB7XG5cbiAgICBsZXQgeVN0YXJ0ID0gMDsgLy9Vc2VkIG9ubHkgaW4gbGlua3Mgb2YgdHlwZSBcIk1FU1NBR0VcIlxuXG4gICAgc2NlbmUuc2VsZWN0QWxsKCcuZGQtYmxvY2snKS5lYWNoKChkKSA9PiB7XG4gICAgICBsZXQgeSA9IGQubGF5b3V0LnBvcy55ICsgZC5sYXlvdXQuaCArIDUwO1xuICAgICAgeVN0YXJ0ID0gTWF0aC5tYXgoeVN0YXJ0LCB5KVxuICAgIH0pO1xuXG4gICAgbGV0IGxpbmtzID0gc2NlbmUuc2VsZWN0QWxsKCcuZGQtbGluaycpXG4gICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIGNvbnN0IGxpbmsgPSBkM3NlbGVjdCh0aGlzKTtcbiAgICAgICAgY29uc3QgdGFpbCA9IGxpbmsuc2VsZWN0KCcuZGQtbGluay10YWlsJyk7XG4gICAgICAgIGNvbnN0IGxlZnRIZWFkID0gbGluay5zZWxlY3QoJy5kZC1saW5rLWhlYWQtbGVmdCcpO1xuICAgICAgICBjb25zdCByaWdodEhlYWQgPSBsaW5rLnNlbGVjdCgnLmRkLWxpbmstaGVhZC1yaWdodCcpO1xuICAgICAgICBjb25zdCBsYWJlbCA9IGxpbmsuc2VsZWN0KCcuZGQtbGluay1sYWJlbCcpO1xuXG4gICAgICAgIHRhaWwuYXR0cignZCcsIHRhaWxHZW5lcmF0b3IoZC5zdHlsZSwge3lTdGFydDogeVN0YXJ0LCB5U2VwYXJhdGlvbjogODB9KSk7XG4gICAgICAgIHJpZ2h0SGVhZC5hdHRyKCdkJywgbGlua1JpZ2h0SGVhZCk7XG4gICAgICAgIGxlZnRIZWFkLmF0dHIoJ2QnLCBsaW5rTGVmdEhlYWQpO1xuXG4gICAgICAgIGFycm93TGFiZWwobGFiZWwsIGQsIFBBRERJTkcpO1xuXG5cbiAgICAgIH0pXG5cbiAgfVxuXG4gIHVwZGF0ZVRpbWVsaW5lcyhzY2VuZSkge1xuICAgIGxldCB5U3RhcnQgPSAwOyAvL1VzZWQgb25seSBpbiBsaW5rcyBvZiB0eXBlIFwiTUVTU0FHRVwiXG5cbiAgICBzY2VuZS5zZWxlY3RBbGwoJy5kZC10aW1lbGluZScpLmVhY2goKGQpID0+IHtcbiAgICAgIGxldCB5ID0gZC5sYXlvdXQucG9zLnkgKyBkLmxheW91dC5oICsgNTA7XG4gICAgICB5U3RhcnQgPSBNYXRoLm1heCh5U3RhcnQsIHkpXG4gICAgfSk7XG5