UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

433 lines (424 loc) 58.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _window = _interopRequireDefault(require("global/window")); var _document = _interopRequireDefault(require("global/document")); var _console = _interopRequireDefault(require("global/console")); var _constants = require("@kepler.gl/constants"); var _domUtils = require("./dom-utils"); // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project /** * This file is copied from https://github.com/tsayen/dom-to-image * Modified by heshan0131 to allow loading external stylesheets and inline webfonts */ var inliner = newInliner(); var fontFaces = newFontFaces(); var images = newImages(); // Default impl options var defaultOptions = { // Default is to fail on error, no placeholder imagePlaceholder: undefined, // Default cache bust is false, it will use the cache cacheBust: false }; var domtoimage = { toSvg: toSvg, toPng: toPng, toJpeg: toJpeg, toBlob: toBlob, toPixelData: toPixelData, impl: { fontFaces: fontFaces, images: images, inliner: inliner, options: {} } }; /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @param {Function} [options.filter] - Should return true if passed node should be included in the output * (excluding node means excluding it's children as well). Not called on the root node. * @param {String} [options.bgcolor] - color for the background, any valid CSS color value. * @param {Number} [options.width] - width to be applied to node before rendering. * @param {Number} [options.height] - height to be applied to node before rendering. * @param {Object} [options.style] - an object whose properties to be copied to node's style before rendering. * @param {Number} [options.quality] - a Number between 0 and 1 indicating image quality (applicable to JPEG only), defaults to 1.0. * @param {boolean} [options.escapeXhtmlForWebpack] - whether to apply fix for uglify error in dom-to-image (should be true for webpack builds), defaults to true. * @param {String} [options.imagePlaceholder] - dataURL to use as a placeholder for failed images, default behaviour is to fail fast on images we can't fetch * @param {Boolean} [options.cacheBust] - set to true to cache bust by appending the time to the request url * @return {Promise} - A promise that is fulfilled with a SVG image data URL * */ function toSvg(node, options) { options = options || {}; copyOptions(options); return Promise.resolve(node).then(function (nd) { return cloneNode(nd, options.filter, true); }).then(embedFonts).then(inlineImages).then(applyOptions).then(function (clone) { return makeSvgDataUri(clone, options.width || (0, _domUtils.getWidth)(node), options.height || (0, _domUtils.getHeight)(node), options.escapeXhtmlForWebpack); }); function applyOptions(clone) { if (options.bgcolor) clone.style.backgroundColor = options.bgcolor; if (options.width) clone.style.width = "".concat(options.width, "px"); if (options.height) clone.style.height = "".concat(options.height, "px"); if (options.style) Object.keys(options.style).forEach(function (property) { clone.style[property] = options.style[property]; }); return clone; } } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @return {Promise} - A promise that is fulfilled with a Uint8Array containing RGBA pixel data. * */ function toPixelData(node, options) { return draw(node, options || {}).then(function (canvas) { return canvas.getContext('2d').getImageData(0, 0, (0, _domUtils.getWidth)(node), (0, _domUtils.getHeight)(node)).data; }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @return {Promise} - A promise that is fulfilled with a PNG image data URL * */ function toPng(node, options) { return draw(node, options || {}).then(function (canvas) { return canvas.toDataURL(); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @return {Promise} - A promise that is fulfilled with a JPEG image data URL * */ function toJpeg(node, options) { options = options || {}; return draw(node, options).then(function (canvas) { return canvas.toDataURL('image/jpeg', options.quality || 1.0); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @return {Promise} - A promise that is fulfilled with a PNG image blob * */ function toBlob(node, options) { return draw(node, options || {}).then(_domUtils.canvasToBlob); } function copyOptions(options) { // Copy options to impl options for use in impl if (typeof options.imagePlaceholder === 'undefined') { domtoimage.impl.options.imagePlaceholder = defaultOptions.imagePlaceholder; } else { domtoimage.impl.options.imagePlaceholder = options.imagePlaceholder; } if (typeof options.cacheBust === 'undefined') { domtoimage.impl.options.cacheBust = defaultOptions.cacheBust; } else { domtoimage.impl.options.cacheBust = options.cacheBust; } } function draw(domNode, options) { return toSvg(domNode, options).then(_domUtils.makeImage).then((0, _domUtils.delay)(100)).then(function (image) { var canvas = newCanvas(domNode); canvas.getContext('2d').drawImage(image, 0, 0); return canvas; }); function newCanvas(dNode) { var canvas = _document["default"].createElement('canvas'); canvas.width = options.width || (0, _domUtils.getWidth)(dNode); canvas.height = options.height || (0, _domUtils.getHeight)(dNode); if (options.bgcolor) { var ctx = canvas.getContext('2d'); ctx.fillStyle = options.bgcolor; ctx.fillRect(0, 0, canvas.width, canvas.height); } return canvas; } } function cloneNode(node, filter, root) { if (!root && filter && !filter(node)) { return Promise.resolve(); } return Promise.resolve(node).then(makeNodeCopy).then(function (clone) { return cloneChildren(node, clone, filter); }).then(function (clone) { return (0, _domUtils.processClone)(node, clone); }); function makeNodeCopy(nd) { if (nd instanceof _window["default"].HTMLCanvasElement) { return (0, _domUtils.makeImage)(nd.toDataURL()); } return nd.cloneNode(false); } function cloneChildrenInOrder(parent, arrChildren, flt) { var done = Promise.resolve(); arrChildren.forEach(function (child) { done = done.then(function () { return cloneNode(child, flt, null); }).then(function (childClone) { if (childClone) { parent.appendChild(childClone); } }); }); return done; } function cloneChildren(original, clone, flt) { var children = original.childNodes; if (children.length === 0) { return Promise.resolve(clone); } return cloneChildrenInOrder(clone, (0, _domUtils.asArray)(children), flt).then(function () { return clone; }); } } function embedFonts(node) { return fontFaces.resolveAll().then(function (cssText) { var styleNode = _document["default"].createElement('style'); node.appendChild(styleNode); styleNode.appendChild(_document["default"].createTextNode(cssText)); return node; }); } function inlineImages(node) { return images.inlineAll(node).then(function () { return node; }); } function makeSvgDataUri(node, width, height) { var escapeXhtmlForWebpack = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; return Promise.resolve(node).then(function (nd) { nd.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); var serializedString = new _window["default"].XMLSerializer().serializeToString(nd); var xhtml = escapeXhtmlForWebpack ? (0, _domUtils.escapeXhtml)(serializedString) : serializedString; var foreignObject = "<foreignObject x=\"0\" y=\"0\" width=\"100%\" height=\"100%\">".concat(xhtml, "</foreignObject>"); var svgStr = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"".concat(width, "\" height=\"").concat(height, "\">").concat(foreignObject, "</svg>"); // Use base64 encoding var base64Svg; if (typeof Buffer !== 'undefined' && Buffer.from) { base64Svg = Buffer.from(svgStr, 'utf8').toString('base64'); } else if (typeof TextEncoder !== 'undefined') { // Modern browsers: TextEncoder handles Unicode → UTF-8 bytes // Must chunk to avoid call stack limits with large arrays var bytes = new TextEncoder().encode(svgStr); var CHUNK_SIZE = 8192; var binary = ''; for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { binary += String.fromCharCode.apply(null, Array.from(bytes.slice(i, i + CHUNK_SIZE))); } base64Svg = _window["default"].btoa(binary); } else { throw new Error('No base64 encoder found'); } return "data:image/svg+xml;base64,".concat(base64Svg); }); } function newInliner() { var URL_REGEX = /url\(['"]?([^'"]+?)['"]?\)/g; return { inlineAll: inlineAll, shouldProcess: shouldProcess, impl: { readUrls: readUrls, inline: inline } }; function shouldProcess(string) { return string.search(URL_REGEX) !== -1; } function readUrls(string) { var result = []; var match; while ((match = URL_REGEX.exec(string)) !== null) { result.push(match[1]); } return result.filter(function (url) { return !(0, _domUtils.isDataUrl)(url); }); } function urlAsRegex(url0) { return new RegExp("(url\\(['\"]?)(".concat((0, _domUtils.escape)(url0), ")(['\"]?\\))"), 'g'); } function inline(string, url, baseUrl, get) { return Promise.resolve(url).then(function (ul) { return baseUrl ? (0, _domUtils.resolveUrl)(ul, baseUrl) : ul; }).then(function (ul) { return typeof get === 'function' ? get(ul) : (0, _domUtils.getAndEncode)(ul, domtoimage.impl.options); }).then(function (data) { return (0, _domUtils.dataAsUrl)(data, (0, _domUtils.mimeType)(url)); }).then(function (dataUrl) { return string.replace(urlAsRegex(url), "$1".concat(dataUrl, "$3")); }); } function inlineAll(string, baseUrl, get) { if (!shouldProcess(string) || (0, _domUtils.isSrcAsDataUrl)(string)) { return Promise.resolve(string); } return Promise.resolve(string).then(readUrls).then(function (urls) { var done = Promise.resolve(string); urls.forEach(function (url) { done = done.then(function (str) { return inline(str, url, baseUrl, get); }); }); return done; }); } } function newFontFaces() { return { resolveAll: resolveAll, impl: { readAll: readAll } }; function resolveAll() { return readAll().then(function (webFonts) { return Promise.all(webFonts.map(function (webFont) { return webFont.resolve(); })); }).then(function (cssStrings) { return cssStrings.join('\n'); }); } function readAll() { return Promise.resolve((0, _domUtils.asArray)(_document["default"].styleSheets)).then(loadExternalStyleSheets).then(getCssRules).then(selectWebFontRules).then(function (rules) { return rules.map(newWebFont); }); function selectWebFontRules(cssRules) { return cssRules.filter(function (rule) { return rule.type === _window["default"].CSSRule.FONT_FACE_RULE; }).filter(function (rule) { return inliner.shouldProcess(rule.style.getPropertyValue('src')); }); } function loadExternalStyleSheets(styleSheets) { return Promise.all(styleSheets.map(function (sheet) { if (sheet.href) { // cloudfont doesn't have allow origin header properly set // error response will remain in cache var cache = sheet.href.includes('uber-fonts') ? 'no-cache' : 'default'; return _window["default"].fetch(sheet.href, { credentials: 'omit', cache: cache }).then(function (response) { return response.text(); }).then(function (text) { var result = (0, _domUtils.setStyleSheetBaseHref)(text, sheet.href); return (0, _domUtils.toStyleSheet)(result); })["catch"](function (err) { // Handle any error that occurred in any of the previous // promises in the chain. stylesheet failed to load should not stop // the process, hence result in only a warning, instead of reject _console["default"].warn(_constants.IMAGE_EXPORT_ERRORS.styleSheet, sheet.href); _console["default"].log(err); return; }); } return Promise.resolve(sheet); })); } function getCssRules(styleSheets) { var cssRules = []; styleSheets.forEach(function (sheet) { // try...catch because browser may not able to enumerate rules for cross-domain sheets if (!sheet) { return; } var rules; try { rules = sheet.rules || sheet.cssRules; } catch (e) { _console["default"].log("'Can't read the css rules of: ".concat(sheet.href), e); return; } if (rules && (0, _typeof2["default"])(rules) === 'object') { try { (0, _domUtils.asArray)(rules || []).forEach(cssRules.push.bind(cssRules)); } catch (e) { _console["default"].log("Error while reading CSS rules from ".concat(sheet.href), e); return; } } else { _console["default"].log('getCssRules can not find cssRules'); return; } }); return cssRules; } function newWebFont(webFontRule) { return { resolve: function resolve() { var baseUrl = (webFontRule.parentStyleSheet || {}).href; return inliner.inlineAll(webFontRule.cssText, baseUrl, null); }, src: function src() { return webFontRule.style.getPropertyValue('src'); } }; } } } function newImages() { return { inlineAll: inlineAll, impl: { newImage: newImage } }; function newImage(element) { function inline(get) { if ((0, _domUtils.isDataUrl)(element.src)) { return Promise.resolve(); } return Promise.resolve(element.src).then(function (ul) { return typeof get === 'function' ? get(ul) : (0, _domUtils.getAndEncode)(ul, domtoimage.impl.options); }).then(function (data) { return (0, _domUtils.dataAsUrl)(data, (0, _domUtils.mimeType)(element.src)); }).then(function (dataUrl) { return new Promise(function (resolve, reject) { element.onload = resolve; element.onerror = reject; element.src = dataUrl; }); }); } return { inline: inline }; } function inlineAll(node) { if (!(node instanceof Element)) { return Promise.resolve(node); } return inlineBackground(node).then(function () { if (node instanceof HTMLImageElement) { return newImage(node).inline(null); } return Promise.all((0, _domUtils.asArray)(node.childNodes).map(function (child) { return inlineAll(child); })); }); function inlineBackground(nd) { var background = nd.style.getPropertyValue('background'); if (!background) { return Promise.resolve(nd); } return inliner.inlineAll(background, null, null).then(function (inlined) { nd.style.setProperty('background', inlined, nd.style.getPropertyPriority('background')); }).then(function () { return nd; }); } } } var _default = exports["default"] = domtoimage; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfd2luZG93IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZG9jdW1lbnQiLCJfY29uc29sZSIsIl9jb25zdGFudHMiLCJfZG9tVXRpbHMiLCJpbmxpbmVyIiwibmV3SW5saW5lciIsImZvbnRGYWNlcyIsIm5ld0ZvbnRGYWNlcyIsImltYWdlcyIsIm5ld0ltYWdlcyIsImRlZmF1bHRPcHRpb25zIiwiaW1hZ2VQbGFjZWhvbGRlciIsInVuZGVmaW5lZCIsImNhY2hlQnVzdCIsImRvbXRvaW1hZ2UiLCJ0b1N2ZyIsInRvUG5nIiwidG9KcGVnIiwidG9CbG9iIiwidG9QaXhlbERhdGEiLCJpbXBsIiwib3B0aW9ucyIsIm5vZGUiLCJjb3B5T3B0aW9ucyIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsIm5kIiwiY2xvbmVOb2RlIiwiZmlsdGVyIiwiZW1iZWRGb250cyIsImlubGluZUltYWdlcyIsImFwcGx5T3B0aW9ucyIsImNsb25lIiwibWFrZVN2Z0RhdGFVcmkiLCJ3aWR0aCIsImdldFdpZHRoIiwiaGVpZ2h0IiwiZ2V0SGVpZ2h0IiwiZXNjYXBlWGh0bWxGb3JXZWJwYWNrIiwiYmdjb2xvciIsInN0eWxlIiwiYmFja2dyb3VuZENvbG9yIiwiY29uY2F0IiwiT2JqZWN0Iiwia2V5cyIsImZvckVhY2giLCJwcm9wZXJ0eSIsImRyYXciLCJjYW52YXMiLCJnZXRDb250ZXh0IiwiZ2V0SW1hZ2VEYXRhIiwiZGF0YSIsInRvRGF0YVVSTCIsInF1YWxpdHkiLCJjYW52YXNUb0Jsb2IiLCJkb21Ob2RlIiwibWFrZUltYWdlIiwiZGVsYXkiLCJpbWFnZSIsIm5ld0NhbnZhcyIsImRyYXdJbWFnZSIsImROb2RlIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwiY3R4IiwiZmlsbFN0eWxlIiwiZmlsbFJlY3QiLCJyb290IiwibWFrZU5vZGVDb3B5IiwiY2xvbmVDaGlsZHJlbiIsInByb2Nlc3NDbG9uZSIsIldpbmRvdyIsIkhUTUxDYW52YXNFbGVtZW50IiwiY2xvbmVDaGlsZHJlbkluT3JkZXIiLCJwYXJlbnQiLCJhcnJDaGlsZHJlbiIsImZsdCIsImRvbmUiLCJjaGlsZCIsImNoaWxkQ2xvbmUiLCJhcHBlbmRDaGlsZCIsIm9yaWdpbmFsIiwiY2hpbGRyZW4iLCJjaGlsZE5vZGVzIiwibGVuZ3RoIiwiYXNBcnJheSIsInJlc29sdmVBbGwiLCJjc3NUZXh0Iiwic3R5bGVOb2RlIiwiY3JlYXRlVGV4dE5vZGUiLCJpbmxpbmVBbGwiLCJhcmd1bWVudHMiLCJzZXRBdHRyaWJ1dGUiLCJzZXJpYWxpemVkU3RyaW5nIiwiWE1MU2VyaWFsaXplciIsInNlcmlhbGl6ZVRvU3RyaW5nIiwieGh0bWwiLCJlc2NhcGVYaHRtbCIsImZvcmVpZ25PYmplY3QiLCJzdmdTdHIiLCJiYXNlNjRTdmciLCJCdWZmZXIiLCJmcm9tIiwidG9TdHJpbmciLCJUZXh0RW5jb2RlciIsImJ5dGVzIiwiZW5jb2RlIiwiQ0hVTktfU0laRSIsImJpbmFyeSIsImkiLCJTdHJpbmciLCJmcm9tQ2hhckNvZGUiLCJhcHBseSIsIkFycmF5Iiwic2xpY2UiLCJidG9hIiwiRXJyb3IiLCJVUkxfUkVHRVgiLCJzaG91bGRQcm9jZXNzIiwicmVhZFVybHMiLCJpbmxpbmUiLCJzdHJpbmciLCJzZWFyY2giLCJyZXN1bHQiLCJtYXRjaCIsImV4ZWMiLCJwdXNoIiwidXJsIiwiaXNEYXRhVXJsIiwidXJsQXNSZWdleCIsInVybDAiLCJSZWdFeHAiLCJlc2NhcGUiLCJiYXNlVXJsIiwiZ2V0IiwidWwiLCJyZXNvbHZlVXJsIiwiZ2V0QW5kRW5jb2RlIiwiZGF0YUFzVXJsIiwibWltZVR5cGUiLCJkYXRhVXJsIiwicmVwbGFjZSIsImlzU3JjQXNEYXRhVXJsIiwidXJscyIsInN0ciIsInJlYWRBbGwiLCJ3ZWJGb250cyIsImFsbCIsIm1hcCIsIndlYkZvbnQiLCJjc3NTdHJpbmdzIiwiam9pbiIsInN0eWxlU2hlZXRzIiwibG9hZEV4dGVybmFsU3R5bGVTaGVldHMiLCJnZXRDc3NSdWxlcyIsInNlbGVjdFdlYkZvbnRSdWxlcyIsInJ1bGVzIiwibmV3V2ViRm9udCIsImNzc1J1bGVzIiwicnVsZSIsInR5cGUiLCJDU1NSdWxlIiwiRk9OVF9GQUNFX1JVTEUiLCJnZXRQcm9wZXJ0eVZhbHVlIiwic2hlZXQiLCJocmVmIiwiY2FjaGUiLCJpbmNsdWRlcyIsImZldGNoIiwiY3JlZGVudGlhbHMiLCJyZXNwb25zZSIsInRleHQiLCJzZXRTdHlsZVNoZWV0QmFzZUhyZWYiLCJ0b1N0eWxlU2hlZXQiLCJlcnIiLCJDb25zb2xlIiwid2FybiIsIklNQUdFX0VYUE9SVF9FUlJPUlMiLCJzdHlsZVNoZWV0IiwibG9nIiwiZSIsIl90eXBlb2YyIiwiYmluZCIsIndlYkZvbnRSdWxlIiwicGFyZW50U3R5bGVTaGVldCIsInNyYyIsIm5ld0ltYWdlIiwiZWxlbWVudCIsInJlamVjdCIsIm9ubG9hZCIsIm9uZXJyb3IiLCJFbGVtZW50IiwiaW5saW5lQmFja2dyb3VuZCIsIkhUTUxJbWFnZUVsZW1lbnQiLCJiYWNrZ3JvdW5kIiwiaW5saW5lZCIsInNldFByb3BlcnR5IiwiZ2V0UHJvcGVydHlQcmlvcml0eSIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uL3NyYy9kb20tdG8taW1hZ2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuLyoqXG4gKiBUaGlzIGZpbGUgaXMgY29waWVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL3RzYXllbi9kb20tdG8taW1hZ2VcbiAqIE1vZGlmaWVkIGJ5IGhlc2hhbjAxMzEgdG8gYWxsb3cgbG9hZGluZyBleHRlcm5hbCBzdHlsZXNoZWV0cyBhbmQgaW5saW5lIHdlYmZvbnRzXG4gKi9cblxuaW1wb3J0IFdpbmRvdyBmcm9tICdnbG9iYWwvd2luZG93JztcbmltcG9ydCBkb2N1bWVudCBmcm9tICdnbG9iYWwvZG9jdW1lbnQnO1xuaW1wb3J0IENvbnNvbGUgZnJvbSAnZ2xvYmFsL2NvbnNvbGUnO1xuaW1wb3J0IHtJTUFHRV9FWFBPUlRfRVJST1JTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbmltcG9ydCB7XG4gIGNhbnZhc1RvQmxvYixcbiAgZXNjYXBlLFxuICBlc2NhcGVYaHRtbCxcbiAgZGVsYXksXG4gIHByb2Nlc3NDbG9uZSxcbiAgYXNBcnJheSxcbiAgbWFrZUltYWdlLFxuICBtaW1lVHlwZSxcbiAgZGF0YUFzVXJsLFxuICBpc0RhdGFVcmwsXG4gIGlzU3JjQXNEYXRhVXJsLFxuICByZXNvbHZlVXJsLFxuICBnZXRXaWR0aCxcbiAgZ2V0SGVpZ2h0LFxuICBnZXRBbmRFbmNvZGUsXG4gIHNldFN0eWxlU2hlZXRCYXNlSHJlZixcbiAgdG9TdHlsZVNoZWV0XG59IGZyb20gJy4vZG9tLXV0aWxzJztcblxuY29uc3QgaW5saW5lciA9IG5ld0lubGluZXIoKTtcbmNvbnN0IGZvbnRGYWNlcyA9IG5ld0ZvbnRGYWNlcygpO1xuY29uc3QgaW1hZ2VzID0gbmV3SW1hZ2VzKCk7XG4vLyBEZWZhdWx0IGltcGwgb3B0aW9uc1xuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIC8vIERlZmF1bHQgaXMgdG8gZmFpbCBvbiBlcnJvciwgbm8gcGxhY2Vob2xkZXJcbiAgaW1hZ2VQbGFjZWhvbGRlcjogdW5kZWZpbmVkLFxuICAvLyBEZWZhdWx0IGNhY2hlIGJ1c3QgaXMgZmFsc2UsIGl0IHdpbGwgdXNlIHRoZSBjYWNoZVxuICBjYWNoZUJ1c3Q6IGZhbHNlXG59O1xuXG5jb25zdCBkb210b2ltYWdlID0ge1xuICB0b1N2ZyxcbiAgdG9QbmcsXG4gIHRvSnBlZyxcbiAgdG9CbG9iLFxuICB0b1BpeGVsRGF0YSxcbiAgaW1wbDoge1xuICAgIGZvbnRGYWNlcyxcbiAgICBpbWFnZXMsXG4gICAgaW5saW5lcixcbiAgICBvcHRpb25zOiB7fSBhcyBhbnlcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgLSBUaGUgRE9NIE5vZGUgb2JqZWN0IHRvIHJlbmRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBSZW5kZXJpbmcgb3B0aW9uc1xuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZmlsdGVyXSAtIFNob3VsZCByZXR1cm4gdHJ1ZSBpZiBwYXNzZWQgbm9kZSBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dFxuICogICAgICAgICAgKGV4Y2x1ZGluZyBub2RlIG1lYW5zIGV4Y2x1ZGluZyBpdCdzIGNoaWxkcmVuIGFzIHdlbGwpLiBOb3QgY2FsbGVkIG9uIHRoZSByb290IG5vZGUuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYmdjb2xvcl0gLSBjb2xvciBmb3IgdGhlIGJhY2tncm91bmQsIGFueSB2YWxpZCBDU1MgY29sb3IgdmFsdWUuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMud2lkdGhdIC0gd2lkdGggdG8gYmUgYXBwbGllZCB0byBub2RlIGJlZm9yZSByZW5kZXJpbmcuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuaGVpZ2h0XSAtIGhlaWdodCB0byBiZSBhcHBsaWVkIHRvIG5vZGUgYmVmb3JlIHJlbmRlcmluZy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5zdHlsZV0gLSBhbiBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyB0byBiZSBjb3BpZWQgdG8gbm9kZSdzIHN0eWxlIGJlZm9yZSByZW5kZXJpbmcuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucXVhbGl0eV0gLSBhIE51bWJlciBiZXR3ZWVuIDAgYW5kIDEgaW5kaWNhdGluZyBpbWFnZSBxdWFsaXR5IChhcHBsaWNhYmxlIHRvIEpQRUcgb25seSksIGRlZmF1bHRzIHRvIDEuMC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuZXNjYXBlWGh0bWxGb3JXZWJwYWNrXSAtIHdoZXRoZXIgdG8gYXBwbHkgZml4IGZvciB1Z2xpZnkgZXJyb3IgaW4gZG9tLXRvLWltYWdlIChzaG91bGQgYmUgdHJ1ZSBmb3Igd2VicGFjayBidWlsZHMpLCBkZWZhdWx0cyB0byB0cnVlLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmltYWdlUGxhY2Vob2xkZXJdIC0gZGF0YVVSTCB0byB1c2UgYXMgYSBwbGFjZWhvbGRlciBmb3IgZmFpbGVkIGltYWdlcywgZGVmYXVsdCBiZWhhdmlvdXIgaXMgdG8gZmFpbCBmYXN0IG9uIGltYWdlcyB3ZSBjYW4ndCBmZXRjaFxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5jYWNoZUJ1c3RdIC0gc2V0IHRvIHRydWUgdG8gY2FjaGUgYnVzdCBieSBhcHBlbmRpbmcgdGhlIHRpbWUgdG8gdGhlIHJlcXVlc3QgdXJsXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aXRoIGEgU1ZHIGltYWdlIGRhdGEgVVJMXG4gKiAqL1xuZnVuY3Rpb24gdG9Tdmcobm9kZSwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgY29weU9wdGlvbnMob3B0aW9ucyk7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUobm9kZSlcbiAgICAudGhlbihuZCA9PiBjbG9uZU5vZGUobmQsIG9wdGlvbnMuZmlsdGVyLCB0cnVlKSlcbiAgICAudGhlbihlbWJlZEZvbnRzKVxuICAgIC50aGVuKGlubGluZUltYWdlcylcbiAgICAudGhlbihhcHBseU9wdGlvbnMpXG4gICAgLnRoZW4oY2xvbmUgPT5cbiAgICAgIG1ha2VTdmdEYXRhVXJpKFxuICAgICAgICBjbG9uZSxcbiAgICAgICAgb3B0aW9ucy53aWR0aCB8fCBnZXRXaWR0aChub2RlKSxcbiAgICAgICAgb3B0aW9ucy5oZWlnaHQgfHwgZ2V0SGVpZ2h0KG5vZGUpLFxuICAgICAgICBvcHRpb25zLmVzY2FwZVhodG1sRm9yV2VicGFja1xuICAgICAgKVxuICAgICk7XG5cbiAgZnVuY3Rpb24gYXBwbHlPcHRpb25zKGNsb25lKSB7XG4gICAgaWYgKG9wdGlvbnMuYmdjb2xvcikgY2xvbmUuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gb3B0aW9ucy5iZ2NvbG9yO1xuXG4gICAgaWYgKG9wdGlvbnMud2lkdGgpIGNsb25lLnN0eWxlLndpZHRoID0gYCR7b3B0aW9ucy53aWR0aH1weGA7XG4gICAgaWYgKG9wdGlvbnMuaGVpZ2h0KSBjbG9uZS5zdHlsZS5oZWlnaHQgPSBgJHtvcHRpb25zLmhlaWdodH1weGA7XG5cbiAgICBpZiAob3B0aW9ucy5zdHlsZSlcbiAgICAgIE9iamVjdC5rZXlzKG9wdGlvbnMuc3R5bGUpLmZvckVhY2gocHJvcGVydHkgPT4ge1xuICAgICAgICBjbG9uZS5zdHlsZVtwcm9wZXJ0eV0gPSBvcHRpb25zLnN0eWxlW3Byb3BlcnR5XTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGNsb25lO1xuICB9XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlfSBub2RlIC0gVGhlIERPTSBOb2RlIG9iamVjdCB0byByZW5kZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gUmVuZGVyaW5nIG9wdGlvbnNcbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdpdGggYSBVaW50OEFycmF5IGNvbnRhaW5pbmcgUkdCQSBwaXhlbCBkYXRhLlxuICogKi9cbmZ1bmN0aW9uIHRvUGl4ZWxEYXRhKG5vZGUsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGRyYXcobm9kZSwgb3B0aW9ucyB8fCB7fSkudGhlbihcbiAgICBjYW52YXMgPT4gY2FudmFzLmdldENvbnRleHQoJzJkJykuZ2V0SW1hZ2VEYXRhKDAsIDAsIGdldFdpZHRoKG5vZGUpLCBnZXRIZWlnaHQobm9kZSkpLmRhdGFcbiAgKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgLSBUaGUgRE9NIE5vZGUgb2JqZWN0IHRvIHJlbmRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBSZW5kZXJpbmcgb3B0aW9uc1xuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2l0aCBhIFBORyBpbWFnZSBkYXRhIFVSTFxuICogKi9cbmZ1bmN0aW9uIHRvUG5nKG5vZGUsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGRyYXcobm9kZSwgb3B0aW9ucyB8fCB7fSkudGhlbihjYW52YXMgPT4gY2FudmFzLnRvRGF0YVVSTCgpKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgLSBUaGUgRE9NIE5vZGUgb2JqZWN0IHRvIHJlbmRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBSZW5kZXJpbmcgb3B0aW9uc1xuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2l0aCBhIEpQRUcgaW1hZ2UgZGF0YSBVUkxcbiAqICovXG5mdW5jdGlvbiB0b0pwZWcobm9kZSwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgcmV0dXJuIGRyYXcobm9kZSwgb3B0aW9ucykudGhlbihjYW52YXMgPT4gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvanBlZycsIG9wdGlvbnMucXVhbGl0eSB8fCAxLjApKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgLSBUaGUgRE9NIE5vZGUgb2JqZWN0IHRvIHJlbmRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBSZW5kZXJpbmcgb3B0aW9uc1xuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2l0aCBhIFBORyBpbWFnZSBibG9iXG4gKiAqL1xuZnVuY3Rpb24gdG9CbG9iKG5vZGUsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGRyYXcobm9kZSwgb3B0aW9ucyB8fCB7fSkudGhlbihjYW52YXNUb0Jsb2IpO1xufVxuXG5mdW5jdGlvbiBjb3B5T3B0aW9ucyhvcHRpb25zKSB7XG4gIC8vIENvcHkgb3B0aW9ucyB0byBpbXBsIG9wdGlvbnMgZm9yIHVzZSBpbiBpbXBsXG4gIGlmICh0eXBlb2Ygb3B0aW9ucy5pbWFnZVBsYWNlaG9sZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgIGRvbXRvaW1hZ2UuaW1wbC5vcHRpb25zLmltYWdlUGxhY2Vob2xkZXIgPSBkZWZhdWx0T3B0aW9ucy5pbWFnZVBsYWNlaG9sZGVyO1xuICB9IGVsc2Uge1xuICAgIGRvbXRvaW1hZ2UuaW1wbC5vcHRpb25zLmltYWdlUGxhY2Vob2xkZXIgPSBvcHRpb25zLmltYWdlUGxhY2Vob2xkZXI7XG4gIH1cblxuICBpZiAodHlwZW9mIG9wdGlvbnMuY2FjaGVCdXN0ID09PSAndW5kZWZpbmVkJykge1xuICAgIGRvbXRvaW1hZ2UuaW1wbC5vcHRpb25zLmNhY2hlQnVzdCA9IGRlZmF1bHRPcHRpb25zLmNhY2hlQnVzdDtcbiAgfSBlbHNlIHtcbiAgICBkb210b2ltYWdlLmltcGwub3B0aW9ucy5jYWNoZUJ1c3QgPSBvcHRpb25zLmNhY2hlQnVzdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBkcmF3KGRvbU5vZGUsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHRvU3ZnKGRvbU5vZGUsIG9wdGlvbnMpXG4gICAgLnRoZW4obWFrZUltYWdlKVxuICAgIC50aGVuKGRlbGF5KDEwMCkpXG4gICAgLnRoZW4oaW1hZ2UgPT4ge1xuICAgICAgY29uc3QgY2FudmFzID0gbmV3Q2FudmFzKGRvbU5vZGUpO1xuICAgICAgY2FudmFzLmdldENvbnRleHQoJzJkJykuZHJhd0ltYWdlKGltYWdlLCAwLCAwKTtcbiAgICAgIHJldHVybiBjYW52YXM7XG4gICAgfSk7XG5cbiAgZnVuY3Rpb24gbmV3Q2FudmFzKGROb2RlKSB7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY2FudmFzLndpZHRoID0gb3B0aW9ucy53aWR0aCB8fCBnZXRXaWR0aChkTm9kZSk7XG4gICAgY2FudmFzLmhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0IHx8IGdldEhlaWdodChkTm9kZSk7XG5cbiAgICBpZiAob3B0aW9ucy5iZ2NvbG9yKSB7XG4gICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSBvcHRpb25zLmJnY29sb3I7XG4gICAgICBjdHguZmlsbFJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FudmFzO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNsb25lTm9kZShub2RlLCBmaWx0ZXIsIHJvb3QpIHtcbiAgaWYgKCFyb290ICYmIGZpbHRlciAmJiAhZmlsdGVyKG5vZGUpKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShub2RlKVxuICAgIC50aGVuKG1ha2VOb2RlQ29weSlcbiAgICAudGhlbihjbG9uZSA9PiBjbG9uZUNoaWxkcmVuKG5vZGUsIGNsb25lLCBmaWx0ZXIpKVxuICAgIC50aGVuKGNsb25lID0+IHByb2Nlc3NDbG9uZShub2RlLCBjbG9uZSkpO1xuXG4gIGZ1bmN0aW9uIG1ha2VOb2RlQ29weShuZCkge1xuICAgIGlmIChuZCBpbnN0YW5jZW9mIFdpbmRvdy5IVE1MQ2FudmFzRWxlbWVudCkge1xuICAgICAgcmV0dXJuIG1ha2VJbWFnZShuZC50b0RhdGFVUkwoKSk7XG4gICAgfVxuICAgIHJldHVybiBuZC5jbG9uZU5vZGUoZmFsc2UpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmVDaGlsZHJlbkluT3JkZXIocGFyZW50LCBhcnJDaGlsZHJlbiwgZmx0KSB7XG4gICAgbGV0IGRvbmUgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBhcnJDaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcbiAgICAgIGRvbmUgPSBkb25lXG4gICAgICAgIC50aGVuKCgpID0+IGNsb25lTm9kZShjaGlsZCwgZmx0LCBudWxsKSlcbiAgICAgICAgLnRoZW4oY2hpbGRDbG9uZSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkQ2xvbmUpIHtcbiAgICAgICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChjaGlsZENsb25lKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBkb25lO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmVDaGlsZHJlbihvcmlnaW5hbCwgY2xvbmUsIGZsdCkge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gb3JpZ2luYWwuY2hpbGROb2RlcztcbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNsb25lKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xvbmVDaGlsZHJlbkluT3JkZXIoY2xvbmUsIGFzQXJyYXkoY2hpbGRyZW4pLCBmbHQpLnRoZW4oKCkgPT4gY2xvbmUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtYmVkRm9udHMobm9kZSkge1xuICByZXR1cm4gZm9udEZhY2VzLnJlc29sdmVBbGwoKS50aGVuKGNzc1RleHQgPT4ge1xuICAgIGNvbnN0IHN0eWxlTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgbm9kZS5hcHBlbmRDaGlsZChzdHlsZU5vZGUpO1xuICAgIHN0eWxlTm9kZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjc3NUZXh0KSk7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBpbmxpbmVJbWFnZXMobm9kZSkge1xuICByZXR1cm4gaW1hZ2VzLmlubGluZUFsbChub2RlKS50aGVuKCgpID0+IG5vZGUpO1xufVxuXG5mdW5jdGlvbiBtYWtlU3ZnRGF0YVVyaShub2RlLCB3aWR0aCwgaGVpZ2h0LCBlc2NhcGVYaHRtbEZvcldlYnBhY2sgPSB0cnVlKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUobm9kZSkudGhlbihuZCA9PiB7XG4gICAgbmQuc2V0QXR0cmlidXRlKCd4bWxucycsICdodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sJyk7XG4gICAgY29uc3Qgc2VyaWFsaXplZFN0cmluZyA9IG5ldyBXaW5kb3cuWE1MU2VyaWFsaXplcigpLnNlcmlhbGl6ZVRvU3RyaW5nKG5kKTtcblxuICAgIGNvbnN0IHhodG1sID0gZXNjYXBlWGh0bWxGb3JXZWJwYWNrID8gZXNjYXBlWGh0bWwoc2VyaWFsaXplZFN0cmluZykgOiBzZXJpYWxpemVkU3RyaW5nO1xuICAgIGNvbnN0IGZvcmVpZ25PYmplY3QgPSBgPGZvcmVpZ25PYmplY3QgeD1cIjBcIiB5PVwiMFwiIHdpZHRoPVwiMTAwJVwiIGhlaWdodD1cIjEwMCVcIj4ke3hodG1sfTwvZm9yZWlnbk9iamVjdD5gO1xuICAgIGNvbnN0IHN2Z1N0ciA9IGA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIiR7d2lkdGh9XCIgaGVpZ2h0PVwiJHtoZWlnaHR9XCI+JHtmb3JlaWduT2JqZWN0fTwvc3ZnPmA7XG5cbiAgICAvLyBVc2UgYmFzZTY0IGVuY29kaW5nXG4gICAgbGV0IGJhc2U2NFN2Zzogc3RyaW5nO1xuICAgIGlmICh0eXBlb2YgQnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiBCdWZmZXIuZnJvbSkge1xuICAgICAgYmFzZTY0U3ZnID0gQnVmZmVyLmZyb20oc3ZnU3RyLCAndXRmOCcpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBUZXh0RW5jb2RlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIC8vIE1vZGVybiBicm93c2VyczogVGV4dEVuY29kZXIgaGFuZGxlcyBVbmljb2RlIOKGkiBVVEYtOCBieXRlc1xuICAgICAgLy8gTXVzdCBjaHVuayB0byBhdm9pZCBjYWxsIHN0YWNrIGxpbWl0cyB3aXRoIGxhcmdlIGFycmF5c1xuICAgICAgY29uc3QgYnl0ZXMgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoc3ZnU3RyKTtcbiAgICAgIGNvbnN0IENIVU5LX1NJWkUgPSA4MTkyO1xuICAgICAgbGV0IGJpbmFyeSA9ICcnO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gQ0hVTktfU0laRSkge1xuICAgICAgICBiaW5hcnkgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBBcnJheS5mcm9tKGJ5dGVzLnNsaWNlKGksIGkgKyBDSFVOS19TSVpFKSkpO1xuICAgICAgfVxuICAgICAgYmFzZTY0U3ZnID0gV2luZG93LmJ0b2EoYmluYXJ5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBiYXNlNjQgZW5jb2RlciBmb3VuZCcpO1xuICAgIH1cbiAgICByZXR1cm4gYGRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsJHtiYXNlNjRTdmd9YDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG5ld0lubGluZXIoKSB7XG4gIGNvbnN0IFVSTF9SRUdFWCA9IC91cmxcXChbJ1wiXT8oW14nXCJdKz8pWydcIl0/XFwpL2c7XG5cbiAgcmV0dXJuIHtcbiAgICBpbmxpbmVBbGwsXG4gICAgc2hvdWxkUHJvY2VzcyxcbiAgICBpbXBsOiB7XG4gICAgICByZWFkVXJscyxcbiAgICAgIGlubGluZVxuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBzaG91bGRQcm9jZXNzKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcuc2VhcmNoKFVSTF9SRUdFWCkgIT09IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVhZFVybHMoc3RyaW5nKSB7XG4gICAgY29uc3QgcmVzdWx0OiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBtYXRjaDogbnVsbCB8IFJlZ0V4cEV4ZWNBcnJheTtcbiAgICB3aGlsZSAoKG1hdGNoID0gVVJMX1JFR0VYLmV4ZWMoc3RyaW5nKSkgIT09IG51bGwpIHtcbiAgICAgIHJlc3VsdC5wdXNoKG1hdGNoWzFdKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdC5maWx0ZXIodXJsID0+IHtcbiAgICAgIHJldHVybiAhaXNEYXRhVXJsKHVybCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB1cmxBc1JlZ2V4KHVybDApIHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChgKHVybFxcXFwoWydcIl0/KSgke2VzY2FwZSh1cmwwKX0pKFsnXCJdP1xcXFwpKWAsICdnJyk7XG4gIH1cblxuICBmdW5jdGlvbiBpbmxpbmUoc3RyaW5nLCB1cmwsIGJhc2VVcmwsIGdldCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodXJsKVxuICAgICAgLnRoZW4odWwgPT4gKGJhc2VVcmwgPyByZXNvbHZlVXJsKHVsLCBiYXNlVXJsKSA6IHVsKSlcbiAgICAgIC50aGVuKHVsID0+ICh0eXBlb2YgZ2V0ID09PSAnZnVuY3Rpb24nID8gZ2V0KHVsKSA6IGdldEFuZEVuY29kZSh1bCwgZG9tdG9pbWFnZS5pbXBsLm9wdGlvbnMpKSlcbiAgICAgIC50aGVuKGRhdGEgPT4gZGF0YUFzVXJsKGRhdGEsIG1pbWVUeXBlKHVybCkpKVxuICAgICAgLnRoZW4oZGF0YVVybCA9PiBzdHJpbmcucmVwbGFjZSh1cmxBc1JlZ2V4KHVybCksIGAkMSR7ZGF0YVVybH0kM2ApKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlubGluZUFsbChzdHJpbmcsIGJhc2VVcmwsIGdldCkge1xuICAgIGlmICghc2hvdWxkUHJvY2VzcyhzdHJpbmcpIHx8IGlzU3JjQXNEYXRhVXJsKHN0cmluZykpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc3RyaW5nKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzdHJpbmcpXG4gICAgICAudGhlbihyZWFkVXJscylcbiAgICAgIC50aGVuKHVybHMgPT4ge1xuICAgICAgICBsZXQgZG9uZSA9IFByb21pc2UucmVzb2x2ZShzdHJpbmcpO1xuICAgICAgICB1cmxzLmZvckVhY2godXJsID0+IHtcbiAgICAgICAgICBkb25lID0gZG9uZS50aGVuKHN0ciA9PiBpbmxpbmUoc3RyLCB1cmwsIGJhc2VVcmwsIGdldCkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGRvbmU7XG4gICAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBuZXdGb250RmFjZXMoKSB7XG4gIHJldHVybiB7XG4gICAgcmVzb2x2ZUFsbCxcbiAgICBpbXBsOiB7cmVhZEFsbH1cbiAgfTtcblxuICBmdW5jdGlvbiByZXNvbHZlQWxsKCkge1xuICAgIHJldHVybiByZWFkQWxsKClcbiAgICAgIC50aGVuKHdlYkZvbnRzID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHdlYkZvbnRzLm1hcCh3ZWJGb250ID0+IHdlYkZvbnQucmVzb2x2ZSgpKSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oY3NzU3RyaW5ncyA9PiBjc3NTdHJpbmdzLmpvaW4oJ1xcbicpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRBbGwoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShhc0FycmF5KGRvY3VtZW50LnN0eWxlU2hlZXRzKSlcbiAgICAgIC50aGVuKGxvYWRFeHRlcm5hbFN0eWxlU2hlZXRzKVxuICAgICAgLnRoZW4oZ2V0Q3NzUnVsZXMpXG4gICAgICAudGhlbihzZWxlY3RXZWJGb250UnVsZXMpXG4gICAgICAudGhlbihydWxlcyA9PiBydWxlcy5tYXAobmV3V2ViRm9udCkpO1xuXG4gICAgZnVuY3Rpb24gc2VsZWN0V2ViRm9udFJ1bGVzKGNzc1J1bGVzKSB7XG4gICAgICByZXR1cm4gY3NzUnVsZXNcbiAgICAgICAgLmZpbHRlcihydWxlID0+IHJ1bGUudHlwZSA9PT0gV2luZG93LkNTU1J1bGUuRk9OVF9GQUNFX1JVTEUpXG4gICAgICAgIC5maWx0ZXIocnVsZSA9PiBpbmxpbmVyLnNob3VsZFByb2Nlc3MocnVsZS5zdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCdzcmMnKSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvYWRFeHRlcm5hbFN0eWxlU2hlZXRzKHN0eWxlU2hlZXRzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIHN0eWxlU2hlZXRzLm1hcChzaGVldCA9PiB7XG4gICAgICAgICAgaWYgKHNoZWV0LmhyZWYpIHtcbiAgICAgICAgICAgIC8vIGNsb3VkZm9udCBkb2Vzbid0IGhhdmUgYWxsb3cgb3JpZ2luIGhlYWRlciBwcm9wZXJseSBzZXRcbiAgICAgICAgICAgIC8vIGVycm9yIHJlc3BvbnNlIHdpbGwgcmVtYWluIGluIGNhY2hlXG4gICAgICAgICAgICBjb25zdCBjYWNoZSA9IHNoZWV0LmhyZWYuaW5jbHVkZXMoJ3ViZXItZm9udHMnKSA/ICduby1jYWNoZScgOiAnZGVmYXVsdCc7XG4gICAgICAgICAgICByZXR1cm4gV2luZG93LmZldGNoKHNoZWV0LmhyZWYsIHtjcmVkZW50aWFsczogJ29taXQnLCBjYWNoZX0pXG4gICAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHJlc3BvbnNlLnRleHQoKSlcbiAgICAgICAgICAgICAgLnRoZW4odGV4dCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gc2V0U3R5bGVTaGVldEJhc2VIcmVmKHRleHQsIHNoZWV0LmhyZWYpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0eWxlU2hlZXQocmVzdWx0KTtcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gSGFuZGxlIGFueSBlcnJvciB0aGF0IG9jY3VycmVkIGluIGFueSBvZiB0aGUgcHJldmlvdXNcbiAgICAgICAgICAgICAgICAvLyBwcm9taXNlcyBpbiB0aGUgY2hhaW4uIHN0eWxlc2hlZXQgZmFpbGVkIHRvIGxvYWQgc2hvdWxkIG5vdCBzdG9wXG4gICAgICAgICAgICAgICAgLy8gdGhlIHByb2Nlc3MsIGhlbmNlIHJlc3VsdCBpbiBvbmx5IGEgd2FybmluZywgaW5zdGVhZCBvZiByZWplY3RcbiAgICAgICAgICAgICAgICBDb25zb2xlLndhcm4oSU1BR0VfRVhQT1JUX0VSUk9SUy5zdHlsZVNoZWV0LCBzaGVldC5ocmVmKTtcbiAgICAgICAgICAgICAgICBDb25zb2xlLmxvZyhlcnIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc2hlZXQpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDc3NSdWxlcyhzdHlsZVNoZWV0cykge1xuICAgICAgY29uc3QgY3NzUnVsZXM6IGFueVtdID0gW107XG4gICAgICBzdHlsZVNoZWV0cy5mb3JFYWNoKHNoZWV0ID0+IHtcbiAgICAgICAgLy8gdHJ5Li4uY2F0Y2ggYmVjYXVzZSBicm93c2VyIG1heSBub3QgYWJsZSB0byBlbnVtZXJhdGUgcnVsZXMgZm9yIGNyb3NzLWRvbWFpbiBzaGVldHNcbiAgICAgICAgaWYgKCFzaGVldCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcnVsZXM7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcnVsZXMgPSBzaGVldC5ydWxlcyB8fCBzaGVldC5jc3NSdWxlcztcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIENvbnNvbGUubG9nKGAnQ2FuJ3QgcmVhZCB0aGUgY3NzIHJ1bGVzIG9mOiAke3NoZWV0LmhyZWZ9YCwgZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJ1bGVzICYmIHR5cGVvZiBydWxlcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXNBcnJheShydWxlcyB8fCBbXSkuZm9yRWFjaChjc3NSdWxlcy5wdXNoLmJpbmQoY3NzUnVsZXMpKTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBDb25zb2xlLmxvZyhgRXJyb3Igd2hpbGUgcmVhZGluZyBDU1MgcnVsZXMgZnJvbSAke3NoZWV0LmhyZWZ9YCwgZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIENvbnNvbGUubG9nKCdnZXRDc3NSdWxlcyBjYW4gbm90IGZpbmQgY3NzUnVsZXMnKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gY3NzUnVsZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV3V2ViRm9udCh3ZWJGb250UnVsZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVzb2x2ZTogKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGJhc2VVcmwgPSAod2ViRm9udFJ1bGUucGFyZW50U3R5bGVTaGVldCB8fCB7fSkuaHJlZjtcbiAgICAgICAgICByZXR1cm4gaW5saW5lci5pbmxpbmVBbGwod2ViRm9udFJ1bGUuY3NzVGV4dCwgYmFzZVVybCwgbnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNyYzogKCkgPT4gd2ViRm9udFJ1bGUuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnc3JjJylcbiAgICAgIH07XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIG5ld0ltYWdlcygpIHtcbiAgcmV0dXJuIHtcbiAgICBpbmxpbmVBbGwsXG4gICAgaW1wbDoge1xuICAgICAgbmV3SW1hZ2VcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gbmV3SW1hZ2UoZWxlbWVudCkge1xuICAgIGZ1bmN0aW9uIGlubGluZShnZXQpIHtcbiAgICAgIGlmIChpc0RhdGFVcmwoZWxlbWVudC5zcmMpKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZWxlbWVudC5zcmMpXG4gICAgICAgIC50aGVuKHVsID0+XG4gICAgICAgICAgdHlwZW9mIGdldCA9PT0gJ2Z1bmN0aW9uJyA/IGdldCh1bCkgOiBnZXRBbmRFbmNvZGUodWwsIGRvbXRvaW1hZ2UuaW1wbC5vcHRpb25zKVxuICAgICAgICApXG4gICAgICAgIC50aGVuKGRhdGEgPT4gZGF0YUFzVXJsKGRhdGEsIG1pbWVUeXBlKGVsZW1lbnQuc3JjKSkpXG4gICAgICAgIC50aGVuKFxuICAgICAgICAgIGRhdGFVcmwgPT5cbiAgICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgZWxlbWVudC5vbmxvYWQgPSByZXNvbHZlO1xuICAgICAgICAgICAgICBlbGVtZW50Lm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgICAgICAgIGVsZW1lbnQuc3JjID0gZGF0YVVybDtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlubGluZVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBpbmxpbmVBbGwobm9kZSkge1xuICAgIGlmICghKG5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShub2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5saW5lQmFja2dyb3VuZChub2RlKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gbmV3SW1hZ2Uobm9kZSkuaW5saW5lKG51bGwpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGFzQXJyYXkobm9kZS5jaGlsZE5vZGVzKS5tYXAoY2hpbGQgPT4gaW5saW5lQWxsKGNoaWxkKSkpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gaW5saW5lQmFja2dyb3VuZChuZCkge1xuICAgICAgY29uc3QgYmFja2dyb3VuZCA9IG5kLnN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2JhY2tncm91bmQnKTtcblxuICAgICAgaWYgKCFiYWNrZ3JvdW5kKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW5saW5lclxuICAgICAgICAuaW5saW5lQWxsKGJhY2tncm91bmQsIG51bGwsIG51bGwpXG4gICAgICAgIC50aGVuKGlubGluZWQgPT4ge1xuICAgICAgICAgIG5kLnN0eWxlLnNldFByb3BlcnR5KCdiYWNrZ3JvdW5kJywgaW5saW5lZCwgbmQuc3R5bGUuZ2V0UHJvcGVydHlQcmlvcml0eSgnYmFja2dyb3VuZCcpKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKCkgPT4gbmQpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBkb210b2ltYWdlO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFNBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFFLFFBQUEsR0FBQUgsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFHLFVBQUEsR0FBQUgsT0FBQTtBQUVBLElBQUFJLFNBQUEsR0FBQUosT0FBQTtBQWJBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBMkJBLElBQU1LLE9BQU8sR0FBR0MsVUFBVSxDQUFDLENBQUM7QUFDNUIsSUFBTUMsU0FBUyxHQUFHQyxZQUFZLENBQUMsQ0FBQztBQUNoQyxJQUFNQyxNQUFNLEdBQUdDLFNBQVMsQ0FBQyxDQUFDO0FBQzFCO0FBQ0EsSUFBTUMsY0FBYyxHQUFHO0VBQ3JCO0VBQ0FDLGdCQUFnQixFQUFFQyxTQUFTO0VBQzNCO0VBQ0FDLFNBQVMsRUFBRTtBQUNiLENBQUM7QUFFRCxJQUFNQyxVQUFVLEdBQUc7RUFDakJDLEtBQUssRUFBTEEsS0FBSztFQUNMQyxLQUFLLEVBQUxBLEtBQUs7RUFDTEMsTUFBTSxFQUFOQSxNQUFNO0VBQ05DLE1BQU0sRUFBTkEsTUFBTTtFQUNOQyxXQUFXLEVBQVhBLFdBQVc7RUFDWEMsSUFBSSxFQUFFO0lBQ0pkLFNBQVMsRUFBVEEsU0FBUztJQUNURSxNQUFNLEVBQU5BLE1BQU07SUFDTkosT0FBTyxFQUFQQSxPQUFPO0lBQ1BpQixPQUFPLEVBQUUsQ0FBQztFQUNaO0FBQ0YsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTTixLQUFLQSxDQUFDTyxJQUFJLEVBQUVELE9BQU8sRUFBRTtFQUM1QkEsT0FBTyxHQUFHQSxPQUFPLElBQUksQ0FBQyxDQUFDO0VBQ3ZCRSxXQUFXLENBQUNGLE9BQU8sQ0FBQztFQUNwQixPQUFPRyxPQUFPLENBQUNDLE9BQU8sQ0FBQ0gsSUFBSSxDQUFDLENBQ3pCSSxJQUFJLENBQUMsVUFBQUMsRUFBRTtJQUFBLE9BQUlDLFNBQVMsQ0FBQ0QsRUFBRSxFQUFFTixPQUFPLENBQUNRLE1BQU0sRUFBRSxJQUFJLENBQUM7RUFBQSxFQUFDLENBQy9DSCxJQUFJLENBQUNJLFVBQVUsQ0FBQyxDQUNoQkosSUFBSSxDQUFDSyxZQUFZLENBQUMsQ0FDbEJMLElBQUksQ0FBQ00sWUFBWSxDQUFDLENBQ2xCTixJQUFJLENBQUMsVUFBQU8sS0FBSztJQUFBLE9BQ1RDLGNBQWMsQ0FDWkQsS0FBSyxFQUNMWixPQUFPLENBQUNjLEtBQUssSUFBSSxJQUFBQyxrQkFBUSxFQUFDZCxJQUFJLENBQUMsRUFDL0JELE9BQU8sQ0FBQ2dCLE1BQU0sSUFBSSxJQUFBQyxtQkFBUyxFQUFDaEIsSUFBSSxDQUFDLEVBQ2pDRCxPQUFPLENBQUNrQixxQkFDVixDQUFDO0VBQUEsQ0FDSCxDQUFDO0VBRUgsU0FBU1AsWUFBWUEsQ0FBQ0MsS0FBSyxFQUFFO0lBQzNCLElBQUlaLE9BQU8sQ0FBQ21CLE9BQU8sRUFBRVAsS0FBSyxDQUFDUSxLQUFLLENBQUNDLGVBQWUsR0FBR3JCLE9BQU8sQ0FBQ21CLE9BQU87SUFFbEUsSUFBSW5CLE9BQU8sQ0FBQ2MsS0FBSyxFQUFFRixLQUFLLENBQUNRLEtBQUssQ0FBQ04sS0FBSyxNQUFBUSxNQUFBLENBQU10QixPQUFPLENBQUNjLEtBQUssT0FBSTtJQUMzRCxJQUFJZCxPQUFPLENBQUNnQixNQUFNLEVBQUVKLEtBQUssQ0FBQ1EsS0FBSyxDQUFDSixNQUFNLE1BQUFNLE1BQUEsQ0FBTXRCLE9BQU8sQ0FBQ2dCLE1BQU0sT0FBSTtJQUU5RCxJQUFJaEIsT0FBTyxDQUFDb0IsS0FBSyxFQUNmRyxNQUFNLENBQUNDLElBQUksQ0FBQ3hCLE9BQU8sQ0FBQ29CLEtBQUssQ0FBQyxDQUFDSyxPQUFPLENBQUMsVUFBQUMsUUFBUSxFQUFJO01BQzdDZCxLQUFLLENBQUNRLEtBQUssQ0FBQ00sUUFBUSxDQUFDLEdBQUcxQixPQUFPLENBQUNvQixLQUFLLENBQUNNLFFBQVEsQ0FBQztJQUNqRCxDQUFDLENBQUM7SUFFSixPQUFPZCxLQUFLO0VBQ2Q7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU2QsV0FBV0EsQ0FBQ0csSUFBSSxFQUFFRCxPQUFPLEVBQUU7RUFDbEMsT0FBTzJCLElBQUksQ0FBQzFCLElBQUksRUFBRUQsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUNLLElBQUksQ0FDbkMsVUFBQXVCLE1BQU07SUFBQSxPQUFJQSxNQUFNLENBQUNDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQ0MsWUFBWSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBQWYsa0JBQVEsRUFBQ2QsSUFBSSxDQUFDLEVBQUUsSUFBQWdCLG1CQUFTLEVBQUNoQixJQUFJLENBQUMsQ0FBQyxDQUFDOEIsSUFBSTtFQUFBLENBQzVGLENBQUM7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3BDLEtBQUtBLENBQUNNLElBQUksRUFBRUQsT0FBTyxFQUFFO0VBQzVCLE9BQU8yQixJQUFJLENBQUMxQixJQUFJLEVBQUVELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDSyxJQUFJLENBQUMsVUFBQXVCLE1BQU07SUFBQSxPQUFJQSxNQUFNLENBQUNJLFNBQVMsQ0FBQyxDQUFDO0VBQUEsRUFBQztBQUNyRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3BDLE1BQU1BLENBQUNLLElBQUksRUFBRUQsT0FBTyxFQUFFO0VBQzdCQSxPQUFPLEdBQUdBLE9BQU8sSUFBSSxDQUFDLENBQUM7RUFDdkIsT0FBTzJCLElBQUksQ0FBQzFCLElBQUksRUFBRUQsT0FBTyxDQUFDLENBQUNLLElBQUksQ0FBQyxVQUFBdUIsTUFBTTtJQUFBLE9BQUlBLE1BQU0sQ0FBQ0ksU0FBUyxDQUFDLFlBQVksRUFBRWhDLE9BQU8sQ0FBQ2lDLE9BQU8sSUFBSSxHQUFHLENBQUM7RUFBQSxFQUFDO0FBQ25HOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTcEMsTUFBTUEsQ0FBQ0ksSUFBSSxFQUFFRCxPQUFPLEVBQUU7RUFDN0IsT0FBTzJCLElBQUksQ0FBQzFCLElBQUksRUFBRUQsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUNLLElBQUksQ0FBQzZCLHNCQUFZLENBQUM7QUFDckQ7QUFFQSxTQUFTaEMsV0FBV0EsQ0FBQ0YsT0FBTyxFQUFFO0VBQzVCO0VBQ0EsSUFBSSxPQUFPQSxPQUFPLENBQUNWLGdCQUFnQixLQUFLLFdBQVcsRUFBRTtJQUNuREcsVUFBVSxDQUFDTSxJQUFJLENBQUNDLE9BQU8sQ0FBQ1YsZ0JBQWdCLEdBQUdELGNBQWMsQ0FBQ0MsZ0JBQWdCO0VBQzVFLENBQUMsTUFBTTtJQUNMRyxVQUFVLENBQUNNLElBQUksQ0FBQ0MsT0FBTyxDQUFDVixnQkFBZ0IsR0FBR1UsT0FBTyxDQUFDVixnQkFBZ0I7RUFDckU7RUFFQSxJQUFJLE9BQU9VLE9BQU8sQ0FBQ1IsU0FBUyxLQUFLLFdBQVcsRUFBRTtJQUM1Q0MsVUFBVSxDQUFDTSxJQUFJLENBQUNDLE9BQU8sQ0FBQ1IsU0FBUyxHQUFHSCxjQUFjLENBQUNHLFNBQVM7RUFDOUQsQ0FBQyxNQUFNO0lBQ0xDLFVBQVUsQ0FBQ00sSUFBSSxDQUFDQyxPQUFPLENBQUNSLFNBQVMsR0FBR1EsT0FBTyxDQUFDUixTQUFTO0VBQ3ZEO0FBQ0Y7QUFFQSxTQUFTbUMsSUFBSUEsQ0FBQ1EsT0FBTyxFQUFFbkMsT0FBTyxFQUFFO0VBQzlCLE9BQU9OLEtBQUssQ0FBQ3lDLE9BQU8sRUFBRW5DLE9BQU8sQ0FBQyxDQUMzQkssSUFBSSxDQUFDK0IsbUJBQVMsQ0FBQyxDQUNmL0IsSUFBSSxDQUFDLElBQUFnQyxlQUFLLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FDaEJoQyxJQUFJLENBQUMsVUFBQWlDLEtBQUssRUFBSTtJQUNiLElBQU1WLE1BQU0sR0FBR1csU0FBUyxDQUFDSixPQUFPLENBQUM7SUFDakNQLE1BQU0sQ0FBQ0MsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDVyxTQUFTLENBQUNGLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLE9BQU9WLE1BQU07RUFDZixDQUFDLENBQUM7RUFFSixTQUFTVyxTQUFTQSxDQUFDRSxLQUFLLEVBQUU7SUFDeEIsSUFBTWIsTUFBTSxHQUFHYyxvQkFBUSxDQUFDQyxhQUFhLENBQUMsUUFBUSxDQUFDO0lBQy9DZixNQUFNLENBQUNkLEtBQUssR0FBR2QsT0FBTyxDQUFDYyxLQUFLLElBQUksSUFBQUMsa0JBQVEsRUFBQzBCLEtBQUssQ0FBQztJQUMvQ2IsTUFBTSxDQUFDWixNQUFNLEdBQUdoQixPQUFPLENBQUNnQixNQUFNLElBQUksSUFBQUMsbUJBQVMsRUFBQ3dCLEtBQUssQ0FBQztJQUVsRCxJQUFJekMsT0FBTyxDQUFDbUIsT0FBTyxFQUFFO01BQ25CLElBQU15QixHQUFHLEdBQUdoQixNQUFNLENBQUNDLFVBQVUsQ0FBQyxJQUFJLENBQUM7TUFDbkNlLEdBQUcsQ0FBQ0MsU0FBUyxHQUFHN0MsT0FBTyxDQUFDbUIsT0FBTztNQUMvQnlCLEdBQUcsQ0FBQ0UsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUVsQixNQUFNLENBQUNkLEtBQUssRUFBRWMsTUFBTSxDQUFDWixNQUFNLENBQUM7SUFDakQ7SUFFQSxPQUFPWSxNQUFNO0VBQ2Y7QUFDRjtBQUVBLFNBQVNyQixTQUFTQSxDQUFDTixJQUFJLEVBQUVPLE1BQU0sRUFBRXVDLElBQUksRUFBRTtFQUNyQyxJQUFJLENBQUNBLElBQUksSUFBSXZDLE1BQU0sSUFBSSxDQUFDQSxNQUFNLENBQUNQLElBQUksQ0FBQyxFQUFFO0lBQ3BDLE9BQU9FLE9BQU8sQ0FBQ0MsT0FBTyxDQUFDLENBQUM7RUFDMUI7RUFFQSxPQUFPRCxPQUFPLENBQUNDLE9BQU8sQ0FBQ0gsSUFBSSxDQUFDLENBQ3pCSSxJQUFJLENBQUMyQyxZQUFZLENBQUMsQ0FDbEIzQyxJQUFJLENBQUMsVUFBQU8sS0FBSztJQUFBLE9BQUlxQyxhQUFhLENBQUNoRCxJQUFJLEVBQUVXLEtBQUssRUFBRUosTUFBTSxDQUFDO0VBQUEsRUFBQyxDQUNqREgsSUFBSSxDQUFDLFVBQUFPLEtBQUs7SUFBQSxPQUFJLElBQUFzQyxzQkFBWSxFQUFDakQsSUFBSSxFQUFFVyxLQUFLLENBQUM7RUFBQSxFQUFDO0VBRTNDLFNBQVNvQyxZQUFZQSxDQUFDMUMsRUFBRSxFQUFFO0lBQ3hCLElBQUlBLEVBQUUsWUFBWTZDLGtCQUFNLENBQUNDLGlCQUFpQixFQUFFO01BQzFDLE9BQU8sSUFBQWhCLG1CQUFTLEVBQUM5QixFQUFFLENBQUMwQixTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2xDO0lBQ0EsT0FBTzFCLEVBQUUsQ0FBQ0MsU0FBUyxDQUFDLEtBQUssQ0FBQztFQUM1QjtFQUVBLFNBQVM4QyxvQkFBb0JBLENBQUNDLE1BQU0sRUFBRUMsV0FBVyxFQUFFQyxHQUFHLEVBQUU7SUFDdEQsSUFBSUMsSUFBSSxHQUFHdEQsT0FBTyxDQUFDQyxPQUFPLENBQUMsQ0FBQztJQUM1Qm1ELFdBQVcsQ0FBQzlCLE9BQU8sQ0FBQyxVQUFBaUMsS0FBSyxFQUFJO01BQzNCRCxJQUFJLEdBQUdBLElBQUksQ0FDUnBELElBQUksQ0FBQztRQUFBLE9BQU1FLFNBQVMsQ0FBQ21ELEtBQUssRUFBRUYsR0FBRyxFQUFFLElBQUksQ0FBQztNQUFBLEVBQUMsQ0FDdkNuRCxJQUFJLENBQUMsVUFBQXNELFVBQVUsRUFBSTtRQUNsQixJQUFJQSxVQUFVLEVBQUU7VUFDZEwsTUFBTSxDQUFDTSxXQUFXLENBQUNELFVBQVUsQ0FBQztRQUNoQztNQUNGLENBQUMsQ0FBQztJQUNOLENBQUMsQ0FBQztJQUNGLE9BQU9GLElBQUk7RUFDYjtFQUVBLFNBQVNSLGFBQWFBLENBQUNZLFFBQVEsRUFBRWpELEtBQUssRUFBRTRDLEdBQUcsRUFBRTtJQUMzQyxJQUFNTSxRQUFRLEdBQUdELFFBQVEsQ0FBQ0UsVUFBVTtJQUNwQyxJQUFJRCxRQUFRLENBQUNFLE1BQU0sS0FBSyxDQUFDLEVBQUU7TUFDekIsT0FBTzdELE9BQU8sQ0FBQ0MsT0FBTyxDQUFDUSxLQUFLLENBQUM7SUFDL0I7SUFFQSxPQUFPeUMsb0JBQW9CLENBQUN6QyxLQUFLLEVBQUUsSUFBQXFELGlCQUFPLEVBQUNILFFBQVEsQ0FBQyxFQUFFTixHQUFHLENBQUMsQ0FBQ25ELElBQUksQ0FBQztNQUFBLE9BQU1PLEtBQUs7SUFBQSxFQUFDO0VBQzlFO0FBQ0Y7QUFFQSxTQUFTSCxVQUFVQSxDQUFDUixJQUFJLEVBQUU7RUFDeEIsT0FBT2hCLFNBQVMsQ0FBQ2lGLFVBQVUsQ0FBQyxDQUFDLENBQUM3RCxJQUFJLENBQUMsVUFBQThELE9BQU8sRUFBSTtJQUM1QyxJQUFNQyxTQUFTLEdBQUcxQixvQkFBUSxDQUFDQyxhQUFhLENBQUMsT0FBTyxDQUFDO0lBQ2pEMUMsSUFBSSxDQUFDMkQsV0FBVyxDQUFDUSxTQUFTLENBQUM7SUFDM0JBLFNBQVMsQ0FBQ1IsV0FBVyxDQUFDbEIsb0JBQVEsQ0FBQzJCLGNBQWMsQ0FBQ0YsT0FBTyxDQUFDLENBQUM7SUFDdkQsT0FBT2xFLElBQUk7RUFDYixDQUFDLENBQUM7QUFDSjtBQUVBLFNBQVNTLFlBQVlBLENBQUNULElBQUksRUFBRTtFQUMxQixPQUFPZCxNQUFNLENBQUNtRixTQUFTLENBQUNyRSxJQUFJLENBQUMsQ0FBQ0ksSUFBSSxDQUFDO0lBQUEsT0FBTUosSUFBSTtFQUFBLEVBQUM7QUFDaEQ7QUFFQSxTQUFTWSxjQUFjQSxDQUFDWixJQUFJLEVBQUVhLEtBQUssRUFBRUUsTUFBTSxFQUFnQztFQUFBLElBQTlCRSxxQkFBcUIsR0FBQXFELFNBQUEsQ0FBQVAsTUFBQSxRQUFBTyxTQUFBLFFBQUFoRixTQUFBLEdBQUFnRixTQUFBLE1BQUcsSUFBSTtFQUN2RSxPQUFPcEUsT0FBTyxDQUFDQyxPQUFPLENBQUNILElBQUksQ0FBQyxDQUFDSSxJQUFJLENBQUMsVUFBQUMsRUFBRSxFQUFJO0lBQ3RDQSxFQUFFLENBQUNrRSxZQUFZLENBQUMsT0FBTyxFQUFFLDhCQUE4QixDQUFDO0lBQ3hELElBQU1DLGdCQUFnQixHQUFHLElBQUl0QixrQkFBTSxDQUFDdUIsYUFBYSxDQUFDLENBQUMsQ0FBQ0MsaUJBQWlCLENBQUNyRSxFQUFFLENBQUM7SUFFekUsSUFBTXNFLEtBQUssR0FBRzFELHFCQUFxQixHQUFHLElBQUEyRCxxQkFBVyxFQUFDSixnQkFBZ0IsQ0FBQyxHQUFHQSxnQkFBZ0I7SUFDdEYsSUFBTUssYUFBYSxvRUFBQXhELE1BQUEsQ0FBNERzRCxLQUFLLHFCQUFrQjtJQUN0RyxJQUFNRyxNQUFNLHdEQUFBekQsTUFBQSxDQUFxRFIsS0FBSyxrQkFBQVEsTUFBQSxDQUFhTixNQUFNLFNBQUFNLE1BQUEsQ0FBS3dELGFBQWEsV0FBUTs7SUFFbkg7SUFDQSxJQUFJRSxTQUFpQjtJQUNyQixJQUFJLE9BQU9DLE1BQU0sS0FBSyxXQUFXLElBQUlBLE1BQU0sQ0FBQ0MsSUFBSSxFQUFFO01BQ2hERixTQUFTLEdBQUdDLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDSCxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUNJLFFBQVEsQ0FBQyxRQUFRLENBQUM7SUFDNUQsQ0FBQyxNQUFNLElBQUksT0FBT0MsV0FBVyxLQUFLLFdBQVcsRUFBRTtNQUM3QztNQUNBO01BQ0EsSUFBTUMsS0FBSyxHQUFHLElBQUlELFdBQVcsQ0FBQyxDQUFDLENBQUNFLE1BQU0sQ0FBQ1AsTUFBTSxDQUFDO01BQzlDLElBQU1RLFVBQVUsR0FBRyxJQUFJO01BQ3ZCLElBQUlDLE1BQU0sR0FBRyxFQUFFO01BQ2YsS0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUdKLEtBQUssQ0FBQ3JCLE1BQU0sRUFBRXlCLENBQUMsSUFBSUYsVUFBVSxFQUFFO1FBQ2pEQyxNQUFNLElBQUlFLE1BQU0sQ0FBQ0MsWUFBWSxDQUFDQyxLQUFLLENBQUMsSUFBSSxFQUFFQyxLQUFLLENBQUNYLElBQUksQ0FBQ0csS0FBSyxDQUFDUyxLQUFLLENBQUNMLENBQUMsRUFBRUEsQ0FBQyxHQUFHRixVQUFVLENBQUMsQ0FBQyxDQUFDO01BQ3ZGO01BQ0FQLFNBQVMsR0FBRzdCLGtCQUFNLENBQUM0QyxJQUFJLENBQUNQLE1BQU0sQ0FBQztJQUNqQyxDQUFDLE1BQU07TUFDTCxNQUFNLElBQUlRLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQztJQUM1QztJQUNBLG9DQUFBMUUsTUFBQSxDQUFvQzBELFNBQVM7RUFDL0MsQ0FBQyxDQUFDO0FBQ0o7QUFFQSxTQUFTaEcsVUFBVUEsQ0FBQSxFQUFHO0VBQ3BCLElBQU1pSCxTQUFTLEdBQUcsNkJBQTZCO0VBRS9DLE9BQU87SUFDTDNCLFNBQVMsRUFBVEEsU0FBUztJQUNUNEIsYUFBYSxFQUFiQSxhQUFhO0lBQ2JuRyxJQUFJLEVBQUU7TUFDSm9HLFFBQVEsRUFBUkEsUUFBUTtNQUNSQyxNQUFNLEVBQU5BO0lBQ0Y7RUFDRixDQUFDO0VBRUQsU0FBU0YsYUFBYUEsQ0FBQ0csTUFBTSxFQUFFO0lBQzdCLE9BQU9BLE1BQU0sQ0FBQ0MsTUFBTSxDQUFDTCxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7RUFDeEM7RUFFQSxTQUFTRSxRQUFRQSxDQUFDRSxNQUFNLEVBQUU7SUFDeEIsSUFBTUUsTUFBZ0IsR0FBRyxFQUFFO0lBQzNCLElBQUlDLEtBQTZCO0lBQ2pDLE9BQU8sQ0FBQ0EsS0FBSyxHQUFHUCxTQUFTLENBQUNRLElBQUksQ0FBQ0osTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFO01BQ2hERSxNQUFNLENBQUNHLElBQUksQ0FBQ0YsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCO0lBQ0EsT0FBT0QsTUFBTSxDQUFDL0YsTUFBTSxDQUFDLFVBQUFtRyxHQUFHLEVBQUk7TUFDMUIsT0FBTyxDQUFDLElBQUFDLG1CQUFTLEVBQUNELEdBQUcsQ0FBQztJQUN4QixDQUFDLENBQUM7RUFDSjtFQUVBLFNBQVNFLFVBQVVBLENBQUNDLElBQUksRUFBRTtJQUN4QixPQ