PATH: /home/hwyuvbry/www/kerbau/assets/vendor/libs/datatables-buttons
FILE_BARU
CREATE
FOLDER_BARU
MKDIR
UPLOAD_FILE
GO
[ .. KEMBALI ]
📄 buttons.colVis.js
↓
X
📄 buttons.colVis.js.LICENSE.txt
↓
X
📄 buttons.html5.js
↓
X
📄 buttons.html5.js.LICENSE.txt
↓
X
📄 buttons.print.js
↓
X
📄 buttons.print.js.LICENSE.txt
↓
X
📄 datatables-buttons.js
↓
X
📄 datatables-buttons.js.LICENSE.txt
↓
X
SAVING...
BERHASIL DIUBAH!
EDITING: buttons.html5.js
/* * ATTENTION: An "eval-source-map" devtool has been used. * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (function() { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./libs/datatables-buttons/buttons.html5.js": /*!**************************************************!*\ !*** ./libs/datatables-buttons/buttons.html5.js ***! \**************************************************/ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var datatables_net_buttons_js_buttons_html5__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! datatables.net-buttons/js/buttons.html5 */ "./node_modules/datatables.net-buttons/js/buttons.html5.js"); /* harmony import */ var datatables_net_buttons_js_buttons_html5__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(datatables_net_buttons_js_buttons_html5__WEBPACK_IMPORTED_MODULE_0__); /***/ }), /***/ "./node_modules/datatables.net-buttons/js/buttons.html5.js": /*!*****************************************************************!*\ !*** ./node_modules/datatables.net-buttons/js/buttons.html5.js ***! \*****************************************************************/ /***/ (function(module, exports, __webpack_require__) { eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * HTML5 export buttons for Buttons and DataTables.\n * 2016 SpryMedia Ltd - datatables.net/license\n *\n * FileSaver.js (1.3.3) - MIT license\n * Copyright © 2016 Eli Grey - http://eligrey.com\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\"), __webpack_require__(/*! datatables.net-buttons */ \"./node_modules/datatables.net-buttons/js/dataTables.buttons.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, jszip, pdfmake, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n// Allow the constructor to pass in JSZip and PDFMake from external requires.\n// Otherwise, use globally defined variables, if they are available.\nfunction _jsZip () {\n\treturn jszip || window.JSZip;\n}\nfunction _pdfMake () {\n\treturn pdfmake || window.pdfMake;\n}\n\nDataTable.Buttons.pdfMake = function (_) {\n\tif ( ! _ ) {\n\t\treturn _pdfMake();\n\t}\n\tpdfmake = _;\n}\n\nDataTable.Buttons.jszip = function (_) {\n\tif ( ! _ ) {\n\t\treturn _jsZip();\n\t}\n\tjszip = _;\n}\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * FileSaver.js dependency\n */\n\n/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */\n\nvar _saveAs = (function(view) {\n\t\"use strict\";\n\t// IE <10 is explicitly unsupported\n\tif (typeof view === \"undefined\" || typeof navigator !== \"undefined\" && /MSIE [1-9]\\./.test(navigator.userAgent)) {\n\t\treturn;\n\t}\n\tvar\n\t\t doc = view.document\n\t\t // only get URL when necessary in case Blob.js hasn't overridden it yet\n\t\t, get_URL = function() {\n\t\t\treturn view.URL || view.webkitURL || view;\n\t\t}\n\t\t, save_link = doc.createElementNS(\"http://www.w3.org/1999/xhtml\", \"a\")\n\t\t, can_use_save_link = \"download\" in save_link\n\t\t, click = function(node) {\n\t\t\tvar event = new MouseEvent(\"click\");\n\t\t\tnode.dispatchEvent(event);\n\t\t}\n\t\t, is_safari = /constructor/i.test(view.HTMLElement) || view.safari\n\t\t, is_chrome_ios =/CriOS\\/[\\d]+/.test(navigator.userAgent)\n\t\t, throw_outside = function(ex) {\n\t\t\t(view.setImmediate || view.setTimeout)(function() {\n\t\t\t\tthrow ex;\n\t\t\t}, 0);\n\t\t}\n\t\t, force_saveable_type = \"application/octet-stream\"\n\t\t// the Blob API is fundamentally broken as there is no \"downloadfinished\" event to subscribe to\n\t\t, arbitrary_revoke_timeout = 1000 * 40 // in ms\n\t\t, revoke = function(file) {\n\t\t\tvar revoker = function() {\n\t\t\t\tif (typeof file === \"string\") { // file is an object URL\n\t\t\t\t\tget_URL().revokeObjectURL(file);\n\t\t\t\t} else { // file is a File\n\t\t\t\t\tfile.remove();\n\t\t\t\t}\n\t\t\t};\n\t\t\tsetTimeout(revoker, arbitrary_revoke_timeout);\n\t\t}\n\t\t, dispatch = function(filesaver, event_types, event) {\n\t\t\tevent_types = [].concat(event_types);\n\t\t\tvar i = event_types.length;\n\t\t\twhile (i--) {\n\t\t\t\tvar listener = filesaver[\"on\" + event_types[i]];\n\t\t\t\tif (typeof listener === \"function\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlistener.call(filesaver, event || filesaver);\n\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\tthrow_outside(ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t, auto_bom = function(blob) {\n\t\t\t// prepend BOM for UTF-8 XML and text/* types (including HTML)\n\t\t\t// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF\n\t\t\tif (/^\\s*(?:text\\/\\S*|application\\/xml|\\S*\\/\\S*\\+xml)\\s*;.*charset\\s*=\\s*utf-8/i.test(blob.type)) {\n\t\t\t\treturn new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});\n\t\t\t}\n\t\t\treturn blob;\n\t\t}\n\t\t, FileSaver = function(blob, name, no_auto_bom) {\n\t\t\tif (!no_auto_bom) {\n\t\t\t\tblob = auto_bom(blob);\n\t\t\t}\n\t\t\t// First try a.download, then web filesystem, then object URLs\n\t\t\tvar\n\t\t\t\t filesaver = this\n\t\t\t\t, type = blob.type\n\t\t\t\t, force = type === force_saveable_type\n\t\t\t\t, object_url\n\t\t\t\t, dispatch_all = function() {\n\t\t\t\t\tdispatch(filesaver, \"writestart progress write writeend\".split(\" \"));\n\t\t\t\t}\n\t\t\t\t// on any filesys errors revert to saving with object URLs\n\t\t\t\t, fs_error = function() {\n\t\t\t\t\tif ((is_chrome_ios || (force && is_safari)) && view.FileReader) {\n\t\t\t\t\t\t// Safari doesn't allow downloading of blob urls\n\t\t\t\t\t\tvar reader = new FileReader();\n\t\t\t\t\t\treader.onloadend = function() {\n\t\t\t\t\t\t\tvar url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');\n\t\t\t\t\t\t\tvar popup = view.open(url, '_blank');\n\t\t\t\t\t\t\tif(!popup) view.location.href = url;\n\t\t\t\t\t\t\turl=undefined; // release reference before dispatching\n\t\t\t\t\t\t\tfilesaver.readyState = filesaver.DONE;\n\t\t\t\t\t\t\tdispatch_all();\n\t\t\t\t\t\t};\n\t\t\t\t\t\treader.readAsDataURL(blob);\n\t\t\t\t\t\tfilesaver.readyState = filesaver.INIT;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// don't create more object URLs than needed\n\t\t\t\t\tif (!object_url) {\n\t\t\t\t\t\tobject_url = get_URL().createObjectURL(blob);\n\t\t\t\t\t}\n\t\t\t\t\tif (force) {\n\t\t\t\t\t\tview.location.href = object_url;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar opened = view.open(object_url, \"_blank\");\n\t\t\t\t\t\tif (!opened) {\n\t\t\t\t\t\t\t// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html\n\t\t\t\t\t\t\tview.location.href = object_url;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfilesaver.readyState = filesaver.DONE;\n\t\t\t\t\tdispatch_all();\n\t\t\t\t\trevoke(object_url);\n\t\t\t\t}\n\t\t\t;\n\t\t\tfilesaver.readyState = filesaver.INIT;\n\n\t\t\tif (can_use_save_link) {\n\t\t\t\tobject_url = get_URL().createObjectURL(blob);\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tsave_link.href = object_url;\n\t\t\t\t\tsave_link.download = name;\n\t\t\t\t\tclick(save_link);\n\t\t\t\t\tdispatch_all();\n\t\t\t\t\trevoke(object_url);\n\t\t\t\t\tfilesaver.readyState = filesaver.DONE;\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfs_error();\n\t\t}\n\t\t, FS_proto = FileSaver.prototype\n\t\t, saveAs = function(blob, name, no_auto_bom) {\n\t\t\treturn new FileSaver(blob, name || blob.name || \"download\", no_auto_bom);\n\t\t}\n\t;\n\t// IE 10+ (native saveAs)\n\tif (typeof navigator !== \"undefined\" && navigator.msSaveOrOpenBlob) {\n\t\treturn function(blob, name, no_auto_bom) {\n\t\t\tname = name || blob.name || \"download\";\n\n\t\t\tif (!no_auto_bom) {\n\t\t\t\tblob = auto_bom(blob);\n\t\t\t}\n\t\t\treturn navigator.msSaveOrOpenBlob(blob, name);\n\t\t};\n\t}\n\n\tFS_proto.abort = function(){};\n\tFS_proto.readyState = FS_proto.INIT = 0;\n\tFS_proto.WRITING = 1;\n\tFS_proto.DONE = 2;\n\n\tFS_proto.error =\n\tFS_proto.onwritestart =\n\tFS_proto.onprogress =\n\tFS_proto.onwrite =\n\tFS_proto.onabort =\n\tFS_proto.onerror =\n\tFS_proto.onwriteend =\n\t\tnull;\n\n\treturn saveAs;\n}(\n\t typeof self !== \"undefined\" && self\n\t|| typeof window !== \"undefined\" && window\n\t|| this.content\n));\n\n\n// Expose file saver on the DataTables API. Can't attach to `DataTables.Buttons`\n// since this file can be loaded before Button's core!\nDataTable.fileSave = _saveAs;\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Local (private) functions\n */\n\n/**\n * Get the sheet name for Excel exports.\n *\n * @param {object}\tconfig Button configuration\n */\nvar _sheetname = function ( config )\n{\n\tvar sheetName = 'Sheet1';\n\n\tif ( config.sheetName ) {\n\t\tsheetName = config.sheetName.replace(/[\\[\\]\\*\\/\\\\\\?\\:]/g, '');\n\t}\n\n\treturn sheetName;\n};\n\n/**\n * Get the newline character(s)\n *\n * @param {object}\tconfig Button configuration\n * @return {string}\t\t\t\tNewline character\n */\nvar _newLine = function ( config )\n{\n\treturn config.newline ?\n\t\tconfig.newline :\n\t\tnavigator.userAgent.match(/Windows/) ?\n\t\t\t'\\r\\n' :\n\t\t\t'\\n';\n};\n\n/**\n * Combine the data from the `buttons.exportData` method into a string that\n * will be used in the export file.\n *\n * @param\t{DataTable.Api} dt\t\t DataTables API instance\n * @param\t{object}\t\t\t\tconfig Button configuration\n * @return {object}\t\t\t\t\t\t\t The data to export\n */\nvar _exportData = function ( dt, config )\n{\n\tvar newLine = _newLine( config );\n\tvar data = dt.buttons.exportData( config.exportOptions );\n\tvar boundary = config.fieldBoundary;\n\tvar separator = config.fieldSeparator;\n\tvar reBoundary = new RegExp( boundary, 'g' );\n\tvar escapeChar = config.escapeChar !== undefined ?\n\t\tconfig.escapeChar :\n\t\t'\\\\';\n\tvar join = function ( a ) {\n\t\tvar s = '';\n\n\t\t// If there is a field boundary, then we might need to escape it in\n\t\t// the source data\n\t\tfor ( var i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\tif ( i > 0 ) {\n\t\t\t\ts += separator;\n\t\t\t}\n\n\t\t\ts += boundary ?\n\t\t\t\tboundary + ('' + a[i]).replace( reBoundary, escapeChar+boundary ) + boundary :\n\t\t\t\ta[i];\n\t\t}\n\n\t\treturn s;\n\t};\n\n\tvar header = config.header ? join( data.header )+newLine : '';\n\tvar footer = config.footer && data.footer ? newLine+join( data.footer ) : '';\n\tvar body = [];\n\n\tfor ( var i=0, ien=data.body.length ; i<ien ; i++ ) {\n\t\tbody.push( join( data.body[i] ) );\n\t}\n\n\treturn {\n\t\tstr: header + body.join( newLine ) + footer,\n\t\trows: body.length\n\t};\n};\n\n/**\n * Older versions of Safari (prior to tech preview 18) don't support the\n * download option required.\n *\n * @return {Boolean} `true` if old Safari\n */\nvar _isDuffSafari = function ()\n{\n\tvar safari = navigator.userAgent.indexOf('Safari') !== -1 &&\n\t\tnavigator.userAgent.indexOf('Chrome') === -1 &&\n\t\tnavigator.userAgent.indexOf('Opera') === -1;\n\n\tif ( ! safari ) {\n\t\treturn false;\n\t}\n\n\tvar version = navigator.userAgent.match( /AppleWebKit\\/(\\d+\\.\\d+)/ );\n\tif ( version && version.length > 1 && version[1]*1 < 603.1 ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n/**\n * Convert from numeric position to letter for column names in Excel\n * @param {int} n Column number\n * @return {string} Column letter(s) name\n */\nfunction createCellPos( n ){\n\tvar ordA = 'A'.charCodeAt(0);\n\tvar ordZ = 'Z'.charCodeAt(0);\n\tvar len = ordZ - ordA + 1;\n\tvar s = \"\";\n\n\twhile( n >= 0 ) {\n\t\ts = String.fromCharCode(n % len + ordA) + s;\n\t\tn = Math.floor(n / len) - 1;\n\t}\n\n\treturn s;\n}\n\ntry {\n\tvar _serialiser = new XMLSerializer();\n\tvar _ieExcel;\n}\ncatch (t) {}\n\n/**\n * Recursively add XML files from an object's structure to a ZIP file. This\n * allows the XSLX file to be easily defined with an object's structure matching\n * the files structure.\n *\n * @param {JSZip} zip ZIP package\n * @param {object} obj Object to add (recursive)\n */\nfunction _addToZip( zip, obj ) {\n\tif ( _ieExcel === undefined ) {\n\t\t// Detect if we are dealing with IE's _awful_ serialiser by seeing if it\n\t\t// drop attributes\n\t\t_ieExcel = _serialiser\n\t\t\t.serializeToString(\n\t\t\t\t( new window.DOMParser() ).parseFromString( excelStrings['xl/worksheets/sheet1.xml'], 'text/xml' )\n\t\t\t)\n\t\t\t.indexOf( 'xmlns:r' ) === -1;\n\t}\n\n\t$.each( obj, function ( name, val ) {\n\t\tif ( $.isPlainObject( val ) ) {\n\t\t\tvar newDir = zip.folder( name );\n\t\t\t_addToZip( newDir, val );\n\t\t}\n\t\telse {\n\t\t\tif ( _ieExcel ) {\n\t\t\t\t// IE's XML serialiser will drop some name space attributes from\n\t\t\t\t// from the root node, so we need to save them. Do this by\n\t\t\t\t// replacing the namespace nodes with a regular attribute that\n\t\t\t\t// we convert back when serialised. Edge does not have this\n\t\t\t\t// issue\n\t\t\t\tvar worksheet = val.childNodes[0];\n\t\t\t\tvar i, ien;\n\t\t\t\tvar attrs = [];\n\n\t\t\t\tfor ( i=worksheet.attributes.length-1 ; i>=0 ; i-- ) {\n\t\t\t\t\tvar attrName = worksheet.attributes[i].nodeName;\n\t\t\t\t\tvar attrValue = worksheet.attributes[i].nodeValue;\n\n\t\t\t\t\tif ( attrName.indexOf( ':' ) !== -1 ) {\n\t\t\t\t\t\tattrs.push( { name: attrName, value: attrValue } );\n\n\t\t\t\t\t\tworksheet.removeAttribute( attrName );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=attrs.length ; i<ien ; i++ ) {\n\t\t\t\t\tvar attr = val.createAttribute( attrs[i].name.replace( ':', '_dt_b_namespace_token_' ) );\n\t\t\t\t\tattr.value = attrs[i].value;\n\t\t\t\t\tworksheet.setAttributeNode( attr );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar str = _serialiser.serializeToString(val);\n\n\t\t\t// Fix IE's XML\n\t\t\tif ( _ieExcel ) {\n\t\t\t\t// IE doesn't include the XML declaration\n\t\t\t\tif ( str.indexOf( '<?xml' ) === -1 ) {\n\t\t\t\t\tstr = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+str;\n\t\t\t\t}\n\n\t\t\t\t// Return namespace attributes to being as such\n\t\t\t\tstr = str.replace( /_dt_b_namespace_token_/g, ':' );\n\n\t\t\t\t// Remove testing name space that IE puts into the space preserve attr\n\t\t\t\tstr = str.replace( /xmlns:NS[\\d]+=\"\" NS[\\d]+:/g, '' );\n\t\t\t}\n\n\t\t\t// Safari, IE and Edge will put empty name space attributes onto\n\t\t\t// various elements making them useless. This strips them out\n\t\t\tstr = str.replace( /<([^<>]*?) xmlns=\"\"([^<>]*?)>/g, '<$1 $2>' );\n\n\t\t\tzip.file( name, str );\n\t\t}\n\t} );\n}\n\n/**\n * Create an XML node and add any children, attributes, etc without needing to\n * be verbose in the DOM.\n *\n * @param {object} doc XML document\n * @param {string} nodeName Node name\n * @param {object} opts Options - can be `attr` (attributes), `children`\n * (child nodes) and `text` (text content)\n * @return {node} Created node\n */\nfunction _createNode( doc, nodeName, opts ) {\n\tvar tempNode = doc.createElement( nodeName );\n\n\tif ( opts ) {\n\t\tif ( opts.attr ) {\n\t\t\t$(tempNode).attr( opts.attr );\n\t\t}\n\n\t\tif ( opts.children ) {\n\t\t\t$.each( opts.children, function ( key, value ) {\n\t\t\t\ttempNode.appendChild( value );\n\t\t\t} );\n\t\t}\n\n\t\tif ( opts.text !== null && opts.text !== undefined ) {\n\t\t\ttempNode.appendChild( doc.createTextNode( opts.text ) );\n\t\t}\n\t}\n\n\treturn tempNode;\n}\n\n/**\n * Get the width for an Excel column based on the contents of that column\n * @param {object} data Data for export\n * @param {int} col Column index\n * @return {int} Column width\n */\nfunction _excelColWidth( data, col ) {\n\tvar max = data.header[col].length;\n\tvar len, lineSplit, str;\n\n\tif ( data.footer && data.footer[col].length > max ) {\n\t\tmax = data.footer[col].length;\n\t}\n\n\tfor ( var i=0, ien=data.body.length ; i<ien ; i++ ) {\n\t\tvar point = data.body[i][col];\n\t\tstr = point !== null && point !== undefined ?\n\t\t\tpoint.toString() :\n\t\t\t'';\n\n\t\t// If there is a newline character, workout the width of the column\n\t\t// based on the longest line in the string\n\t\tif ( str.indexOf('\\n') !== -1 ) {\n\t\t\tlineSplit = str.split('\\n');\n\t\t\tlineSplit.sort( function (a, b) {\n\t\t\t\treturn b.length - a.length;\n\t\t\t} );\n\n\t\t\tlen = lineSplit[0].length;\n\t\t}\n\t\telse {\n\t\t\tlen = str.length;\n\t\t}\n\n\t\tif ( len > max ) {\n\t\t\tmax = len;\n\t\t}\n\n\t\t// Max width rather than having potentially massive column widths\n\t\tif ( max > 40 ) {\n\t\t\treturn 54; // 40 * 1.35\n\t\t}\n\t}\n\n\tmax *= 1.35;\n\n\t// And a min width\n\treturn max > 6 ? max : 6;\n}\n\n// Excel - Pre-defined strings to build a basic XLSX file\nvar excelStrings = {\n\t\"_rels/.rels\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+\n\t\t'<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">'+\n\t\t\t'<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>'+\n\t\t'</Relationships>',\n\n\t\"xl/_rels/workbook.xml.rels\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+\n\t\t'<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">'+\n\t\t\t'<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>'+\n\t\t\t'<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>'+\n\t\t'</Relationships>',\n\n\t\"[Content_Types].xml\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+\n\t\t'<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">'+\n\t\t\t'<Default Extension=\"xml\" ContentType=\"application/xml\" />'+\n\t\t\t'<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" />'+\n\t\t\t'<Default Extension=\"jpeg\" ContentType=\"image/jpeg\" />'+\n\t\t\t'<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" />'+\n\t\t\t'<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" />'+\n\t\t\t'<Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" />'+\n\t\t'</Types>',\n\n\t\"xl/workbook.xml\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+\n\t\t'<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">'+\n\t\t\t'<fileVersion appName=\"xl\" lastEdited=\"5\" lowestEdited=\"5\" rupBuild=\"24816\"/>'+\n\t\t\t'<workbookPr showInkAnnotation=\"0\" autoCompressPictures=\"0\"/>'+\n\t\t\t'<bookViews>'+\n\t\t\t\t'<workbookView xWindow=\"0\" yWindow=\"0\" windowWidth=\"25600\" windowHeight=\"19020\" tabRatio=\"500\"/>'+\n\t\t\t'</bookViews>'+\n\t\t\t'<sheets>'+\n\t\t\t\t'<sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/>'+\n\t\t\t'</sheets>'+\n\t\t\t'<definedNames/>'+\n\t\t'</workbook>',\n\n\t\"xl/worksheets/sheet1.xml\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>'+\n\t\t'<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x14ac\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\">'+\n\t\t\t'<sheetData/>'+\n\t\t\t'<mergeCells count=\"0\"/>'+\n\t\t'</worksheet>',\n\n\t\"xl/styles.xml\":\n\t\t'<?xml version=\"1.0\" encoding=\"UTF-8\"?>'+\n\t\t'<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x14ac\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\">'+\n\t\t\t'<numFmts count=\"6\">'+\n\t\t\t\t'<numFmt numFmtId=\"164\" formatCode=\"#,##0.00_-\\ [$$-45C]\"/>'+\n\t\t\t\t'<numFmt numFmtId=\"165\" formatCode=\""£"#,##0.00\"/>'+\n\t\t\t\t'<numFmt numFmtId=\"166\" formatCode=\"[$€-2]\\ #,##0.00\"/>'+\n\t\t\t\t'<numFmt numFmtId=\"167\" formatCode=\"0.0%\"/>'+\n\t\t\t\t'<numFmt numFmtId=\"168\" formatCode=\"#,##0;(#,##0)\"/>'+\n\t\t\t\t'<numFmt numFmtId=\"169\" formatCode=\"#,##0.00;(#,##0.00)\"/>'+\n\t\t\t'</numFmts>'+\n\t\t\t'<fonts count=\"5\" x14ac:knownFonts=\"1\">'+\n\t\t\t\t'<font>'+\n\t\t\t\t\t'<sz val=\"11\" />'+\n\t\t\t\t\t'<name val=\"Calibri\" />'+\n\t\t\t\t'</font>'+\n\t\t\t\t'<font>'+\n\t\t\t\t\t'<sz val=\"11\" />'+\n\t\t\t\t\t'<name val=\"Calibri\" />'+\n\t\t\t\t\t'<color rgb=\"FFFFFFFF\" />'+\n\t\t\t\t'</font>'+\n\t\t\t\t'<font>'+\n\t\t\t\t\t'<sz val=\"11\" />'+\n\t\t\t\t\t'<name val=\"Calibri\" />'+\n\t\t\t\t\t'<b />'+\n\t\t\t\t'</font>'+\n\t\t\t\t'<font>'+\n\t\t\t\t\t'<sz val=\"11\" />'+\n\t\t\t\t\t'<name val=\"Calibri\" />'+\n\t\t\t\t\t'<i />'+\n\t\t\t\t'</font>'+\n\t\t\t\t'<font>'+\n\t\t\t\t\t'<sz val=\"11\" />'+\n\t\t\t\t\t'<name val=\"Calibri\" />'+\n\t\t\t\t\t'<u />'+\n\t\t\t\t'</font>'+\n\t\t\t'</fonts>'+\n\t\t\t'<fills count=\"6\">'+\n\t\t\t\t'<fill>'+\n\t\t\t\t\t'<patternFill patternType=\"none\" />'+\n\t\t\t\t'</fill>'+\n\t\t\t\t'<fill>'+ // Excel appears to use this as a dotted background regardless of values but\n\t\t\t\t\t'<patternFill patternType=\"none\" />'+ // to be valid to the schema, use a patternFill\n\t\t\t\t'</fill>'+\n\t\t\t\t'<fill>'+\n\t\t\t\t\t'<patternFill patternType=\"solid\">'+\n\t\t\t\t\t\t'<fgColor rgb=\"FFD9D9D9\" />'+\n\t\t\t\t\t\t'<bgColor indexed=\"64\" />'+\n\t\t\t\t\t'</patternFill>'+\n\t\t\t\t'</fill>'+\n\t\t\t\t'<fill>'+\n\t\t\t\t\t'<patternFill patternType=\"solid\">'+\n\t\t\t\t\t\t'<fgColor rgb=\"FFD99795\" />'+\n\t\t\t\t\t\t'<bgColor indexed=\"64\" />'+\n\t\t\t\t\t'</patternFill>'+\n\t\t\t\t'</fill>'+\n\t\t\t\t'<fill>'+\n\t\t\t\t\t'<patternFill patternType=\"solid\">'+\n\t\t\t\t\t\t'<fgColor rgb=\"ffc6efce\" />'+\n\t\t\t\t\t\t'<bgColor indexed=\"64\" />'+\n\t\t\t\t\t'</patternFill>'+\n\t\t\t\t'</fill>'+\n\t\t\t\t'<fill>'+\n\t\t\t\t\t'<patternFill patternType=\"solid\">'+\n\t\t\t\t\t\t'<fgColor rgb=\"ffc6cfef\" />'+\n\t\t\t\t\t\t'<bgColor indexed=\"64\" />'+\n\t\t\t\t\t'</patternFill>'+\n\t\t\t\t'</fill>'+\n\t\t\t'</fills>'+\n\t\t\t'<borders count=\"2\">'+\n\t\t\t\t'<border>'+\n\t\t\t\t\t'<left />'+\n\t\t\t\t\t'<right />'+\n\t\t\t\t\t'<top />'+\n\t\t\t\t\t'<bottom />'+\n\t\t\t\t\t'<diagonal />'+\n\t\t\t\t'</border>'+\n\t\t\t\t'<border diagonalUp=\"false\" diagonalDown=\"false\">'+\n\t\t\t\t\t'<left style=\"thin\">'+\n\t\t\t\t\t\t'<color auto=\"1\" />'+\n\t\t\t\t\t'</left>'+\n\t\t\t\t\t'<right style=\"thin\">'+\n\t\t\t\t\t\t'<color auto=\"1\" />'+\n\t\t\t\t\t'</right>'+\n\t\t\t\t\t'<top style=\"thin\">'+\n\t\t\t\t\t\t'<color auto=\"1\" />'+\n\t\t\t\t\t'</top>'+\n\t\t\t\t\t'<bottom style=\"thin\">'+\n\t\t\t\t\t\t'<color auto=\"1\" />'+\n\t\t\t\t\t'</bottom>'+\n\t\t\t\t\t'<diagonal />'+\n\t\t\t\t'</border>'+\n\t\t\t'</borders>'+\n\t\t\t'<cellStyleXfs count=\"1\">'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" />'+\n\t\t\t'</cellStyleXfs>'+\n\t\t\t'<cellXfs count=\"68\">'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"2\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"2\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"2\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"2\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"2\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"3\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"3\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"3\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"3\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"3\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"4\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"4\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"4\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"4\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"4\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"5\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"5\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"5\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"5\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"5\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"0\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"0\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"0\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"2\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"2\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"2\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"2\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"2\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"3\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"3\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"3\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"3\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"3\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"4\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"4\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"4\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"4\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"4\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"5\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"1\" fillId=\"5\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"2\" fillId=\"5\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"3\" fillId=\"5\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"4\" fillId=\"5\" borderId=\"1\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment horizontal=\"left\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment horizontal=\"center\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment horizontal=\"right\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment horizontal=\"fill\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment textRotation=\"90\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyAlignment=\"1\">'+\n\t\t\t\t\t'<alignment wrapText=\"1\"/>'+\n\t\t\t\t'</xf>'+\n\t\t\t\t'<xf numFmtId=\"9\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"165\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"166\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"167\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"168\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"169\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"3\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"4\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"1\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"2\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t\t'<xf numFmtId=\"14\" fontId=\"0\" fillId=\"0\" borderId=\"0\" applyFont=\"1\" applyFill=\"1\" applyBorder=\"1\" xfId=\"0\" applyNumberFormat=\"1\"/>'+\n\t\t\t'</cellXfs>'+\n\t\t\t'<cellStyles count=\"1\">'+\n\t\t\t\t'<cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\" />'+\n\t\t\t'</cellStyles>'+\n\t\t\t'<dxfs count=\"0\" />'+\n\t\t\t'<tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\" defaultPivotStyle=\"PivotStyleMedium4\" />'+\n\t\t'</styleSheet>'\n};\n// Note we could use 3 `for` loops for the styles, but when gzipped there is\n// virtually no difference in size, since the above can be easily compressed\n\n// Pattern matching for special number formats. Perhaps this should be exposed\n// via an API in future?\n// Ref: section 3.8.30 - built in formatters in open spreadsheet\n// https://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%204%20-%20Markup%20Language%20Reference.pdf\nvar _excelSpecials = [\n\t{ match: /^\\-?\\d+\\.\\d%$/, style: 60, fmt: function (d) { return d/100; } }, // Percent with d.p.\n\t{ match: /^\\-?\\d+\\.?\\d*%$/, style: 56, fmt: function (d) { return d/100; } }, // Percent\n\t{ match: /^\\-?\\$[\\d,]+.?\\d*$/, style: 57 }, // Dollars\n\t{ match: /^\\-?£[\\d,]+.?\\d*$/, style: 58 }, // Pounds\n\t{ match: /^\\-?€[\\d,]+.?\\d*$/, style: 59 }, // Euros\n\t{ match: /^\\-?\\d+$/, style: 65 }, // Numbers without thousand separators\n\t{ match: /^\\-?\\d+\\.\\d{2}$/, style: 66 }, // Numbers 2 d.p. without thousands separators\n\t{ match: /^\\([\\d,]+\\)$/, style: 61, fmt: function (d) { return -1 * d.replace(/[\\(\\)]/g, ''); } }, // Negative numbers indicated by brackets\n\t{ match: /^\\([\\d,]+\\.\\d{2}\\)$/, style: 62, fmt: function (d) { return -1 * d.replace(/[\\(\\)]/g, ''); } }, // Negative numbers indicated by brackets - 2d.p.\n\t{ match: /^\\-?[\\d,]+$/, style: 63 }, // Numbers with thousand separators\n\t{ match: /^\\-?[\\d,]+\\.\\d{2}$/, style: 64 },\n\t{ match: /^[\\d]{4}\\-[01][\\d]\\-[0123][\\d]$/, style: 67, fmt: function (d) {return Math.round(25569 + (Date.parse(d) / (86400 * 1000)));}} //Date yyyy-mm-dd\n];\n\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Buttons\n */\n\n//\n// Copy to clipboard\n//\nDataTable.ext.buttons.copyHtml5 = {\n\tclassName: 'buttons-copy buttons-html5',\n\n\ttext: function ( dt ) {\n\t\treturn dt.i18n( 'buttons.copy', 'Copy' );\n\t},\n\n\taction: function ( e, dt, button, config ) {\n\t\tthis.processing( true );\n\n\t\tvar that = this;\n\t\tvar exportData = _exportData( dt, config );\n\t\tvar info = dt.buttons.exportInfo( config );\n\t\tvar newline = _newLine(config);\n\t\tvar output = exportData.str;\n\t\tvar hiddenDiv = $('<div/>')\n\t\t\t.css( {\n\t\t\t\theight: 1,\n\t\t\t\twidth: 1,\n\t\t\t\toverflow: 'hidden',\n\t\t\t\tposition: 'fixed',\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0\n\t\t\t} );\n\n\t\tif ( info.title ) {\n\t\t\toutput = info.title + newline + newline + output;\n\t\t}\n\n\t\tif ( info.messageTop ) {\n\t\t\toutput = info.messageTop + newline + newline + output;\n\t\t}\n\n\t\tif ( info.messageBottom ) {\n\t\t\toutput = output + newline + newline + info.messageBottom;\n\t\t}\n\n\t\tif ( config.customize ) {\n\t\t\toutput = config.customize( output, config, dt );\n\t\t}\n\n\t\tvar textarea = $('<textarea readonly/>')\n\t\t\t.val( output )\n\t\t\t.appendTo( hiddenDiv );\n\n\t\t// For browsers that support the copy execCommand, try to use it\n\t\tif ( document.queryCommandSupported('copy') ) {\n\t\t\thiddenDiv.appendTo( dt.table().container() );\n\t\t\ttextarea[0].focus();\n\t\t\ttextarea[0].select();\n\n\t\t\ttry {\n\t\t\t\tvar successful = document.execCommand( 'copy' );\n\t\t\t\thiddenDiv.remove();\n\n\t\t\t\tif (successful) {\n\t\t\t\t\tdt.buttons.info(\n\t\t\t\t\t\tdt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ),\n\t\t\t\t\t\tdt.i18n( 'buttons.copySuccess', {\n\t\t\t\t\t\t\t1: 'Copied one row to clipboard',\n\t\t\t\t\t\t\t_: 'Copied %d rows to clipboard'\n\t\t\t\t\t\t}, exportData.rows ),\n\t\t\t\t\t\t2000\n\t\t\t\t\t);\n\n\t\t\t\t\tthis.processing( false );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (t) {}\n\t\t}\n\n\t\t// Otherwise we show the text box and instruct the user to use it\n\t\tvar message = $('<span>'+dt.i18n( 'buttons.copyKeys',\n\t\t\t\t'Press <i>ctrl</i> or <i>\\u2318</i> + <i>C</i> to copy the table data<br>to your system clipboard.<br><br>'+\n\t\t\t\t'To cancel, click this message or press escape.' )+'</span>'\n\t\t\t)\n\t\t\t.append( hiddenDiv );\n\n\t\tdt.buttons.info( dt.i18n( 'buttons.copyTitle', 'Copy to clipboard' ), message, 0 );\n\n\t\t// Select the text so when the user activates their system clipboard\n\t\t// it will copy that text\n\t\ttextarea[0].focus();\n\t\ttextarea[0].select();\n\n\t\t// Event to hide the message when the user is done\n\t\tvar container = $(message).closest('.dt-button-info');\n\t\tvar close = function () {\n\t\t\tcontainer.off( 'click.buttons-copy' );\n\t\t\t$(document).off( '.buttons-copy' );\n\t\t\tdt.buttons.info( false );\n\t\t};\n\n\t\tcontainer.on( 'click.buttons-copy', close );\n\t\t$(document)\n\t\t\t.on( 'keydown.buttons-copy', function (e) {\n\t\t\t\tif ( e.keyCode === 27 ) { // esc\n\t\t\t\t\tclose();\n\t\t\t\t\tthat.processing( false );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.on( 'copy.buttons-copy cut.buttons-copy', function () {\n\t\t\t\tclose();\n\t\t\t\tthat.processing( false );\n\t\t\t} );\n\t},\n\n\texportOptions: {},\n\n\tfieldSeparator: '\\t',\n\n\tfieldBoundary: '',\n\n\theader: true,\n\n\tfooter: false,\n\n\ttitle: '*',\n\n\tmessageTop: '*',\n\n\tmessageBottom: '*'\n};\n\n//\n// CSV export\n//\nDataTable.ext.buttons.csvHtml5 = {\n\tbom: false,\n\n\tclassName: 'buttons-csv buttons-html5',\n\n\tavailable: function () {\n\t\treturn window.FileReader !== undefined && window.Blob;\n\t},\n\n\ttext: function ( dt ) {\n\t\treturn dt.i18n( 'buttons.csv', 'CSV' );\n\t},\n\n\taction: function ( e, dt, button, config ) {\n\t\tthis.processing( true );\n\n\t\t// Set the text\n\t\tvar output = _exportData( dt, config ).str;\n\t\tvar info = dt.buttons.exportInfo(config);\n\t\tvar charset = config.charset;\n\n\t\tif ( config.customize ) {\n\t\t\toutput = config.customize( output, config, dt );\n\t\t}\n\n\t\tif ( charset !== false ) {\n\t\t\tif ( ! charset ) {\n\t\t\t\tcharset = document.characterSet || document.charset;\n\t\t\t}\n\n\t\t\tif ( charset ) {\n\t\t\t\tcharset = ';charset='+charset;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcharset = '';\n\t\t}\n\n\t\tif ( config.bom ) {\n\t\t\toutput = String.fromCharCode(0xFEFF) + output;\n\t\t}\n\n\t\t_saveAs(\n\t\t\tnew Blob( [output], {type: 'text/csv'+charset} ),\n\t\t\tinfo.filename,\n\t\t\ttrue\n\t\t);\n\n\t\tthis.processing( false );\n\t},\n\n\tfilename: '*',\n\n\textension: '.csv',\n\n\texportOptions: {},\n\n\tfieldSeparator: ',',\n\n\tfieldBoundary: '\"',\n\n\tescapeChar: '\"',\n\n\tcharset: null,\n\n\theader: true,\n\n\tfooter: false\n};\n\n//\n// Excel (xlsx) export\n//\nDataTable.ext.buttons.excelHtml5 = {\n\tclassName: 'buttons-excel buttons-html5',\n\n\tavailable: function () {\n\t\treturn window.FileReader !== undefined && _jsZip() !== undefined && ! _isDuffSafari() && _serialiser;\n\t},\n\n\ttext: function ( dt ) {\n\t\treturn dt.i18n( 'buttons.excel', 'Excel' );\n\t},\n\n\taction: function ( e, dt, button, config ) {\n\t\tthis.processing( true );\n\n\t\tvar that = this;\n\t\tvar rowPos = 0;\n\t\tvar dataStartRow, dataEndRow;\n\t\tvar getXml = function ( type ) {\n\t\t\tvar str = excelStrings[ type ];\n\n\t\t\t//str = str.replace( /xmlns:/g, 'xmlns_' ).replace( /mc:/g, 'mc_' );\n\n\t\t\treturn $.parseXML( str );\n\t\t};\n\t\tvar rels = getXml('xl/worksheets/sheet1.xml');\n\t\tvar relsGet = rels.getElementsByTagName( \"sheetData\" )[0];\n\n\t\tvar xlsx = {\n\t\t\t_rels: {\n\t\t\t\t\".rels\": getXml('_rels/.rels')\n\t\t\t},\n\t\t\txl: {\n\t\t\t\t_rels: {\n\t\t\t\t\t\"workbook.xml.rels\": getXml('xl/_rels/workbook.xml.rels')\n\t\t\t\t},\n\t\t\t\t\"workbook.xml\": getXml('xl/workbook.xml'),\n\t\t\t\t\"styles.xml\": getXml('xl/styles.xml'),\n\t\t\t\t\"worksheets\": {\n\t\t\t\t\t\"sheet1.xml\": rels\n\t\t\t\t}\n\n\t\t\t},\n\t\t\t\"[Content_Types].xml\": getXml('[Content_Types].xml')\n\t\t};\n\n\t\tvar data = dt.buttons.exportData( config.exportOptions );\n\t\tvar currentRow, rowNode;\n\t\tvar addRow = function ( row ) {\n\t\t\tcurrentRow = rowPos+1;\n\t\t\trowNode = _createNode( rels, \"row\", { attr: {r:currentRow} } );\n\n\t\t\tfor ( var i=0, ien=row.length ; i<ien ; i++ ) {\n\t\t\t\t// Concat both the Cell Columns as a letter and the Row of the cell.\n\t\t\t\tvar cellId = createCellPos(i) + '' + currentRow;\n\t\t\t\tvar cell = null;\n\n\t\t\t\t// For null, undefined of blank cell, continue so it doesn't create the _createNode\n\t\t\t\tif ( row[i] === null || row[i] === undefined || row[i] === '' ) {\n\t\t\t\t\tif ( config.createEmptyCells === true ) {\n\t\t\t\t\t\trow[i] = '';\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar originalContent = row[i];\n\t\t\t\trow[i] = typeof row[i].trim === 'function'\n\t\t\t\t\t? row[i].trim()\n\t\t\t\t\t: row[i];\n\n\t\t\t\t// Special number formatting options\n\t\t\t\tfor ( var j=0, jen=_excelSpecials.length ; j<jen ; j++ ) {\n\t\t\t\t\tvar special = _excelSpecials[j];\n\n\t\t\t\t\t// TODO Need to provide the ability for the specials to say\n\t\t\t\t\t// if they are returning a string, since at the moment it is\n\t\t\t\t\t// assumed to be a number\n\t\t\t\t\tif ( row[i].match && ! row[i].match(/^0\\d+/) && row[i].match( special.match ) ) {\n\t\t\t\t\t\tvar val = row[i].replace(/[^\\d\\.\\-]/g, '');\n\n\t\t\t\t\t\tif ( special.fmt ) {\n\t\t\t\t\t\t\tval = special.fmt( val );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcell = _createNode( rels, 'c', {\n\t\t\t\t\t\t\tattr: {\n\t\t\t\t\t\t\t\tr: cellId,\n\t\t\t\t\t\t\t\ts: special.style\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t_createNode( rels, 'v', { text: val } )\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( ! cell ) {\n\t\t\t\t\tif ( typeof row[i] === 'number' || (\n\t\t\t\t\t\trow[i].match &&\n\t\t\t\t\t\trow[i].match(/^-?\\d+(\\.\\d+)?([eE]\\-?\\d+)?$/) && // Includes exponential format\n\t\t\t\t\t\t! row[i].match(/^0\\d+/) )\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Detect numbers - don't match numbers with leading zeros\n\t\t\t\t\t\t// or a negative anywhere but the start\n\t\t\t\t\t\tcell = _createNode( rels, 'c', {\n\t\t\t\t\t\t\tattr: {\n\t\t\t\t\t\t\t\tt: 'n',\n\t\t\t\t\t\t\t\tr: cellId\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t_createNode( rels, 'v', { text: row[i] } )\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// String output - replace non standard characters for text output\n\t\t\t\t\t\tvar text = ! originalContent.replace ?\n\t\t\t\t\t\t\toriginalContent :\n\t\t\t\t\t\t\toriginalContent.replace(/[\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x9F]/g, '');\n\n\t\t\t\t\t\tcell = _createNode( rels, 'c', {\n\t\t\t\t\t\t\tattr: {\n\t\t\t\t\t\t\t\tt: 'inlineStr',\n\t\t\t\t\t\t\t\tr: cellId\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tchildren:{\n\t\t\t\t\t\t\t\trow: _createNode( rels, 'is', {\n\t\t\t\t\t\t\t\t\tchildren: {\n\t\t\t\t\t\t\t\t\t\trow: _createNode( rels, 't', {\n\t\t\t\t\t\t\t\t\t\t\ttext: text,\n\t\t\t\t\t\t\t\t\t\t\tattr: {\n\t\t\t\t\t\t\t\t\t\t\t\t'xml:space': 'preserve'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trowNode.appendChild( cell );\n\t\t\t}\n\n\t\t\trelsGet.appendChild(rowNode);\n\t\t\trowPos++;\n\t\t};\n\n\t\tif ( config.customizeData ) {\n\t\t\tconfig.customizeData( data );\n\t\t}\n\n\t\tvar mergeCells = function ( row, colspan ) {\n\t\t\tvar mergeCells = $('mergeCells', rels);\n\n\t\t\tmergeCells[0].appendChild( _createNode( rels, 'mergeCell', {\n\t\t\t\tattr: {\n\t\t\t\t\tref: 'A'+row+':'+createCellPos(colspan)+row\n\t\t\t\t}\n\t\t\t} ) );\n\t\t\tmergeCells.attr( 'count', parseFloat(mergeCells.attr( 'count' ))+1 );\n\t\t\t$('row:eq('+(row-1)+') c', rels).attr( 's', '51' ); // centre\n\t\t};\n\n\t\t// Title and top messages\n\t\tvar exportInfo = dt.buttons.exportInfo( config );\n\t\tif ( exportInfo.title ) {\n\t\t\taddRow( [exportInfo.title], rowPos );\n\t\t\tmergeCells( rowPos, data.header.length-1 );\n\t\t}\n\n\t\tif ( exportInfo.messageTop ) {\n\t\t\taddRow( [exportInfo.messageTop], rowPos );\n\t\t\tmergeCells( rowPos, data.header.length-1 );\n\t\t}\n\n\n\t\t// Table itself\n\t\tif ( config.header ) {\n\t\t\taddRow( data.header, rowPos );\n\t\t\t$('row:last c', rels).attr( 's', '2' ); // bold\n\t\t}\n\t\n\t\tdataStartRow = rowPos;\n\n\t\tfor ( var n=0, ie=data.body.length ; n<ie ; n++ ) {\n\t\t\taddRow( data.body[n], rowPos );\n\t\t}\n\t\n\t\tdataEndRow = rowPos;\n\n\t\tif ( config.footer && data.footer ) {\n\t\t\taddRow( data.footer, rowPos);\n\t\t\t$('row:last c', rels).attr( 's', '2' ); // bold\n\t\t}\n\n\t\t// Below the table\n\t\tif ( exportInfo.messageBottom ) {\n\t\t\taddRow( [exportInfo.messageBottom], rowPos );\n\t\t\tmergeCells( rowPos, data.header.length-1 );\n\t\t}\n\n\t\t// Set column widths\n\t\tvar cols = _createNode( rels, 'cols' );\n\t\t$('worksheet', rels).prepend( cols );\n\n\t\tfor ( var i=0, ien=data.header.length ; i<ien ; i++ ) {\n\t\t\tcols.appendChild( _createNode( rels, 'col', {\n\t\t\t\tattr: {\n\t\t\t\t\tmin: i+1,\n\t\t\t\t\tmax: i+1,\n\t\t\t\t\twidth: _excelColWidth( data, i ),\n\t\t\t\t\tcustomWidth: 1\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\t// Workbook modifications\n\t\tvar workbook = xlsx.xl['workbook.xml'];\n\n\t\t$( 'sheets sheet', workbook ).attr( 'name', _sheetname( config ) );\n\n\t\t// Auto filter for columns\n\t\tif ( config.autoFilter ) {\n\t\t\t$('mergeCells', rels).before( _createNode( rels, 'autoFilter', {\n\t\t\t\tattr: {\n\t\t\t\t\tref: 'A'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\t\t$('definedNames', workbook).append( _createNode( workbook, 'definedName', {\n\t\t\t\tattr: {\n\t\t\t\t\tname: '_xlnm._FilterDatabase',\n\t\t\t\t\tlocalSheetId: '0',\n\t\t\t\t\thidden: 1\n\t\t\t\t},\n\t\t\t\ttext: _sheetname(config)+'!$A$'+dataStartRow+':'+createCellPos(data.header.length-1)+dataEndRow\n\t\t\t} ) );\n\t\t}\n\n\t\t// Let the developer customise the document if they want to\n\t\tif ( config.customize ) {\n\t\t\tconfig.customize( xlsx, config, dt );\n\t\t}\n\n\t\t// Excel doesn't like an empty mergeCells tag\n\t\tif ( $('mergeCells', rels).children().length === 0 ) {\n\t\t\t$('mergeCells', rels).remove();\n\t\t}\n\n\t\tvar jszip = _jsZip();\n\t\tvar zip = new jszip();\n\t\tvar zipConfig = {\n\t\t\ttype: 'blob',\n\t\t\tmimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n\t\t};\n\n\t\t_addToZip( zip, xlsx );\n\n\t\tif ( zip.generateAsync ) {\n\t\t\t// JSZip 3+\n\t\t\tzip\n\t\t\t\t.generateAsync( zipConfig )\n\t\t\t\t.then( function ( blob ) {\n\t\t\t\t\t_saveAs( blob, exportInfo.filename );\n\t\t\t\t\tthat.processing( false );\n\t\t\t\t} );\n\t\t}\n\t\telse {\n\t\t\t// JSZip 2.5\n\t\t\t_saveAs(\n\t\t\t\tzip.generate( zipConfig ),\n\t\t\t\texportInfo.filename\n\t\t\t);\n\t\t\tthis.processing( false );\n\t\t}\n\t},\n\n\tfilename: '*',\n\n\textension: '.xlsx',\n\n\texportOptions: {},\n\n\theader: true,\n\n\tfooter: false,\n\n\ttitle: '*',\n\n\tmessageTop: '*',\n\n\tmessageBottom: '*',\n\n\tcreateEmptyCells: false,\n\n\tautoFilter: false,\n\n\tsheetName: ''\n};\n\n//\n// PDF export - using pdfMake - http://pdfmake.org\n//\nDataTable.ext.buttons.pdfHtml5 = {\n\tclassName: 'buttons-pdf buttons-html5',\n\n\tavailable: function () {\n\t\treturn window.FileReader !== undefined && _pdfMake();\n\t},\n\n\ttext: function ( dt ) {\n\t\treturn dt.i18n( 'buttons.pdf', 'PDF' );\n\t},\n\n\taction: function ( e, dt, button, config ) {\n\t\tthis.processing( true );\n\n\t\tvar that = this;\n\t\tvar data = dt.buttons.exportData( config.exportOptions );\n\t\tvar info = dt.buttons.exportInfo( config );\n\t\tvar rows = [];\n\n\t\tif ( config.header ) {\n\t\t\trows.push( $.map( data.header, function ( d ) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: typeof d === 'string' ? d : d+'',\n\t\t\t\t\tstyle: 'tableHeader'\n\t\t\t\t};\n\t\t\t} ) );\n\t\t}\n\n\t\tfor ( var i=0, ien=data.body.length ; i<ien ; i++ ) {\n\t\t\trows.push( $.map( data.body[i], function ( d ) {\n\t\t\t\tif ( d === null || d === undefined ) {\n\t\t\t\t\td = '';\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\ttext: typeof d === 'string' ? d : d+'',\n\t\t\t\t\tstyle: i % 2 ? 'tableBodyEven' : 'tableBodyOdd'\n\t\t\t\t};\n\t\t\t} ) );\n\t\t}\n\n\t\tif ( config.footer && data.footer) {\n\t\t\trows.push( $.map( data.footer, function ( d ) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: typeof d === 'string' ? d : d+'',\n\t\t\t\t\tstyle: 'tableFooter'\n\t\t\t\t};\n\t\t\t} ) );\n\t\t}\n\n\t\tvar doc = {\n\t\t\tpageSize: config.pageSize,\n\t\t\tpageOrientation: config.orientation,\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttable: {\n\t\t\t\t\t\theaderRows: 1,\n\t\t\t\t\t\tbody: rows\n\t\t\t\t\t},\n\t\t\t\t\tlayout: 'noBorders'\n\t\t\t\t}\n\t\t\t],\n\t\t\tstyles: {\n\t\t\t\ttableHeader: {\n\t\t\t\t\tbold: true,\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tcolor: 'white',\n\t\t\t\t\tfillColor: '#2d4154',\n\t\t\t\t\talignment: 'center'\n\t\t\t\t},\n\t\t\t\ttableBodyEven: {},\n\t\t\t\ttableBodyOdd: {\n\t\t\t\t\tfillColor: '#f3f3f3'\n\t\t\t\t},\n\t\t\t\ttableFooter: {\n\t\t\t\t\tbold: true,\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tcolor: 'white',\n\t\t\t\t\tfillColor: '#2d4154'\n\t\t\t\t},\n\t\t\t\ttitle: {\n\t\t\t\t\talignment: 'center',\n\t\t\t\t\tfontSize: 15\n\t\t\t\t},\n\t\t\t\tmessage: {}\n\t\t\t},\n\t\t\tdefaultStyle: {\n\t\t\t\tfontSize: 10\n\t\t\t}\n\t\t};\n\n\t\tif ( info.messageTop ) {\n\t\t\tdoc.content.unshift( {\n\t\t\t\ttext: info.messageTop,\n\t\t\t\tstyle: 'message',\n\t\t\t\tmargin: [ 0, 0, 0, 12 ]\n\t\t\t} );\n\t\t}\n\n\t\tif ( info.messageBottom ) {\n\t\t\tdoc.content.push( {\n\t\t\t\ttext: info.messageBottom,\n\t\t\t\tstyle: 'message',\n\t\t\t\tmargin: [ 0, 0, 0, 12 ]\n\t\t\t} );\n\t\t}\n\n\t\tif ( info.title ) {\n\t\t\tdoc.content.unshift( {\n\t\t\t\ttext: info.title,\n\t\t\t\tstyle: 'title',\n\t\t\t\tmargin: [ 0, 0, 0, 12 ]\n\t\t\t} );\n\t\t}\n\n\t\tif ( config.customize ) {\n\t\t\tconfig.customize( doc, config, dt );\n\t\t}\n\n\t\tvar pdf = _pdfMake().createPdf( doc );\n\n\t\tif ( config.download === 'open' && ! _isDuffSafari() ) {\n\t\t\tpdf.open();\n\t\t}\n\t\telse {\n\t\t\tpdf.download( info.filename );\n\t\t}\n\n\t\tthis.processing( false );\n\t},\n\n\ttitle: '*',\n\n\tfilename: '*',\n\n\textension: '.pdf',\n\n\texportOptions: {},\n\n\torientation: 'portrait',\n\n\tpageSize: 'A4',\n\n\theader: true,\n\n\tfooter: false,\n\n\tmessageTop: '*',\n\n\tmessageBottom: '*',\n\n\tcustomize: null,\n\n\tdownload: 'download'\n};\n\n\nreturn DataTable.Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnV0dG9ucy9qcy9idXR0b25zLmh0bWw1LmpzLmpzIiwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTSxJQUEwQztBQUNoRDtBQUNBLEVBQUUsaUNBQVEsQ0FBQywyQ0FBUSxFQUFFLDJEQUFnQixFQUFFLG1IQUF3QixDQUFDLG1DQUFFO0FBQ2xFO0FBQ0EsR0FBRztBQUFBLGtHQUFFO0FBQ0w7QUFDQSxNQUFNLEVBcUJKO0FBQ0YsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQSxNQUFNLE9BQU87QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNERBQTREO0FBQzVELDBEQUEwRCxnQkFBZ0I7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpRkFBaUYsR0FBRyx5QkFBeUI7QUFDN0c7QUFDQTtBQUNBLHNCQUFzQjtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixZQUFZLFdBQVc7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxlQUFlO0FBQzFCLFdBQVcsV0FBVztBQUN0QixZQUFZLGVBQWU7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdDQUFnQyxRQUFRO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSx1Q0FBdUMsUUFBUTtBQUMvQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFNBQVM7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxZQUFZLEtBQUs7QUFDakIsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNENBQTRDLE9BQU87QUFDbkQ7QUFDQTs7QUFFQTtBQUNBLG9CQUFvQixtQ0FBbUM7O0FBRXZEO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQixZQUFZLFFBQVE7QUFDcEIsWUFBWSxRQUFRO0FBQ3BCO0FBQ0EsWUFBWSxpQkFBaUI7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEIsWUFBWSxRQUFRO0FBQ3BCLFlBQVksYUFBYTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLFFBQVE7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxPQUFPO0FBQ3JEO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUMsaURBQWlEO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRyxxRUFBcUUsaUJBQWlCO0FBQ3pGLEdBQUcscUVBQXFFLGlCQUFpQjtBQUN6RixHQUFHLGlEQUFpRDtBQUNwRCxHQUFHLGlEQUFpRDtBQUNwRCxHQUFHLGlEQUFpRDtBQUNwRCxHQUFHLGlEQUFpRDtBQUNwRCxHQUFHLG9CQUFvQixFQUFFLDJCQUEyQjtBQUNwRCxHQUFHLHFFQUFxRSx5Q0FBeUM7QUFDakgsR0FBRyxzQkFBc0IsRUFBRSw2Q0FBNkMseUNBQXlDO0FBQ2pILEdBQUcsaURBQWlEO0FBQ3BELEdBQUcsdUJBQXVCLEVBQUUsd0JBQXdCO0FBQ3BELEdBQUcsY0FBYyxFQUFFLHdEQUF3RCwrREFBK0Q7QUFDMUk7Ozs7QUFJQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsRUFBRTs7QUFFRixrQkFBa0I7O0FBRWxCOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdCQUF3QiwwQkFBMEI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQSxrQkFBa0I7O0FBRWxCOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLE9BQU8sZ0JBQWdCOztBQUVoRSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0NBQStDLFFBQVE7QUFDdkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSxrQ0FBa0MsWUFBWTtBQUM5QztBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLGtDQUFrQyxlQUFlO0FBQ2pEO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSx1REFBdUQ7QUFDdkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxPQUFPO0FBQzlDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsMENBQTBDLFFBQVE7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUEsa0JBQWtCOztBQUVsQjs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsd0NBQXdDLFFBQVE7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQTs7QUFFQSxrQkFBa0I7O0FBRWxCOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0EsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL1Z1ZXh5Ly4vbm9kZV9tb2R1bGVzL2RhdGF0YWJsZXMubmV0LWJ1dHRvbnMvanMvYnV0dG9ucy5odG1sNS5qcz85YzJiIl0sInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogSFRNTDUgZXhwb3J0IGJ1dHRvbnMgZm9yIEJ1dHRvbnMgYW5kIERhdGFUYWJsZXMuXG4gKiAyMDE2IFNwcnlNZWRpYSBMdGQgLSBkYXRhdGFibGVzLm5ldC9saWNlbnNlXG4gKlxuICogRmlsZVNhdmVyLmpzICgxLjMuMykgLSBNSVQgbGljZW5zZVxuICogQ29weXJpZ2h0IMKpIDIwMTYgRWxpIEdyZXkgLSBodHRwOi8vZWxpZ3JleS5jb21cbiAqL1xuXG4oZnVuY3Rpb24oIGZhY3RvcnkgKXtcblx0aWYgKCB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKCBbJ2pxdWVyeScsICdkYXRhdGFibGVzLm5ldCcsICdkYXRhdGFibGVzLm5ldC1idXR0b25zJ10sIGZ1bmN0aW9uICggJCApIHtcblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCB3aW5kb3csIGRvY3VtZW50ICk7XG5cdFx0fSApO1xuXHR9XG5cdGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyb290LCAkLCBqc3ppcCwgcGRmbWFrZSkge1xuXHRcdFx0aWYgKCAhIHJvb3QgKSB7XG5cdFx0XHRcdHJvb3QgPSB3aW5kb3c7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggISAkIHx8ICEgJC5mbi5kYXRhVGFibGUgKSB7XG5cdFx0XHRcdCQgPSByZXF1aXJlKCdkYXRhdGFibGVzLm5ldCcpKHJvb3QsICQpLiQ7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggISAkLmZuLmRhdGFUYWJsZS5CdXR0b25zICkge1xuXHRcdFx0XHRyZXF1aXJlKCdkYXRhdGFibGVzLm5ldC1idXR0b25zJykocm9vdCwgJCk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCByb290LCByb290LmRvY3VtZW50LCBqc3ppcCwgcGRmbWFrZSApO1xuXHRcdH07XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gQnJvd3NlclxuXHRcdGZhY3RvcnkoIGpRdWVyeSwgd2luZG93LCBkb2N1bWVudCApO1xuXHR9XG59KGZ1bmN0aW9uKCAkLCB3aW5kb3csIGRvY3VtZW50LCBqc3ppcCwgcGRmbWFrZSwgdW5kZWZpbmVkICkge1xuJ3VzZSBzdHJpY3QnO1xudmFyIERhdGFUYWJsZSA9ICQuZm4uZGF0YVRhYmxlO1xuXG4vLyBBbGxvdyB0aGUgY29uc3RydWN0b3IgdG8gcGFzcyBpbiBKU1ppcCBhbmQgUERGTWFrZSBmcm9tIGV4dGVybmFsIHJlcXVpcmVzLlxuLy8gT3RoZXJ3aXNlLCB1c2UgZ2xvYmFsbHkgZGVmaW5lZCB2YXJpYWJsZXMsIGlmIHRoZXkgYXJlIGF2YWlsYWJsZS5cbmZ1bmN0aW9uIF9qc1ppcCAoKSB7XG5cdHJldHVybiBqc3ppcCB8fCB3aW5kb3cuSlNaaXA7XG59XG5mdW5jdGlvbiBfcGRmTWFrZSAoKSB7XG5cdHJldHVybiBwZGZtYWtlIHx8IHdpbmRvdy5wZGZNYWtlO1xufVxuXG5EYXRhVGFibGUuQnV0dG9ucy5wZGZNYWtlID0gZnVuY3Rpb24gKF8pIHtcblx0aWYgKCAhIF8gKSB7XG5cdFx0cmV0dXJuIF9wZGZNYWtlKCk7XG5cdH1cblx0cGRmbWFrZSA9IF87XG59XG5cbkRhdGFUYWJsZS5CdXR0b25zLmpzemlwID0gZnVuY3Rpb24gKF8pIHtcblx0aWYgKCAhIF8gKSB7XG5cdFx0cmV0dXJuIF9qc1ppcCgpO1xuXHR9XG5cdGpzemlwID0gXztcbn1cblxuXG4vKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICpcbiAqIEZpbGVTYXZlci5qcyBkZXBlbmRlbmN5XG4gKi9cblxuLypqc2xpbnQgYml0d2lzZTogdHJ1ZSwgaW5kZW50OiA0LCBsYXhicmVhazogdHJ1ZSwgbGF4Y29tbWE6IHRydWUsIHNtYXJ0dGFiczogdHJ1ZSwgcGx1c3BsdXM6IHRydWUgKi9cblxudmFyIF9zYXZlQXMgPSAoZnVuY3Rpb24odmlldykge1xuXHRcInVzZSBzdHJpY3RcIjtcblx0Ly8gSUUgPDEwIGlzIGV4cGxpY2l0bHkgdW5zdXBwb3J0ZWRcblx0aWYgKHR5cGVvZiB2aWV3ID09PSBcInVuZGVmaW5lZFwiIHx8IHR5cGVvZiBuYXZpZ2F0b3IgIT09IFwidW5kZWZpbmVkXCIgJiYgL01TSUUgWzEtOV1cXC4vLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0dmFyXG5cdFx0ICBkb2MgPSB2aWV3LmRvY3VtZW50XG5cdFx0ICAvLyBvbmx5IGdldCBVUkwgd2hlbiBuZWNlc3NhcnkgaW4gY2FzZSBCbG9iLmpzIGhhc24ndCBvdmVycmlkZGVuIGl0IHlldFxuXHRcdCwgZ2V0X1VSTCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHZpZXcuVVJMIHx8IHZpZXcud2Via2l0VVJMIHx8IHZpZXc7XG5cdFx0fVxuXHRcdCwgc2F2ZV9saW5rID0gZG9jLmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIiwgXCJhXCIpXG5cdFx0LCBjYW5fdXNlX3NhdmVfbGluayA9IFwiZG93bmxvYWRcIiBpbiBzYXZlX2xpbmtcblx0XHQsIGNsaWNrID0gZnVuY3Rpb24obm9kZSkge1xuXHRcdFx0dmFyIGV2ZW50ID0gbmV3IE1vdXNlRXZlbnQoXCJjbGlja1wiKTtcblx0XHRcdG5vZGUuZGlzcGF0Y2hFdmVudChldmVudCk7XG5cdFx0fVxuXHRcdCwgaXNfc2FmYXJpID0gL2NvbnN0cnVjdG9yL2kudGVzdCh2aWV3LkhUTUxFbGVtZW50KSB8fCB2aWV3LnNhZmFyaVxuXHRcdCwgaXNfY2hyb21lX2lvcyA9L0NyaU9TXFwvW1xcZF0rLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpXG5cdFx0LCB0aHJvd19vdXRzaWRlID0gZnVuY3Rpb24oZXgpIHtcblx0XHRcdCh2aWV3LnNldEltbWVkaWF0ZSB8fCB2aWV3LnNldFRpbWVvdXQpKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR0aHJvdyBleDtcblx0XHRcdH0sIDApO1xuXHRcdH1cblx0XHQsIGZvcmNlX3NhdmVhYmxlX3R5cGUgPSBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiXG5cdFx0Ly8gdGhlIEJsb2IgQVBJIGlzIGZ1bmRhbWVudGFsbHkgYnJva2VuIGFzIHRoZXJlIGlzIG5vIFwiZG93bmxvYWRmaW5pc2hlZFwiIGV2ZW50IHRvIHN1YnNjcmliZSB0b1xuXHRcdCwgYXJiaXRyYXJ5X3Jldm9rZV90aW1lb3V0ID0gMTAwMCAqIDQwIC8vIGluIG1zXG5cdFx0LCByZXZva2UgPSBmdW5jdGlvbihmaWxlKSB7XG5cdFx0XHR2YXIgcmV2b2tlciA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAodHlwZW9mIGZpbGUgPT09IFwic3RyaW5nXCIpIHsgLy8gZmlsZSBpcyBhbiBvYmplY3QgVVJMXG5cdFx0XHRcdFx0Z2V0X1VSTCgpLnJldm9rZU9iamVjdFVSTChmaWxlKTtcblx0XHRcdFx0fSBlbHNlIHsgLy8gZmlsZSBpcyBhIEZpbGVcblx0XHRcdFx0XHRmaWxlLnJlbW92ZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0c2V0VGltZW91dChyZXZva2VyLCBhcmJpdHJhcnlfcmV2b2tlX3RpbWVvdXQpO1xuXHRcdH1cblx0XHQsIGRpc3BhdGNoID0gZnVuY3Rpb24oZmlsZXNhdmVyLCBldmVudF90eXBlcywgZXZlbnQpIHtcblx0XHRcdGV2ZW50X3R5cGVzID0gW10uY29uY2F0KGV2ZW50X3R5cGVzKTtcblx0XHRcdHZhciBpID0gZXZlbnRfdHlwZXMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKGktLSkge1xuXHRcdFx0XHR2YXIgbGlzdGVuZXIgPSBmaWxlc2F2ZXJbXCJvblwiICsgZXZlbnRfdHlwZXNbaV1dO1xuXHRcdFx0XHRpZiAodHlwZW9mIGxpc3RlbmVyID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0bGlzdGVuZXIuY2FsbChmaWxlc2F2ZXIsIGV2ZW50IHx8IGZpbGVzYXZlcik7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXgpIHtcblx0XHRcdFx0XHRcdHRocm93X291dHNpZGUoZXgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHQsIGF1dG9fYm9tID0gZnVuY3Rpb24oYmxvYikge1xuXHRcdFx0Ly8gcHJlcGVuZCBCT00gZm9yIFVURi04IFhNTCBhbmQgdGV4dC8qIHR5cGVzIChpbmNsdWRpbmcgSFRNTClcblx0XHRcdC8vIG5vdGU6IHlvdXIgYnJvd3NlciB3aWxsIGF1dG9tYXRpY2FsbHkgY29udmVydCBVVEYtMTYgVStGRUZGIHRvIEVGIEJCIEJGXG5cdFx0XHRpZiAoL15cXHMqKD86dGV4dFxcL1xcUyp8YXBwbGljYXRpb25cXC94bWx8XFxTKlxcL1xcUypcXCt4bWwpXFxzKjsuKmNoYXJzZXRcXHMqPVxccyp1dGYtOC9pLnRlc3QoYmxvYi50eXBlKSkge1xuXHRcdFx0XHRyZXR1cm4gbmV3IEJsb2IoW1N0cmluZy5mcm9tQ2hhckNvZGUoMHhGRUZGKSwgYmxvYl0sIHt0eXBlOiBibG9iLnR5cGV9KTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBibG9iO1xuXHRcdH1cblx0XHQsIEZpbGVTYXZlciA9IGZ1bmN0aW9uKGJsb2IsIG5hbWUsIG5vX2F1dG9fYm9tKSB7XG5cdFx0XHRpZiAoIW5vX2F1dG9fYm9tKSB7XG5cdFx0XHRcdGJsb2IgPSBhdXRvX2JvbShibG9iKTtcblx0XHRcdH1cblx0XHRcdC8vIEZpcnN0IHRyeSBhLmRvd25sb2FkLCB0aGVuIHdlYiBmaWxlc3lzdGVtLCB0aGVuIG9iamVjdCBVUkxzXG5cdFx0XHR2YXJcblx0XHRcdFx0ICBmaWxlc2F2ZXIgPSB0aGlzXG5cdFx0XHRcdCwgdHlwZSA9IGJsb2IudHlwZVxuXHRcdFx0XHQsIGZvcmNlID0gdHlwZSA9PT0gZm9yY2Vfc2F2ZWFibGVfdHlwZVxuXHRcdFx0XHQsIG9iamVjdF91cmxcblx0XHRcdFx0LCBkaXNwYXRjaF9hbGwgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRkaXNwYXRjaChmaWxlc2F2ZXIsIFwid3JpdGVzdGFydCBwcm9ncmVzcyB3cml0ZSB3cml0ZWVuZFwiLnNwbGl0KFwiIFwiKSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gb24gYW55IGZpbGVzeXMgZXJyb3JzIHJldmVydCB0byBzYXZpbmcgd2l0aCBvYmplY3QgVVJMc1xuXHRcdFx0XHQsIGZzX2Vycm9yID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKChpc19jaHJvbWVfaW9zIHx8IChmb3JjZSAmJiBpc19zYWZhcmkpKSAmJiB2aWV3LkZpbGVSZWFkZXIpIHtcblx0XHRcdFx0XHRcdC8vIFNhZmFyaSBkb2Vzbid0IGFsbG93IGRvd25sb2FkaW5nIG9mIGJsb2IgdXJsc1xuXHRcdFx0XHRcdFx0dmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG5cdFx0XHRcdFx0XHRyZWFkZXIub25sb2FkZW5kID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHZhciB1cmwgPSBpc19jaHJvbWVfaW9zID8gcmVhZGVyLnJlc3VsdCA6IHJlYWRlci5yZXN1bHQucmVwbGFjZSgvXmRhdGE6W147XSo7LywgJ2RhdGE6YXR0YWNobWVudC9maWxlOycpO1xuXHRcdFx0XHRcdFx0XHR2YXIgcG9wdXAgPSB2aWV3Lm9wZW4odXJsLCAnX2JsYW5rJyk7XG5cdFx0XHRcdFx0XHRcdGlmKCFwb3B1cCkgdmlldy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuXHRcdFx0XHRcdFx0XHR1cmw9dW5kZWZpbmVkOyAvLyByZWxlYXNlIHJlZmVyZW5jZSBiZWZvcmUgZGlzcGF0Y2hpbmdcblx0XHRcdFx0XHRcdFx0ZmlsZXNhdmVyLnJlYWR5U3RhdGUgPSBmaWxlc2F2ZXIuRE9ORTtcblx0XHRcdFx0XHRcdFx0ZGlzcGF0Y2hfYWxsKCk7XG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0cmVhZGVyLnJlYWRBc0RhdGFVUkwoYmxvYik7XG5cdFx0XHRcdFx0XHRmaWxlc2F2ZXIucmVhZHlTdGF0ZSA9IGZpbGVzYXZlci5JTklUO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyBkb24ndCBjcmVhdGUgbW9yZSBvYmplY3QgVVJMcyB0aGFuIG5lZWRlZFxuXHRcdFx0XHRcdGlmICghb2JqZWN0X3VybCkge1xuXHRcdFx0XHRcdFx0b2JqZWN0X3VybCA9IGdldF9VUkwoKS5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChmb3JjZSkge1xuXHRcdFx0XHRcdFx0dmlldy5sb2NhdGlvbi5ocmVmID0gb2JqZWN0X3VybDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dmFyIG9wZW5lZCA9IHZpZXcub3BlbihvYmplY3RfdXJsLCBcIl9ibGFua1wiKTtcblx0XHRcdFx0XHRcdGlmICghb3BlbmVkKSB7XG5cdFx0XHRcdFx0XHRcdC8vIEFwcGxlIGRvZXMgbm90IGFsbG93IHdpbmRvdy5vcGVuLCBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIuYXBwbGUuY29tL2xpYnJhcnkvc2FmYXJpL2RvY3VtZW50YXRpb24vVG9vbHMvQ29uY2VwdHVhbC9TYWZhcmlFeHRlbnNpb25HdWlkZS9Xb3JraW5nd2l0aFdpbmRvd3NhbmRUYWJzL1dvcmtpbmd3aXRoV2luZG93c2FuZFRhYnMuaHRtbFxuXHRcdFx0XHRcdFx0XHR2aWV3LmxvY2F0aW9uLmhyZWYgPSBvYmplY3RfdXJsO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRmaWxlc2F2ZXIucmVhZHlTdGF0ZSA9IGZpbGVzYXZlci5ET05FO1xuXHRcdFx0XHRcdGRpc3BhdGNoX2FsbCgpO1xuXHRcdFx0XHRcdHJldm9rZShvYmplY3RfdXJsKTtcblx0XHRcdFx0fVxuXHRcdFx0O1xuXHRcdFx0ZmlsZXNhdmVyLnJlYWR5U3RhdGUgPSBmaWxlc2F2ZXIuSU5JVDtcblxuXHRcdFx0aWYgKGNhbl91c2Vfc2F2ZV9saW5rKSB7XG5cdFx0XHRcdG9iamVjdF91cmwgPSBnZXRfVVJMKCkuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuXHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHNhdmVfbGluay5ocmVmID0gb2JqZWN0X3VybDtcblx0XHRcdFx0XHRzYXZlX2xpbmsuZG93bmxvYWQgPSBuYW1lO1xuXHRcdFx0XHRcdGNsaWNrKHNhdmVfbGluayk7XG5cdFx0XHRcdFx0ZGlzcGF0Y2hfYWxsKCk7XG5cdFx0XHRcdFx0cmV2b2tlKG9iamVjdF91cmwpO1xuXHRcdFx0XHRcdGZpbGVzYXZlci5yZWFkeVN0YXRlID0gZmlsZXNhdmVyLkRPTkU7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGZzX2Vycm9yKCk7XG5cdFx0fVxuXHRcdCwgRlNfcHJvdG8gPSBGaWxlU2F2ZXIucHJvdG90eXBlXG5cdFx0LCBzYXZlQXMgPSBmdW5jdGlvbihibG9iLCBuYW1lLCBub19hdXRvX2JvbSkge1xuXHRcdFx0cmV0dXJuIG5ldyBGaWxlU2F2ZXIoYmxvYiwgbmFtZSB8fCBibG9iLm5hbWUgfHwgXCJkb3dubG9hZFwiLCBub19hdXRvX2JvbSk7XG5cdFx0fVxuXHQ7XG5cdC8vIElFIDEwKyAobmF0aXZlIHNhdmVBcylcblx0aWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT09IFwidW5kZWZpbmVkXCIgJiYgbmF2aWdhdG9yLm1zU2F2ZU9yT3BlbkJsb2IpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oYmxvYiwgbmFtZSwgbm9fYXV0b19ib20pIHtcblx0XHRcdG5hbWUgPSBuYW1lIHx8IGJsb2IubmFtZSB8fCBcImRvd25sb2FkXCI7XG5cblx0XHRcdGlmICghbm9fYXV0b19ib20pIHtcblx0XHRcdFx0YmxvYiA9IGF1dG9fYm9tKGJsb2IpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG5hdmlnYXRvci5tc1NhdmVPck9wZW5CbG9iKGJsb2IsIG5hbWUpO1xuXHRcdH07XG5cdH1cblxuXHRGU19wcm90by5hYm9ydCA9IGZ1bmN0aW9uKCl7fTtcblx0RlNfcHJvdG8ucmVhZHlTdGF0ZSA9IEZTX3Byb3RvLklOSVQgPSAwO1xuXHRGU19wcm90by5XUklUSU5HID0gMTtcblx0RlNfcHJvdG8uRE9ORSA9IDI7XG5cblx0RlNfcHJvdG8uZXJyb3IgPVxuXHRGU19wcm90by5vbndyaXRlc3RhcnQgPVxuXHRGU19wcm90by5vbnByb2dyZXNzID1cblx0RlNfcHJvdG8ub253cml0ZSA9XG5cdEZTX3Byb3RvLm9uYWJvcnQgPVxuXHRGU19wcm90by5vbmVycm9yID1cblx0RlNfcHJvdG8ub253cml0ZWVuZCA9XG5cdFx0bnVsbDtcblxuXHRyZXR1cm4gc2F2ZUFzO1xufShcblx0ICAgdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgJiYgc2VsZlxuXHR8fCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmIHdpbmRvd1xuXHR8fCB0aGlzLmNvbnRlbnRcbikpO1xuXG5cbi8vIEV4cG9zZSBmaWxlIHNhdmVyIG9uIHRoZSBEYXRhVGFibGVzIEFQSS4gQ2FuJ3QgYXR0YWNoIHRvIGBEYXRhVGFibGVzLkJ1dHRvbnNgXG4vLyBzaW5jZSB0aGlzIGZpbGUgY2FuIGJlIGxvYWRlZCBiZWZvcmUgQnV0dG9uJ3MgY29yZSFcbkRhdGFUYWJsZS5maWxlU2F2ZSA9IF9zYXZlQXM7XG5cblxuLyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG4gKiBMb2NhbCAocHJpdmF0ZSkgZnVuY3Rpb25zXG4gKi9cblxuLyoqXG4gKiBHZXQgdGhlIHNoZWV0IG5hbWUgZm9yIEV4Y2VsIGV4cG9ydHMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9XHRjb25maWcgQnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqL1xudmFyIF9zaGVldG5hbWUgPSBmdW5jdGlvbiAoIGNvbmZpZyApXG57XG5cdHZhciBzaGVldE5hbWUgPSAnU2hlZXQxJztcblxuXHRpZiAoIGNvbmZpZy5zaGVldE5hbWUgKSB7XG5cdFx0c2hlZXROYW1lID0gY29uZmlnLnNoZWV0TmFtZS5yZXBsYWNlKC9bXFxbXFxdXFwqXFwvXFxcXFxcP1xcOl0vZywgJycpO1xuXHR9XG5cblx0cmV0dXJuIHNoZWV0TmFtZTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBuZXdsaW5lIGNoYXJhY3RlcihzKVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fVx0Y29uZmlnIEJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJuIHtzdHJpbmd9XHRcdFx0XHROZXdsaW5lIGNoYXJhY3RlclxuICovXG52YXIgX25ld0xpbmUgPSBmdW5jdGlvbiAoIGNvbmZpZyApXG57XG5cdHJldHVybiBjb25maWcubmV3bGluZSA/XG5cdFx0Y29uZmlnLm5ld2xpbmUgOlxuXHRcdG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL1dpbmRvd3MvKSA/XG5cdFx0XHQnXFxyXFxuJyA6XG5cdFx0XHQnXFxuJztcbn07XG5cbi8qKlxuICogQ29tYmluZSB0aGUgZGF0YSBmcm9tIHRoZSBgYnV0dG9ucy5leHBvcnREYXRhYCBtZXRob2QgaW50byBhIHN0cmluZyB0aGF0XG4gKiB3aWxsIGJlIHVzZWQgaW4gdGhlIGV4cG9ydCBmaWxlLlxuICpcbiAqIEBwYXJhbVx0e0RhdGFUYWJsZS5BcGl9IGR0XHRcdCBEYXRhVGFibGVzIEFQSSBpbnN0YW5jZVxuICogQHBhcmFtXHR7b2JqZWN0fVx0XHRcdFx0Y29uZmlnIEJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJuIHtvYmplY3R9XHRcdFx0XHRcdFx0XHQgVGhlIGRhdGEgdG8gZXhwb3J0XG4gKi9cbnZhciBfZXhwb3J0RGF0YSA9IGZ1bmN0aW9uICggZHQsIGNvbmZpZyApXG57XG5cdHZhciBuZXdMaW5lID0gX25ld0xpbmUoIGNvbmZpZyApO1xuXHR2YXIgZGF0YSA9IGR0LmJ1dHRvbnMuZXhwb3J0RGF0YSggY29uZmlnLmV4cG9ydE9wdGlvbnMgKTtcblx0dmFyIGJvdW5kYXJ5ID0gY29uZmlnLmZpZWxkQm91bmRhcnk7XG5cdHZhciBzZXBhcmF0b3IgPSBjb25maWcuZmllbGRTZXBhcmF0b3I7XG5cdHZhciByZUJvdW5kYXJ5ID0gbmV3IFJlZ0V4cCggYm91bmRhcnksICdnJyApO1xuXHR2YXIgZXNjYXBlQ2hhciA9IGNvbmZpZy5lc2NhcGVDaGFyICE9PSB1bmRlZmluZWQgP1xuXHRcdGNvbmZpZy5lc2NhcGVDaGFyIDpcblx0XHQnXFxcXCc7XG5cdHZhciBqb2luID0gZnVuY3Rpb24gKCBhICkge1xuXHRcdHZhciBzID0gJyc7XG5cblx0XHQvLyBJZiB0aGVyZSBpcyBhIGZpZWxkIGJvdW5kYXJ5LCB0aGVuIHdlIG1pZ2h0IG5lZWQgdG8gZXNjYXBlIGl0IGluXG5cdFx0Ly8gdGhlIHNvdXJjZSBkYXRhXG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRpZiAoIGkgPiAwICkge1xuXHRcdFx0XHRzICs9IHNlcGFyYXRvcjtcblx0XHRcdH1cblxuXHRcdFx0cyArPSBib3VuZGFyeSA/XG5cdFx0XHRcdGJvdW5kYXJ5ICsgKCcnICsgYVtpXSkucmVwbGFjZSggcmVCb3VuZGFyeSwgZXNjYXBlQ2hhcitib3VuZGFyeSApICsgYm91bmRhcnkgOlxuXHRcdFx0XHRhW2ldO1xuXHRcdH1cblxuXHRcdHJldHVybiBzO1xuXHR9O1xuXG5cdHZhciBoZWFkZXIgPSBjb25maWcuaGVhZGVyID8gam9pbiggZGF0YS5oZWFkZXIgKStuZXdMaW5lIDogJyc7XG5cdHZhciBmb290ZXIgPSBjb25maWcuZm9vdGVyICYmIGRhdGEuZm9vdGVyID8gbmV3TGluZStqb2luKCBkYXRhLmZvb3RlciApIDogJyc7XG5cdHZhciBib2R5ID0gW107XG5cblx0Zm9yICggdmFyIGk9MCwgaWVuPWRhdGEuYm9keS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRib2R5LnB1c2goIGpvaW4oIGRhdGEuYm9keVtpXSApICk7XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdHN0cjogaGVhZGVyICsgYm9keS5qb2luKCBuZXdMaW5lICkgKyBmb290ZXIsXG5cdFx0cm93czogYm9keS5sZW5ndGhcblx0fTtcbn07XG5cbi8qKlxuICogT2xkZXIgdmVyc2lvbnMgb2YgU2FmYXJpIChwcmlvciB0byB0ZWNoIHByZXZpZXcgMTgpIGRvbid0IHN1cHBvcnQgdGhlXG4gKiBkb3dubG9hZCBvcHRpb24gcmVxdWlyZWQuXG4gKlxuICogQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIG9sZCBTYWZhcmlcbiAqL1xudmFyIF9pc0R1ZmZTYWZhcmkgPSBmdW5jdGlvbiAoKVxue1xuXHR2YXIgc2FmYXJpID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdTYWZhcmknKSAhPT0gLTEgJiZcblx0XHRuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0Nocm9tZScpID09PSAtMSAmJlxuXHRcdG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignT3BlcmEnKSA9PT0gLTE7XG5cblx0aWYgKCAhIHNhZmFyaSApIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHR2YXIgdmVyc2lvbiA9IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goIC9BcHBsZVdlYktpdFxcLyhcXGQrXFwuXFxkKykvICk7XG5cdGlmICggdmVyc2lvbiAmJiB2ZXJzaW9uLmxlbmd0aCA+IDEgJiYgdmVyc2lvblsxXSoxIDwgNjAzLjEgKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRyZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIENvbnZlcnQgZnJvbSBudW1lcmljIHBvc2l0aW9uIHRvIGxldHRlciBmb3IgY29sdW1uIG5hbWVzIGluIEV4Y2VsXG4gKiBAcGFyYW0gIHtpbnR9IG4gQ29sdW1uIG51bWJlclxuICogQHJldHVybiB7c3RyaW5nfSBDb2x1bW4gbGV0dGVyKHMpIG5hbWVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQ2VsbFBvcyggbiApe1xuXHR2YXIgb3JkQSA9ICdBJy5jaGFyQ29kZUF0KDApO1xuXHR2YXIgb3JkWiA9ICdaJy5jaGFyQ29kZUF0KDApO1xuXHR2YXIgbGVuID0gb3JkWiAtIG9yZEEgKyAxO1xuXHR2YXIgcyA9IFwiXCI7XG5cblx0d2hpbGUoIG4gPj0gMCApIHtcblx0XHRzID0gU3RyaW5nLmZyb21DaGFyQ29kZShuICUgbGVuICsgb3JkQSkgKyBzO1xuXHRcdG4gPSBNYXRoLmZsb29yKG4gLyBsZW4pIC0gMTtcblx0fVxuXG5cdHJldHVybiBzO1xufVxuXG50cnkge1xuXHR2YXIgX3NlcmlhbGlzZXIgPSBuZXcgWE1MU2VyaWFsaXplcigpO1xuXHR2YXIgX2llRXhjZWw7XG59XG5jYXRjaCAodCkge31cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBhZGQgWE1MIGZpbGVzIGZyb20gYW4gb2JqZWN0J3Mgc3RydWN0dXJlIHRvIGEgWklQIGZpbGUuIFRoaXNcbiAqIGFsbG93cyB0aGUgWFNMWCBmaWxlIHRvIGJlIGVhc2lseSBkZWZpbmVkIHdpdGggYW4gb2JqZWN0J3Mgc3RydWN0dXJlIG1hdGNoaW5nXG4gKiB0aGUgZmlsZXMgc3RydWN0dXJlLlxuICpcbiAqIEBwYXJhbSB7SlNaaXB9IHppcCBaSVAgcGFja2FnZVxuICogQHBhcmFtIHtvYmplY3R9IG9iaiBPYmplY3QgdG8gYWRkIChyZWN1cnNpdmUpXG4gKi9cbmZ1bmN0aW9uIF9hZGRUb1ppcCggemlwLCBvYmogKSB7XG5cdGlmICggX2llRXhjZWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHQvLyBEZXRlY3QgaWYgd2UgYXJlIGRlYWxpbmcgd2l0aCBJRSdzIF9hd2Z1bF8gc2VyaWFsaXNlciBieSBzZWVpbmcgaWYgaXRcblx0XHQvLyBkcm9wIGF0dHJpYnV0ZXNcblx0XHRfaWVFeGNlbCA9IF9zZXJpYWxpc2VyXG5cdFx0XHQuc2VyaWFsaXplVG9TdHJpbmcoXG5cdFx0XHRcdCggbmV3IHdpbmRvdy5ET01QYXJzZXIoKSApLnBhcnNlRnJvbVN0cmluZyggZXhjZWxTdHJpbmdzWyd4bC93b3Jrc2hlZXRzL3NoZWV0MS54bWwnXSwgJ3RleHQveG1sJyApXG5cdFx0XHQpXG5cdFx0XHQuaW5kZXhPZiggJ3htbG5zOnInICkgPT09IC0xO1xuXHR9XG5cblx0JC5lYWNoKCBvYmosIGZ1bmN0aW9uICggbmFtZSwgdmFsICkge1xuXHRcdGlmICggJC5pc1BsYWluT2JqZWN0KCB2YWwgKSApIHtcblx0XHRcdHZhciBuZXdEaXIgPSB6aXAuZm9sZGVyKCBuYW1lICk7XG5cdFx0XHRfYWRkVG9aaXAoIG5ld0RpciwgdmFsICk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0aWYgKCBfaWVFeGNlbCApIHtcblx0XHRcdFx0Ly8gSUUncyBYTUwgc2VyaWFsaXNlciB3aWxsIGRyb3Agc29tZSBuYW1lIHNwYWNlIGF0dHJpYnV0ZXMgZnJvbVxuXHRcdFx0XHQvLyBmcm9tIHRoZSByb290IG5vZGUsIHNvIHdlIG5lZWQgdG8gc2F2ZSB0aGVtLiBEbyB0aGlzIGJ5XG5cdFx0XHRcdC8vIHJlcGxhY2luZyB0aGUgbmFtZXNwYWNlIG5vZGVzIHdpdGggYSByZWd1bGFyIGF0dHJpYnV0ZSB0aGF0XG5cdFx0XHRcdC8vIHdlIGNvbnZlcnQgYmFjayB3aGVuIHNlcmlhbGlzZWQuIEVkZ2UgZG9lcyBub3QgaGF2ZSB0aGlzXG5cdFx0XHRcdC8vIGlzc3VlXG5cdFx0XHRcdHZhciB3b3Jrc2hlZXQgPSB2YWwuY2hpbGROb2Rlc1swXTtcblx0XHRcdFx0dmFyIGksIGllbjtcblx0XHRcdFx0dmFyIGF0dHJzID0gW107XG5cblx0XHRcdFx0Zm9yICggaT13b3Jrc2hlZXQuYXR0cmlidXRlcy5sZW5ndGgtMSA7IGk+PTAgOyBpLS0gKSB7XG5cdFx0XHRcdFx0dmFyIGF0dHJOYW1lID0gd29ya3NoZWV0LmF0dHJpYnV0ZXNbaV0ubm9kZU5hbWU7XG5cdFx0XHRcdFx0dmFyIGF0dHJWYWx1ZSA9IHdvcmtzaGVldC5hdHRyaWJ1dGVzW2ldLm5vZGVWYWx1ZTtcblxuXHRcdFx0XHRcdGlmICggYXR0ck5hbWUuaW5kZXhPZiggJzonICkgIT09IC0xICkge1xuXHRcdFx0XHRcdFx0YXR0cnMucHVzaCggeyBuYW1lOiBhdHRyTmFtZSwgdmFsdWU6IGF0dHJWYWx1ZSB9ICk7XG5cblx0XHRcdFx0XHRcdHdvcmtzaGVldC5yZW1vdmVBdHRyaWJ1dGUoIGF0dHJOYW1lICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Zm9yICggaT0wLCBpZW49YXR0cnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0dmFyIGF0dHIgPSB2YWwuY3JlYXRlQXR0cmlidXRlKCBhdHRyc1tpXS5uYW1lLnJlcGxhY2UoICc6JywgJ19kdF9iX25hbWVzcGFjZV90b2tlbl8nICkgKTtcblx0XHRcdFx0XHRhdHRyLnZhbHVlID0gYXR0cnNbaV0udmFsdWU7XG5cdFx0XHRcdFx0d29ya3NoZWV0LnNldEF0dHJpYnV0ZU5vZGUoIGF0dHIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc3RyID0gX3NlcmlhbGlzZXIuc2VyaWFsaXplVG9TdHJpbmcodmFsKTtcblxuXHRcdFx0Ly8gRml4IElFJ3MgWE1MXG5cdFx0XHRpZiAoIF9pZUV4Y2VsICkge1xuXHRcdFx0XHQvLyBJRSBkb2Vzbid0IGluY2x1ZGUgdGhlIFhNTCBkZWNsYXJhdGlvblxuXHRcdFx0XHRpZiAoIHN0ci5pbmRleE9mKCAnPD94bWwnICkgPT09IC0xICkge1xuXHRcdFx0XHRcdHN0ciA9ICc8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiIHN0YW5kYWxvbmU9XCJ5ZXNcIj8+JytzdHI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZXR1cm4gbmFtZXNwYWNlIGF0dHJpYnV0ZXMgdG8gYmVpbmcgYXMgc3VjaFxuXHRcdFx0XHRzdHIgPSBzdHIucmVwbGFjZSggL19kdF9iX25hbWVzcGFjZV90b2tlbl8vZywgJzonICk7XG5cblx0XHRcdFx0Ly8gUmVtb3ZlIHRlc3RpbmcgbmFtZSBzcGFjZSB0aGF0IElFIHB1dHMgaW50byB0aGUgc3BhY2UgcHJlc2VydmUgYXR0clxuXHRcdFx0XHRzdHIgPSBzdHIucmVwbGFjZSggL3htbG5zOk5TW1xcZF0rPVwiXCIgTlNbXFxkXSs6L2csICcnICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNhZmFyaSwgSUUgYW5kIEVkZ2Ugd2lsbCBwdXQgZW1wdHkgbmFtZSBzcGFjZSBhdHRyaWJ1dGVzIG9udG9cblx0XHRcdC8vIHZhcmlvdXMgZWxlbWVudHMgbWFraW5nIHRoZW0gdXNlbGVzcy4gVGhpcyBzdHJpcHMgdGhlbSBvdXRcblx0XHRcdHN0ciA9IHN0ci5yZXBsYWNlKCAvPChbXjw+XSo/KSB4bWxucz1cIlwiKFtePD5dKj8pPi9nLCAnPCQxICQyPicgKTtcblxuXHRcdFx0emlwLmZpbGUoIG5hbWUsIHN0ciApO1xuXHRcdH1cblx0fSApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhbiBYTUwgbm9kZSBhbmQgYWRkIGFueSBjaGlsZHJlbiwgYXR0cmlidXRlcywgZXRjIHdpdGhvdXQgbmVlZGluZyB0b1xuICogYmUgdmVyYm9zZSBpbiB0aGUgRE9NLlxuICpcbiAqIEBwYXJhbSAge29iamVjdH0gZG9jICAgICAgWE1MIGRvY3VtZW50XG4gKiBAcGFyYW0gIHtzdHJpbmd9IG5vZGVOYW1lIE5vZGUgbmFtZVxuICogQHBhcmFtICB7b2JqZWN0fSBvcHRzICAgICBPcHRpb25zIC0gY2FuIGJlIGBhdHRyYCAoYXR0cmlidXRlcyksIGBjaGlsZHJlbmBcbiAqICAgKGNoaWxkIG5vZGVzKSBhbmQgYHRleHRgICh0ZXh0IGNvbnRlbnQpXG4gKiBAcmV0dXJuIHtub2RlfSAgICAgICAgICAgIENyZWF0ZWQgbm9kZVxuICovXG5mdW5jdGlvbiBfY3JlYXRlTm9kZSggZG9jLCBub2RlTmFtZSwgb3B0cyApIHtcblx0dmFyIHRlbXBOb2RlID0gZG9jLmNyZWF0ZUVsZW1lbnQoIG5vZGVOYW1lICk7XG5cblx0aWYgKCBvcHRzICkge1xuXHRcdGlmICggb3B0cy5hdHRyICkge1xuXHRcdFx0JCh0ZW1wTm9kZSkuYXR0ciggb3B0cy5hdHRyICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHRzLmNoaWxkcmVuICkge1xuXHRcdFx0JC5lYWNoKCBvcHRzLmNoaWxkcmVuLCBmdW5jdGlvbiAoIGtleSwgdmFsdWUgKSB7XG5cdFx0XHRcdHRlbXBOb2RlLmFwcGVuZENoaWxkKCB2YWx1ZSApO1xuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0cy50ZXh0ICE9PSBudWxsICYmIG9wdHMudGV4dCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dGVtcE5vZGUuYXBwZW5kQ2hpbGQoIGRvYy5jcmVhdGVUZXh0Tm9kZSggb3B0cy50ZXh0ICkgKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdGVtcE5vZGU7XG59XG5cbi8qKlxuICogR2V0IHRoZSB3aWR0aCBmb3IgYW4gRXhjZWwgY29sdW1uIGJhc2VkIG9uIHRoZSBjb250ZW50cyBvZiB0aGF0IGNvbHVtblxuICogQHBhcmFtICB7b2JqZWN0fSBkYXRhIERhdGEgZm9yIGV4cG9ydFxuICogQHBhcmFtICB7aW50fSAgICBjb2wgIENvbHVtbiBpbmRleFxuICogQHJldHVybiB7aW50fSAgICAgICAgIENvbHVtbiB3aWR0aFxuICovXG5mdW5jdGlvbiBfZXhjZWxDb2xXaWR0aCggZGF0YSwgY29sICkge1xuXHR2YXIgbWF4ID0gZGF0YS5oZWFkZXJbY29sXS5sZW5ndGg7XG5cdHZhciBsZW4sIGxpbmVTcGxpdCwgc3RyO1xuXG5cdGlmICggZGF0YS5mb290ZXIgJiYgZGF0YS5mb290ZXJbY29sXS5sZW5ndGggPiBtYXggKSB7XG5cdFx0bWF4ID0gZGF0YS5mb290ZXJbY29sXS5sZW5ndGg7XG5cdH1cblxuXHRmb3IgKCB2YXIgaT0wLCBpZW49ZGF0YS5ib2R5Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdHZhciBwb2ludCA9IGRhdGEuYm9keVtpXVtjb2xdO1xuXHRcdHN0ciA9IHBvaW50ICE9PSBudWxsICYmIHBvaW50ICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0cG9pbnQudG9TdHJpbmcoKSA6XG5cdFx0XHQnJztcblxuXHRcdC8vIElmIHRoZXJlIGlzIGEgbmV3bGluZSBjaGFyYWN0ZXIsIHdvcmtvdXQgdGhlIHdpZHRoIG9mIHRoZSBjb2x1bW5cblx0XHQvLyBiYXNlZCBvbiB0aGUgbG9uZ2VzdCBsaW5lIGluIHRoZSBzdHJpbmdcblx0XHRpZiAoIHN0ci5pbmRleE9mKCdcXG4nKSAhPT0gLTEgKSB7XG5cdFx0XHRsaW5lU3BsaXQgPSBzdHIuc3BsaXQoJ1xcbicpO1xuXHRcdFx0bGluZVNwbGl0LnNvcnQoIGZ1bmN0aW9uIChhLCBiKSB7XG5cdFx0XHRcdHJldHVybiBiLmxlbmd0aCAtIGEubGVuZ3RoO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRsZW4gPSBsaW5lU3BsaXRbMF0ubGVuZ3RoO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGxlbiA9IHN0ci5sZW5ndGg7XG5cdFx0fVxuXG5cdFx0aWYgKCBsZW4gPiBtYXggKSB7XG5cdFx0XHRtYXggPSBsZW47XG5cdFx0fVxuXG5cdFx0Ly8gTWF4IHdpZHRoIHJhdGhlciB0aGFuIGhhdmluZyBwb3RlbnRpYWxseSBtYXNzaXZlIGNvbHVtbiB3aWR0aHNcblx0XHRpZiAoIG1heCA+IDQwICkge1xuXHRcdFx0cmV0dXJuIDU0OyAvLyA0MCAqIDEuMzVcblx0XHR9XG5cdH1cblxuXHRtYXggKj0gMS4zNTtcblxuXHQvLyBBbmQgYSBtaW4gd2lkdGhcblx0cmV0dXJuIG1heCA+IDYgPyBtYXggOiA2O1xufVxuXG4vLyBFeGNlbCAtIFByZS1kZWZpbmVkIHN0cmluZ3MgdG8gYnVpbGQgYSBiYXNpYyBYTFNYIGZpbGVcbnZhciBleGNlbFN0cmluZ3MgPSB7XG5cdFwiX3JlbHMvLnJlbHNcIjpcblx0XHQnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIiBzdGFuZGFsb25lPVwieWVzXCI/PicrXG5cdFx0JzxSZWxhdGlvbnNoaXBzIHhtbG5zPVwiaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3BhY2thZ2UvMjAwNi9yZWxhdGlvbnNoaXBzXCI+Jytcblx0XHRcdCc8UmVsYXRpb25zaGlwIElkPVwicklkMVwiIFR5cGU9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzL29mZmljZURvY3VtZW50XCIgVGFyZ2V0PVwieGwvd29ya2Jvb2sueG1sXCIvPicrXG5cdFx0JzwvUmVsYXRpb25zaGlwcz4nLFxuXG5cdFwieGwvX3JlbHMvd29ya2Jvb2sueG1sLnJlbHNcIjpcblx0XHQnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIiBzdGFuZGFsb25lPVwieWVzXCI/PicrXG5cdFx0JzxSZWxhdGlvbnNoaXBzIHhtbG5zPVwiaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3BhY2thZ2UvMjAwNi9yZWxhdGlvbnNoaXBzXCI+Jytcblx0XHRcdCc8UmVsYXRpb25zaGlwIElkPVwicklkMVwiIFR5cGU9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzL3dvcmtzaGVldFwiIFRhcmdldD1cIndvcmtzaGVldHMvc2hlZXQxLnhtbFwiLz4nK1xuXHRcdFx0JzxSZWxhdGlvbnNoaXAgSWQ9XCJySWQyXCIgVHlwZT1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L3JlbGF0aW9uc2hpcHMvc3R5bGVzXCIgVGFyZ2V0PVwic3R5bGVzLnhtbFwiLz4nK1xuXHRcdCc8L1JlbGF0aW9uc2hpcHM+JyxcblxuXHRcIltDb250ZW50X1R5cGVzXS54bWxcIjpcblx0XHQnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIiBzdGFuZGFsb25lPVwieWVzXCI/PicrXG5cdFx0JzxUeXBlcyB4bWxucz1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9wYWNrYWdlLzIwMDYvY29udGVudC10eXBlc1wiPicrXG5cdFx0XHQnPERlZmF1bHQgRXh0ZW5zaW9uPVwieG1sXCIgQ29udGVudFR5cGU9XCJhcHBsaWNhdGlvbi94bWxcIiAvPicrXG5cdFx0XHQnPERlZmF1bHQgRXh0ZW5zaW9uPVwicmVsc1wiIENvbnRlbnRUeXBlPVwiYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLXBhY2thZ2UucmVsYXRpb25zaGlwcyt4bWxcIiAvPicrXG5cdFx0XHQnPERlZmF1bHQgRXh0ZW5zaW9uPVwianBlZ1wiIENvbnRlbnRUeXBlPVwiaW1hZ2UvanBlZ1wiIC8+Jytcblx0XHRcdCc8T3ZlcnJpZGUgUGFydE5hbWU9XCIveGwvd29ya2Jvb2sueG1sXCIgQ29udGVudFR5cGU9XCJhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldC5tYWluK3htbFwiIC8+Jytcblx0XHRcdCc8T3ZlcnJpZGUgUGFydE5hbWU9XCIveGwvd29ya3NoZWV0cy9zaGVldDEueG1sXCIgQ29udGVudFR5cGU9XCJhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC53b3Jrc2hlZXQreG1sXCIgLz4nK1xuXHRcdFx0JzxPdmVycmlkZSBQYXJ0TmFtZT1cIi94bC9zdHlsZXMueG1sXCIgQ29udGVudFR5cGU9XCJhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zdHlsZXMreG1sXCIgLz4nK1xuXHRcdCc8L1R5cGVzPicsXG5cblx0XCJ4bC93b3JrYm9vay54bWxcIjpcblx0XHQnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIiBzdGFuZGFsb25lPVwieWVzXCI/PicrXG5cdFx0Jzx3b3JrYm9vayB4bWxucz1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9zcHJlYWRzaGVldG1sLzIwMDYvbWFpblwiIHhtbG5zOnI9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzXCI+Jytcblx0XHRcdCc8ZmlsZVZlcnNpb24gYXBwTmFtZT1cInhsXCIgbGFzdEVkaXRlZD1cIjVcIiBsb3dlc3RFZGl0ZWQ9XCI1XCIgcnVwQnVpbGQ9XCIyNDgxNlwiLz4nK1xuXHRcdFx0Jzx3b3JrYm9va1ByIHNob3dJbmtBbm5vdGF0aW9uPVwiMFwiIGF1dG9Db21wcmVzc1BpY3R1cmVzPVwiMFwiLz4nK1xuXHRcdFx0Jzxib29rVmlld3M+Jytcblx0XHRcdFx0Jzx3b3JrYm9va1ZpZXcgeFdpbmRvdz1cIjBcIiB5V2luZG93PVwiMFwiIHdpbmRvd1dpZHRoPVwiMjU2MDBcIiB3aW5kb3dIZWlnaHQ9XCIxOTAyMFwiIHRhYlJhdGlvPVwiNTAwXCIvPicrXG5cdFx0XHQnPC9ib29rVmlld3M+Jytcblx0XHRcdCc8c2hlZXRzPicrXG5cdFx0XHRcdCc8c2hlZXQgbmFtZT1cIlNoZWV0MVwiIHNoZWV0SWQ9XCIxXCIgcjppZD1cInJJZDFcIi8+Jytcblx0XHRcdCc8L3NoZWV0cz4nK1xuXHRcdFx0JzxkZWZpbmVkTmFtZXMvPicrXG5cdFx0Jzwvd29ya2Jvb2s+JyxcblxuXHRcInhsL3dvcmtzaGVldHMvc2hlZXQxLnhtbFwiOlxuXHRcdCc8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiIHN0YW5kYWxvbmU9XCJ5ZXNcIj8+Jytcblx0XHQnPHdvcmtzaGVldCB4bWxucz1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9zcHJlYWRzaGVldG1sLzIwMDYvbWFpblwiIHhtbG5zOnI9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzXCIgeG1sbnM6bWM9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvbWFya3VwLWNvbXBhdGliaWxpdHkvMjAwNlwiIG1jOklnbm9yYWJsZT1cIngxNGFjXCIgeG1sbnM6eDE0YWM9XCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMDkvOS9hY1wiPicrXG5cdFx0XHQnPHNoZWV0RGF0YS8+Jytcblx0XHRcdCc8bWVyZ2VDZWxscyBjb3VudD1cIjBcIi8+Jytcblx0XHQnPC93b3Jrc2hlZXQ+JyxcblxuXHRcInhsL3N0eWxlcy54bWxcIjpcblx0XHQnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIj8+Jytcblx0XHQnPHN0eWxlU2hlZXQgeG1sbnM9XCJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvc3ByZWFkc2hlZXRtbC8yMDA2L21haW5cIiB4bWxuczptYz1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9tYXJrdXAtY29tcGF0aWJpbGl0eS8yMDA2XCIgbWM6SWdub3JhYmxlPVwieDE0YWNcIiB4bWxuczp4MTRhYz1cImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAwOS85L2FjXCI+Jytcblx0XHRcdCc8bnVtRm10cyBjb3VudD1cIjZcIj4nK1xuXHRcdFx0XHQnPG51bUZtdCBudW1GbXRJZD1cIjE2NFwiIGZvcm1hdENvZGU9XCIjLCMjMC4wMF8tXFwgWyQkLTQ1Q11cIi8+Jytcblx0XHRcdFx0JzxudW1GbXQgbnVtRm10SWQ9XCIxNjVcIiBmb3JtYXRDb2RlPVwiJnF1b3Q7wqMmcXVvdDsjLCMjMC4wMFwiLz4nK1xuXHRcdFx0XHQnPG51bUZtdCBudW1GbXRJZD1cIjE2NlwiIGZvcm1hdENvZGU9XCJbJOKCrC0yXVxcICMsIyMwLjAwXCIvPicrXG5cdFx0XHRcdCc8bnVtRm10IG51bUZtdElkPVwiMTY3XCIgZm9ybWF0Q29kZT1cIjAuMCVcIi8+Jytcblx0XHRcdFx0JzxudW1GbXQgbnVtRm10SWQ9XCIxNjhcIiBmb3JtYXRDb2RlPVwiIywjIzA7KCMsIyMwKVwiLz4nK1xuXHRcdFx0XHQnPG51bUZtdCBudW1GbXRJZD1cIjE2OVwiIGZvcm1hdENvZGU9XCIjLCMjMC4wMDsoIywjIzAuMDApXCIvPicrXG5cdFx0XHQnPC9udW1GbXRzPicrXG5cdFx0XHQnPGZvbnRzIGNvdW50PVwiNVwiIHgxNGFjOmtub3duRm9udHM9XCIxXCI+Jytcblx0XHRcdFx0Jzxmb250PicrXG5cdFx0XHRcdFx0JzxzeiB2YWw9XCIxMVwiIC8+Jytcblx0XHRcdFx0XHQnPG5hbWUgdmFsPVwiQ2FsaWJyaVwiIC8+Jytcblx0XHRcdFx0JzwvZm9udD4nK1xuXHRcdFx0XHQnPGZvbnQ+Jytcblx0XHRcdFx0XHQnPHN6IHZhbD1cIjExXCIgLz4nK1xuXHRcdFx0XHRcdCc8bmFtZSB2YWw9XCJDYWxpYnJpXCIgLz4nK1xuXHRcdFx0XHRcdCc8Y29sb3IgcmdiPVwiRkZGRkZGRkZcIiAvPicrXG5cdFx0XHRcdCc8L2ZvbnQ+Jytcblx0XHRcdFx0Jzxmb250PicrXG5cdFx0XHRcdFx0JzxzeiB2YWw9XCIxMVwiIC8+Jytcblx0XHRcdFx0XHQnPG5hbWUgdmFsPVwiQ2FsaWJyaVwiIC8+Jytcblx0XHRcdFx0XHQnPGIgLz4nK1xuXHRcdFx0XHQnPC9mb250PicrXG5cdFx0XHRcdCc8Zm9udD4nK1xuXHRcdFx0XHRcdCc8c3ogdmFsPVwiMTFcIiAvPicrXG5cdFx0XHRcdFx0JzxuYW1lIHZhbD1cIkNhbGlicmlcIiAvPicrXG5cdFx0XHRcdFx0JzxpIC8+Jytcblx0XHRcdFx0JzwvZm9udD4nK1xuXHRcdFx0XHQnPGZvbnQ+Jytcblx0XHRcdFx0XHQnPHN6IHZhbD1cIjExXCIgLz4nK1xuXHRcdFx0XHRcdCc8bmFtZSB2YWw9XCJDYWxpYnJpXCIgLz4nK1xuXHRcdFx0XHRcdCc8dSAvPicrXG5cdFx0XHRcdCc8L2ZvbnQ+Jytcblx0XHRcdCc8L2ZvbnRzPicrXG5cdFx0XHQnPGZpbGxzIGNvdW50PVwiNlwiPicrXG5cdFx0XHRcdCc8ZmlsbD4nK1xuXHRcdFx0XHRcdCc8cGF0dGVybkZpbGwgcGF0dGVyblR5cGU9XCJub25lXCIgLz4nK1xuXHRcdFx0XHQnPC9maWxsPicrXG5cdFx0XHRcdCc8ZmlsbD4nKyAvLyBFeGNlbCBhcHBlYXJzIHRvIHVzZSB0aGlzIGFzIGEgZG90dGVkIGJhY2tncm91bmQgcmVnYXJkbGVzcyBvZiB2YWx1ZXMgYnV0XG5cdFx0XHRcdFx0JzxwYXR0ZXJuRmlsbCBwYXR0ZXJuVHlwZT1cIm5vbmVcIiAvPicrIC8vIHRvIGJlIHZhbGlkIHRvIHRoZSBzY2hlbWEsIHVzZSBhIHBhdHRlcm5GaWxsXG5cdFx0XHRcdCc8L2ZpbGw+Jytcblx0XHRcdFx0JzxmaWxsPicrXG5cdFx0XHRcdFx0JzxwYXR0ZXJuRmlsbCBwYXR0ZXJuVHlwZT1cInNvbGlkXCI+Jytcblx0XHRcdFx0XHRcdCc8ZmdDb2xvciByZ2I9XCJGRkQ5RDlEOVwiIC8+Jytcblx0XHRcdFx0XHRcdCc8YmdDb2xvciBpbmRleGVkPVwiNjRcIiAvPicrXG5cdFx0XHRcdFx0JzwvcGF0dGVybkZpbGw+Jytcblx0XHRcdFx0JzwvZmlsbD4nK1xuXHRcdFx0XHQnPGZpbGw+Jytcblx0XHRcdFx0XHQnPHBhdHRlcm5GaWxsIHBhdHRlcm5UeXBlPVwic29saWRcIj4nK1xuXHRcdFx0XHRcdFx0JzxmZ0NvbG9yIHJnYj1cIkZGRDk5Nzk1XCIgLz4nK1xuXHRcdFx0XHRcdFx0JzxiZ0NvbG9yIGluZGV4ZWQ9XCI2NFwiIC8+Jytcblx0XHRcdFx0XHQnPC9wYXR0ZXJuRmlsbD4nK1xuXHRcdFx0XHQnPC9maWxsPicrXG5cdFx0XHRcdCc8ZmlsbD4nK1xuXHRcdFx0XHRcdCc8cGF0dGVybkZpbGwgcGF0dGVyblR5cGU9XCJzb2xpZFwiPicrXG5cdFx0XHRcdFx0XHQnPGZnQ29sb3IgcmdiPVwiZmZjNmVmY2VcIiAvPicrXG5cdFx0XHRcdFx0XHQnPGJnQ29sb3IgaW5kZXhlZD1cIjY0XCIgLz4nK1xuXHRcdFx0XHRcdCc8L3BhdHRlcm5GaWxsPicrXG5cdFx0XHRcdCc8L2ZpbGw+Jytcblx0XHRcdFx0JzxmaWxsPicrXG5cdFx0XHRcdFx0JzxwYXR0ZXJuRmlsbCBwYXR0ZXJuVHlwZT1cInNvbGlkXCI+Jytcblx0XHRcdFx0XHRcdCc8ZmdDb2xvciByZ2I9XCJmZmM2Y2ZlZlwiIC8+Jytcblx0XHRcdFx0XHRcdCc8YmdDb2xvciBpbmRleGVkPVwiNjRcIiAvPicrXG5cdFx0XHRcdFx0JzwvcGF0dGVybkZpbGw+Jytcblx0XHRcdFx0JzwvZmlsbD4nK1xuXHRcdFx0JzwvZmlsbHM+Jytcblx0XHRcdCc8Ym9yZGVycyBjb3VudD1cIjJcIj4nK1xuXHRcdFx0XHQnPGJvcmRlcj4nK1xuXHRcdFx0XHRcdCc8bGVmdCAvPicrXG5cdFx0XHRcdFx0JzxyaWdodCAvPicrXG5cdFx0XHRcdFx0Jzx0b3AgLz4nK1xuXHRcdFx0XHRcdCc8Ym90dG9tIC8+Jytcblx0XHRcdFx0XHQnPGRpYWdvbmFsIC8+Jytcblx0XHRcdFx0JzwvYm9yZGVyPicrXG5cdFx0XHRcdCc8Ym9yZGVyIGRpYWdvbmFsVXA9XCJmYWxzZVwiIGRpYWdvbmFsRG93bj1cImZhbHNlXCI+Jytcblx0XHRcdFx0XHQnPGxlZnQgc3R5bGU9XCJ0aGluXCI+Jytcblx0XHRcdFx0XHRcdCc8Y29sb3IgYXV0bz1cIjFcIiAvPicrXG5cdFx0XHRcdFx0JzwvbGVmdD4nK1xuXHRcdFx0XHRcdCc8cmlnaHQgc3R5bGU9XCJ0aGluXCI+Jytcblx0XHRcdFx0XHRcdCc8Y29sb3IgYXV0bz1cIjFcIiAvPicrXG5cdFx0XHRcdFx0JzwvcmlnaHQ+Jytcblx0XHRcdFx0XHQnPHRvcCBzdHlsZT1cInRoaW5cIj4nK1xuXHRcdFx0XHRcdFx0Jzxjb2xvciBhdXRvPVwiMVwiIC8+Jytcblx0XHRcdFx0XHQnPC90b3A+Jytcblx0XHRcdFx0XHQnPGJvdHRvbSBzdHlsZT1cInRoaW5cIj4nK1xuXHRcdFx0XHRcdFx0Jzxjb2xvciBhdXRvPVwiMVwiIC8+Jytcblx0XHRcdFx0XHQnPC9ib3R0b20+Jytcblx0XHRcdFx0XHQnPGRpYWdvbmFsIC8+Jytcblx0XHRcdFx0JzwvYm9yZGVyPicrXG5cdFx0XHQnPC9ib3JkZXJzPicrXG5cdFx0XHQnPGNlbGxTdHlsZVhmcyBjb3VudD1cIjFcIj4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgLz4nK1xuXHRcdFx0JzwvY2VsbFN0eWxlWGZzPicrXG5cdFx0XHQnPGNlbGxYZnMgY291bnQ9XCI2OFwiPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjFcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIyXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiM1wiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjRcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMlwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMVwiIGZpbGxJZD1cIjJcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjJcIiBmaWxsSWQ9XCIyXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIzXCIgZmlsbElkPVwiMlwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiNFwiIGZpbGxJZD1cIjJcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIzXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIxXCIgZmlsbElkPVwiM1wiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMlwiIGZpbGxJZD1cIjNcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjNcIiBmaWxsSWQ9XCIzXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCI0XCIgZmlsbElkPVwiM1wiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjRcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjFcIiBmaWxsSWQ9XCI0XCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIyXCIgZmlsbElkPVwiNFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiM1wiIGZpbGxJZD1cIjRcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjRcIiBmaWxsSWQ9XCI0XCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiNVwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMVwiIGZpbGxJZD1cIjVcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjJcIiBmaWxsSWQ9XCI1XCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIzXCIgZmlsbElkPVwiNVwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiNFwiIGZpbGxJZD1cIjVcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIxXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMlwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjNcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCI0XCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjJcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjFcIiBmaWxsSWQ9XCIyXCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIyXCIgZmlsbElkPVwiMlwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiM1wiIGZpbGxJZD1cIjJcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjRcIiBmaWxsSWQ9XCIyXCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiM1wiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMVwiIGZpbGxJZD1cIjNcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjJcIiBmaWxsSWQ9XCIzXCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIzXCIgZmlsbElkPVwiM1wiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiNFwiIGZpbGxJZD1cIjNcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCI0XCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIxXCIgZmlsbElkPVwiNFwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMlwiIGZpbGxJZD1cIjRcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjNcIiBmaWxsSWQ9XCI0XCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCI0XCIgZmlsbElkPVwiNFwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjVcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjFcIiBmaWxsSWQ9XCI1XCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIyXCIgZmlsbElkPVwiNVwiIGJvcmRlcklkPVwiMVwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiM1wiIGZpbGxJZD1cIjVcIiBib3JkZXJJZD1cIjFcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjRcIiBmaWxsSWQ9XCI1XCIgYm9yZGVySWQ9XCIxXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseUFsaWdubWVudD1cIjFcIj4nK1xuXHRcdFx0XHRcdCc8YWxpZ25tZW50IGhvcml6b250YWw9XCJsZWZ0XCIvPicrXG5cdFx0XHRcdCc8L3hmPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlBbGlnbm1lbnQ9XCIxXCI+Jytcblx0XHRcdFx0XHQnPGFsaWdubWVudCBob3Jpem9udGFsPVwiY2VudGVyXCIvPicrXG5cdFx0XHRcdCc8L3hmPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlBbGlnbm1lbnQ9XCIxXCI+Jytcblx0XHRcdFx0XHQnPGFsaWdubWVudCBob3Jpem9udGFsPVwicmlnaHRcIi8+Jytcblx0XHRcdFx0JzwveGY+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjBcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseUFsaWdubWVudD1cIjFcIj4nK1xuXHRcdFx0XHRcdCc8YWxpZ25tZW50IGhvcml6b250YWw9XCJmaWxsXCIvPicrXG5cdFx0XHRcdCc8L3hmPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlBbGlnbm1lbnQ9XCIxXCI+Jytcblx0XHRcdFx0XHQnPGFsaWdubWVudCB0ZXh0Um90YXRpb249XCI5MFwiLz4nK1xuXHRcdFx0XHQnPC94Zj4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIiB4ZklkPVwiMFwiIGFwcGx5QWxpZ25tZW50PVwiMVwiPicrXG5cdFx0XHRcdFx0JzxhbGlnbm1lbnQgd3JhcFRleHQ9XCIxXCIvPicrXG5cdFx0XHRcdCc8L3hmPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCI5XCIgICBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjE2NFwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIiB4ZklkPVwiMFwiIGFwcGx5TnVtYmVyRm9ybWF0PVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMTY1XCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlOdW1iZXJGb3JtYXQ9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIxNjZcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjE2N1wiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgYXBwbHlGb250PVwiMVwiIGFwcGx5RmlsbD1cIjFcIiBhcHBseUJvcmRlcj1cIjFcIiB4ZklkPVwiMFwiIGFwcGx5TnVtYmVyRm9ybWF0PVwiMVwiLz4nK1xuXHRcdFx0XHQnPHhmIG51bUZtdElkPVwiMTY4XCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlOdW1iZXJGb3JtYXQ9XCIxXCIvPicrXG5cdFx0XHRcdCc8eGYgbnVtRm10SWQ9XCIxNjlcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjNcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjRcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjFcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjJcIiBmb250SWQ9XCIwXCIgZmlsbElkPVwiMFwiIGJvcmRlcklkPVwiMFwiIGFwcGx5Rm9udD1cIjFcIiBhcHBseUZpbGw9XCIxXCIgYXBwbHlCb3JkZXI9XCIxXCIgeGZJZD1cIjBcIiBhcHBseU51bWJlckZvcm1hdD1cIjFcIi8+Jytcblx0XHRcdFx0Jzx4ZiBudW1GbXRJZD1cIjE0XCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIiBhcHBseUZvbnQ9XCIxXCIgYXBwbHlGaWxsPVwiMVwiIGFwcGx5Qm9yZGVyPVwiMVwiIHhmSWQ9XCIwXCIgYXBwbHlOdW1iZXJGb3JtYXQ9XCIxXCIvPicrXG5cdFx0XHQnPC9jZWxsWGZzPicrXG5cdFx0XHQnPGNlbGxTdHlsZXMgY291bnQ9XCIxXCI+Jytcblx0XHRcdFx0JzxjZWxsU3R5bGUgbmFtZT1cIk5vcm1hbFwiIHhmSWQ9XCIwXCIgYnVpbHRpbklkPVwiMFwiIC8+Jytcblx0XHRcdCc8L2NlbGxTdHlsZXM+Jytcblx0XHRcdCc8ZHhmcyBjb3VudD1cIjBcIiAvPicrXG5cdFx0XHQnPHRhYmxlU3R5bGVzIGNvdW50PVwiMFwiIGRlZmF1bHRUYWJsZVN0eWxlPVwiVGFibGVTdHlsZU1lZGl1bTlcIiBkZWZhdWx0UGl2b3RTdHlsZT1cIlBpdm90U3R5bGVNZWRpdW00XCIgLz4nK1xuXHRcdCc8L3N0eWxlU2hlZXQ+J1xufTtcbi8vIE5vdGUgd2UgY291bGQgdXNlIDMgYGZvcmAgbG9vcHMgZm9yIHRoZSBzdHlsZXMsIGJ1dCB3aGVuIGd6aXBwZWQgdGhlcmUgaXNcbi8vIHZpcnR1YWxseSBubyBkaWZmZXJlbmNlIGluIHNpemUsIHNpbmNlIHRoZSBhYm92ZSBjYW4gYmUgZWFzaWx5IGNvbXByZXNzZWRcblxuLy8gUGF0dGVybiBtYXRjaGluZyBmb3Igc3BlY2lhbCBudW1iZXIgZm9ybWF0cy4gUGVyaGFwcyB0aGlzIHNob3VsZCBiZSBleHBvc2VkXG4vLyB2aWEgYW4gQVBJIGluIGZ1dHVyZT9cbi8vIFJlZjogc2VjdGlvbiAzLjguMzAgLSBidWlsdCBpbiBmb3JtYXR0ZXJzIGluIG9wZW4gc3ByZWFkc2hlZXRcbi8vICAgaHR0cHM6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9uZXdzL1RDNDVfY3VycmVudF93b3JrL09mZmljZSUyME9wZW4lMjBYTUwlMjBQYXJ0JTIwNCUyMC0lMjBNYXJrdXAlMjBMYW5ndWFnZSUyMFJlZmVyZW5jZS5wZGZcbnZhciBfZXhjZWxTcGVjaWFscyA9IFtcblx0eyBtYXRjaDogL15cXC0/XFxkK1xcLlxcZCUkLywgICAgICAgICAgICAgICBzdHlsZTogNjAsIGZtdDogZnVuY3Rpb24gKGQpIHsgcmV0dXJuIGQvMTAwOyB9IH0sIC8vIFBlcmNlbnQgd2l0aCBkLnAuXG5cdHsgbWF0Y2g6IC9eXFwtP1xcZCtcXC4/XFxkKiUkLywgICAgICAgICAgICAgc3R5bGU6IDU2LCBmbXQ6IGZ1bmN0aW9uIChkKSB7IHJldHVybiBkLzEwMDsgfSB9LCAvLyBQZXJjZW50XG5cdHsgbWF0Y2g6IC9eXFwtP1xcJFtcXGQsXSsuP1xcZCokLywgICAgICAgICAgc3R5bGU6IDU3IH0sIC8vIERvbGxhcnNcblx0eyBtYXRjaDogL15cXC0/wqNbXFxkLF0rLj9cXGQqJC8sICAgICAgICAgICBzdHlsZTogNTggfSwgLy8gUG91bmRzXG5cdHsgbWF0Y2g6IC9eXFwtP+KCrFtcXGQsXSsuP1xcZCokLywgICAgICAgICAgIHN0eWxlOiA1OSB9LCAvLyBFdXJvc1xuXHR7IG1hdGNoOiAvXlxcLT9cXGQrJC8sICAgICAgICAgICAgICAgICAgICBzdHlsZTogNjUgfSwgLy8gTnVtYmVycyB3aXRob3V0IHRob3VzYW5kIHNlcGFyYXRvcnNcblx0eyBtYXRjaDogL15cXC0/XFxkK1xcLlxcZHsyfSQvLCAgICAgICAgICAgICBzdHlsZTogNjYgfSwgLy8gTnVtYmVycyAyIGQucC4gd2l0aG91dCB0aG91c2FuZHMgc2VwYXJhdG9yc1xuXHR7IG1hdGNoOiAvXlxcKFtcXGQsXStcXCkkLywgICAgICAgICAgICAgICAgc3R5bGU6IDYxLCBmbXQ6IGZ1bmN0aW9uIChkKSB7IHJldHVybiAtMSAqIGQucmVwbGFjZSgvW1xcKFxcKV0vZywgJycpOyB9IH0sICAvLyBOZWdhdGl2ZSBudW1iZXJzIGluZGljYXRlZCBieSBicmFja2V0c1xuXHR7IG1hdGNoOiAvXlxcKFtcXGQsXStcXC5cXGR7Mn1cXCkkLywgICAgICAgICBzdHlsZTogNjIsIGZtdDogZnVuY3Rpb24gKGQpIHsgcmV0dXJuIC0xICogZC5yZXBsYWNlKC9bXFwoXFwpXS9nLCAnJyk7IH0gfSwgIC8vIE5lZ2F0aXZlIG51bWJlcnMgaW5kaWNhdGVkIGJ5IGJyYWNrZXRzIC0gMmQucC5cblx0eyBtYXRjaDogL15cXC0/W1xcZCxdKyQvLCAgICAgICAgICAgICAgICAgc3R5bGU6IDYzIH0sIC8vIE51bWJlcnMgd2l0aCB0aG91c2FuZCBzZXBhcmF0b3JzXG5cdHsgbWF0Y2g6IC9eXFwtP1tcXGQsXStcXC5cXGR7Mn0kLywgICAgICAgICAgc3R5bGU6IDY0IH0sXG5cdHsgbWF0Y2g6IC9eW1xcZF17NH1cXC1bMDFdW1xcZF1cXC1bMDEyM11bXFxkXSQvLCBzdHlsZTogNjcsIGZtdDogZnVuY3Rpb24gKGQpIHtyZXR1cm4gTWF0aC5yb3VuZCgyNTU2OSArIChEYXRlLnBhcnNlKGQpIC8gKDg2NDAwICogMTAwMCkpKTt9fSAvL0RhdGUgeXl5eS1tbS1kZFxuXTtcblxuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKlxuICogQnV0dG9uc1xuICovXG5cbi8vXG4vLyBDb3B5IHRvIGNsaXBib2FyZFxuLy9cbkRhdGFUYWJsZS5leHQuYnV0dG9ucy5jb3B5SHRtbDUgPSB7XG5cdGNsYXNzTmFtZTogJ2J1dHRvbnMtY29weSBidXR0b25zLWh0bWw1JyxcblxuXHR0ZXh0OiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5jb3B5JywgJ0NvcHknICk7XG5cdH0sXG5cblx0YWN0aW9uOiBmdW5jdGlvbiAoIGUsIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHR0aGlzLnByb2Nlc3NpbmcoIHRydWUgKTtcblxuXHRcdHZhciB0aGF0ID0gdGhpcztcblx0XHR2YXIgZXhwb3J0RGF0YSA9IF9leHBvcnREYXRhKCBkdCwgY29uZmlnICk7XG5cdFx0dmFyIGluZm8gPSBkdC5idXR0b25zLmV4cG9ydEluZm8oIGNvbmZpZyApO1xuXHRcdHZhciBuZXdsaW5lID0gX25ld0xpbmUoY29uZmlnKTtcblx0XHR2YXIgb3V0cHV0ID0gZXhwb3J0RGF0YS5zdHI7XG5cdFx0dmFyIGhpZGRlbkRpdiA9ICQoJzxkaXYvPicpXG5cdFx0XHQuY3NzKCB7XG5cdFx0XHRcdGhlaWdodDogMSxcblx0XHRcdFx0d2lkdGg6IDEsXG5cdFx0XHRcdG92ZXJmbG93OiAnaGlkZGVuJyxcblx0XHRcdFx0cG9zaXRpb246ICdmaXhlZCcsXG5cdFx0XHRcdHRvcDogMCxcblx0XHRcdFx0bGVmdDogMFxuXHRcdFx0fSApO1xuXG5cdFx0aWYgKCBpbmZvLnRpdGxlICkge1xuXHRcdFx0b3V0cHV0ID0gaW5mby50aXRsZSArIG5ld2xpbmUgKyBuZXdsaW5lICsgb3V0cHV0O1xuXHRcdH1cblxuXHRcdGlmICggaW5mby5tZXNzYWdlVG9wICkge1xuXHRcdFx0b3V0cHV0ID0gaW5mby5tZXNzYWdlVG9wICsgbmV3bGluZSArIG5ld2xpbmUgKyBvdXRwdXQ7XG5cdFx0fVxuXG5cdFx0aWYgKCBpbmZvLm1lc3NhZ2VCb3R0b20gKSB7XG5cdFx0XHRvdXRwdXQgPSBvdXRwdXQgKyBuZXdsaW5lICsgbmV3bGluZSArIGluZm8ubWVzc2FnZUJvdHRvbTtcblx0XHR9XG5cblx0XHRpZiAoIGNvbmZpZy5jdXN0b21pemUgKSB7XG5cdFx0XHRvdXRwdXQgPSBjb25maWcuY3VzdG9taXplKCBvdXRwdXQsIGNvbmZpZywgZHQgKTtcblx0XHR9XG5cblx0XHR2YXIgdGV4dGFyZWEgPSAkKCc8dGV4dGFyZWEgcmVhZG9ubHkvPicpXG5cdFx0XHQudmFsKCBvdXRwdXQgKVxuXHRcdFx0LmFwcGVuZFRvKCBoaWRkZW5EaXYgKTtcblxuXHRcdC8vIEZvciBicm93c2VycyB0aGF0IHN1cHBvcnQgdGhlIGNvcHkgZXhlY0NvbW1hbmQsIHRyeSB0byB1c2UgaXRcblx0XHRpZiAoIGRvY3VtZW50LnF1ZXJ5Q29tbWFuZFN1cHBvcnRlZCgnY29weScpICkge1xuXHRcdFx0aGlkZGVuRGl2LmFwcGVuZFRvKCBkdC50YWJsZSgpLmNvbnRhaW5lcigpICk7XG5cdFx0XHR0ZXh0YXJlYVswXS5mb2N1cygpO1xuXHRcdFx0dGV4dGFyZWFbMF0uc2VsZWN0KCk7XG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHZhciBzdWNjZXNzZnVsID0gZG9jdW1lbnQuZXhlY0NvbW1hbmQoICdjb3B5JyApO1xuXHRcdFx0XHRoaWRkZW5EaXYucmVtb3ZlKCk7XG5cblx0XHRcdFx0aWYgKHN1Y2Nlc3NmdWwpIHtcblx0XHRcdFx0XHRkdC5idXR0b25zLmluZm8oXG5cdFx0XHRcdFx0XHRkdC5pMThuKCAnYnV0dG9ucy5jb3B5VGl0bGUnLCAnQ29weSB0byBjbGlwYm9hcmQnICksXG5cdFx0XHRcdFx0XHRkdC5pMThuKCAnYnV0dG9ucy5jb3B5U3VjY2VzcycsIHtcblx0XHRcdFx0XHRcdFx0MTogJ0NvcGllZCBvbmUgcm93IHRvIGNsaXBib2FyZCcsXG5cdFx0XHRcdFx0XHRcdF86ICdDb3BpZWQgJWQgcm93cyB0byBjbGlwYm9hcmQnXG5cdFx0XHRcdFx0XHR9LCBleHBvcnREYXRhLnJvd3MgKSxcblx0XHRcdFx0XHRcdDIwMDBcblx0XHRcdFx0XHQpO1xuXG5cdFx0XHRcdFx0dGhpcy5wcm9jZXNzaW5nKCBmYWxzZSApO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Y2F0Y2ggKHQpIHt9XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXJ3aXNlIHdlIHNob3cgdGhlIHRleHQgYm94IGFuZCBpbnN0cnVjdCB0aGUgdXNlciB0byB1c2UgaXRcblx0XHR2YXIgbWVzc2FnZSA9ICQoJzxzcGFuPicrZHQuaTE4biggJ2J1dHRvbnMuY29weUtleXMnLFxuXHRcdFx0XHQnUHJlc3MgPGk+Y3RybDwvaT4gb3IgPGk+XFx1MjMxODwvaT4gKyA8aT5DPC9pPiB0byBjb3B5IHRoZSB0YWJsZSBkYXRhPGJyPnRvIHlvdXIgc3lzdGVtIGNsaXBib2FyZC48YnI+PGJyPicrXG5cdFx0XHRcdCdUbyBjYW5jZWwsIGNsaWNrIHRoaXMgbWVzc2FnZSBvciBwcmVzcyBlc2NhcGUuJyApKyc8L3NwYW4+J1xuXHRcdFx0KVxuXHRcdFx0LmFwcGVuZCggaGlkZGVuRGl2ICk7XG5cblx0XHRkdC5idXR0b25zLmluZm8oIGR0LmkxOG4oICdidXR0b25zLmNvcHlUaXRsZScsICdDb3B5IHRvIGNsaXBib2FyZCcgKSwgbWVzc2FnZSwgMCApO1xuXG5cdFx0Ly8gU2VsZWN0IHRoZSB0ZXh0IHNvIHdoZW4gdGhlIHVzZXIgYWN0aXZhdGVzIHRoZWlyIHN5c3RlbSBjbGlwYm9hcmRcblx0XHQvLyBpdCB3aWxsIGNvcHkgdGhhdCB0ZXh0XG5cdFx0dGV4dGFyZWFbMF0uZm9jdXMoKTtcblx0XHR0ZXh0YXJlYVswXS5zZWxlY3QoKTtcblxuXHRcdC8vIEV2ZW50IHRvIGhpZGUgdGhlIG1lc3NhZ2Ugd2hlbiB0aGUgdXNlciBpcyBkb25lXG5cdFx0dmFyIGNvbnRhaW5lciA9ICQobWVzc2FnZSkuY2xvc2VzdCgnLmR0LWJ1dHRvbi1pbmZvJyk7XG5cdFx0dmFyIGNsb3NlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29udGFpbmVyLm9mZiggJ2NsaWNrLmJ1dHRvbnMtY29weScgKTtcblx0XHRcdCQoZG9jdW1lbnQpLm9mZiggJy5idXR0b25zLWNvcHknICk7XG5cdFx0XHRkdC5idXR0b25zLmluZm8oIGZhbHNlICk7XG5cdFx0fTtcblxuXHRcdGNvbnRhaW5lci5vbiggJ2NsaWNrLmJ1dHRvbnMtY29weScsIGNsb3NlICk7XG5cdFx0JChkb2N1bWVudClcblx0XHRcdC5vbiggJ2tleWRvd24uYnV0dG9ucy1jb3B5JywgZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0aWYgKCBlLmtleUNvZGUgPT09IDI3ICkgeyAvLyBlc2Ncblx0XHRcdFx0XHRjbG9zZSgpO1xuXHRcdFx0XHRcdHRoYXQucHJvY2Vzc2luZyggZmFsc2UgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApXG5cdFx0XHQub24oICdjb3B5LmJ1dHRvbnMtY29weSBjdXQuYnV0dG9ucy1jb3B5JywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRjbG9zZSgpO1xuXHRcdFx0XHR0aGF0LnByb2Nlc3NpbmcoIGZhbHNlICk7XG5cdFx0XHR9ICk7XG5cdH0sXG5cblx0ZXhwb3J0T3B0aW9uczoge30sXG5cblx0ZmllbGRTZXBhcmF0b3I6ICdcXHQnLFxuXG5cdGZpZWxkQm91bmRhcnk6ICcnLFxuXG5cdGhlYWRlcjogdHJ1ZSxcblxuXHRmb290ZXI6IGZhbHNlLFxuXG5cdHRpdGxlOiAnKicsXG5cblx0bWVzc2FnZVRvcDogJyonLFxuXG5cdG1lc3NhZ2VCb3R0b206ICcqJ1xufTtcblxuLy9cbi8vIENTViBleHBvcnRcbi8vXG5EYXRhVGFibGUuZXh0LmJ1dHRvbnMuY3N2SHRtbDUgPSB7XG5cdGJvbTogZmFsc2UsXG5cblx0Y2xhc3NOYW1lOiAnYnV0dG9ucy1jc3YgYnV0dG9ucy1odG1sNScsXG5cblx0YXZhaWxhYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHdpbmRvdy5GaWxlUmVhZGVyICE9PSB1bmRlZmluZWQgJiYgd2luZG93LkJsb2I7XG5cdH0sXG5cblx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRyZXR1cm4gZHQuaTE4biggJ2J1dHRvbnMuY3N2JywgJ0NTVicgKTtcblx0fSxcblxuXHRhY3Rpb246IGZ1bmN0aW9uICggZSwgZHQsIGJ1dHRvbiwgY29uZmlnICkge1xuXHRcdHRoaXMucHJvY2Vzc2luZyggdHJ1ZSApO1xuXG5cdFx0Ly8gU2V0IHRoZSB0ZXh0XG5cdFx0dmFyIG91dHB1dCA9IF9leHBvcnREYXRhKCBkdCwgY29uZmlnICkuc3RyO1xuXHRcdHZhciBpbmZvID0gZHQuYnV0dG9ucy5leHBvcnRJbmZvKGNvbmZpZyk7XG5cdFx0dmFyIGNoYXJzZXQgPSBjb25maWcuY2hhcnNldDtcblxuXHRcdGlmICggY29uZmlnLmN1c3RvbWl6ZSApIHtcblx0XHRcdG91dHB1dCA9IGNvbmZpZy5jdXN0b21pemUoIG91dHB1dCwgY29uZmlnLCBkdCApO1xuXHRcdH1cblxuXHRcdGlmICggY2hhcnNldCAhPT0gZmFsc2UgKSB7XG5cdFx0XHRpZiAoICEgY2hhcnNldCApIHtcblx0XHRcdFx0Y2hhcnNldCA9IGRvY3VtZW50LmNoYXJhY3RlclNldCB8fCBkb2N1bWVudC5jaGFyc2V0O1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGNoYXJzZXQgKSB7XG5cdFx0XHRcdGNoYXJzZXQgPSAnO2NoYXJzZXQ9JytjaGFyc2V0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGNoYXJzZXQgPSAnJztcblx0XHR9XG5cblx0XHRpZiAoIGNvbmZpZy5ib20gKSB7XG5cdFx0XHRvdXRwdXQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4RkVGRikgKyBvdXRwdXQ7XG5cdFx0fVxuXG5cdFx0X3NhdmVBcyhcblx0XHRcdG5ldyBCbG9iKCBbb3V0cHV0XSwge3R5cGU6ICd0ZXh0L2NzdicrY2hhcnNldH0gKSxcblx0XHRcdGluZm8uZmlsZW5hbWUsXG5cdFx0XHR0cnVlXG5cdFx0KTtcblxuXHRcdHRoaXMucHJvY2Vzc2luZyggZmFsc2UgKTtcblx0fSxcblxuXHRmaWxlbmFtZTogJyonLFxuXG5cdGV4dGVuc2lvbjogJy5jc3YnLFxuXG5cdGV4cG9ydE9wdGlvbnM6IHt9LFxuXG5cdGZpZWxkU2VwYXJhdG9yOiAnLCcsXG5cblx0ZmllbGRCb3VuZGFyeTogJ1wiJyxcblxuXHRlc2NhcGVDaGFyOiAnXCInLFxuXG5cdGNoYXJzZXQ6IG51bGwsXG5cblx0aGVhZGVyOiB0cnVlLFxuXG5cdGZvb3RlcjogZmFsc2Vcbn07XG5cbi8vXG4vLyBFeGNlbCAoeGxzeCkgZXhwb3J0XG4vL1xuRGF0YVRhYmxlLmV4dC5idXR0b25zLmV4Y2VsSHRtbDUgPSB7XG5cdGNsYXNzTmFtZTogJ2J1dHRvbnMtZXhjZWwgYnV0dG9ucy1odG1sNScsXG5cblx0YXZhaWxhYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHdpbmRvdy5GaWxlUmVhZGVyICE9PSB1bmRlZmluZWQgJiYgX2pzWmlwKCkgIT09IHVuZGVmaW5lZCAmJiAhIF9pc0R1ZmZTYWZhcmkoKSAmJiBfc2VyaWFsaXNlcjtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5leGNlbCcsICdFeGNlbCcgKTtcblx0fSxcblxuXHRhY3Rpb246IGZ1bmN0aW9uICggZSwgZHQsIGJ1dHRvbiwgY29uZmlnICkge1xuXHRcdHRoaXMucHJvY2Vzc2luZyggdHJ1ZSApO1xuXG5cdFx0dmFyIHRoYXQgPSB0aGlzO1xuXHRcdHZhciByb3dQb3MgPSAwO1xuXHRcdHZhciBkYXRhU3RhcnRSb3csIGRhdGFFbmRSb3c7XG5cdFx0dmFyIGdldFhtbCA9IGZ1bmN0aW9uICggdHlwZSApIHtcblx0XHRcdHZhciBzdHIgPSBleGNlbFN0cmluZ3NbIHR5cGUgXTtcblxuXHRcdFx0Ly9zdHIgPSBzdHIucmVwbGFjZSggL3htbG5zOi9nLCAneG1sbnNfJyApLnJlcGxhY2UoIC9tYzovZywgJ21jXycgKTtcblxuXHRcdFx0cmV0dXJuICQucGFyc2VYTUwoIHN0ciApO1xuXHRcdH07XG5cdFx0dmFyIHJlbHMgPSBnZXRYbWwoJ3hsL3dvcmtzaGVldHMvc2hlZXQxLnhtbCcpO1xuXHRcdHZhciByZWxzR2V0ID0gcmVscy5nZXRFbGVtZW50c0J5VGFnTmFtZSggXCJzaGVldERhdGFcIiApWzBdO1xuXG5cdFx0dmFyIHhsc3ggPSB7XG5cdFx0XHRfcmVsczoge1xuXHRcdFx0XHRcIi5yZWxzXCI6IGdldFhtbCgnX3JlbHMvLnJlbHMnKVxuXHRcdFx0fSxcblx0XHRcdHhsOiB7XG5cdFx0XHRcdF9yZWxzOiB7XG5cdFx0XHRcdFx0XCJ3b3JrYm9vay54bWwucmVsc1wiOiBnZXRYbWwoJ3hsL19yZWxzL3dvcmtib29rLnhtbC5yZWxzJylcblx0XHRcdFx0fSxcblx0XHRcdFx0XCJ3b3JrYm9vay54bWxcIjogZ2V0WG1sKCd4bC93b3JrYm9vay54bWwnKSxcblx0XHRcdFx0XCJzdHlsZXMueG1sXCI6IGdldFhtbCgneGwvc3R5bGVzLnhtbCcpLFxuXHRcdFx0XHRcIndvcmtzaGVldHNcIjoge1xuXHRcdFx0XHRcdFwic2hlZXQxLnhtbFwiOiByZWxzXG5cdFx0XHRcdH1cblxuXHRcdFx0fSxcblx0XHRcdFwiW0NvbnRlbnRfVHlwZXNdLnhtbFwiOiBnZXRYbWwoJ1tDb250ZW50X1R5cGVzXS54bWwnKVxuXHRcdH07XG5cblx0XHR2YXIgZGF0YSA9IGR0LmJ1dHRvbnMuZXhwb3J0RGF0YSggY29uZmlnLmV4cG9ydE9wdGlvbnMgKTtcblx0XHR2YXIgY3VycmVudFJvdywgcm93Tm9kZTtcblx0XHR2YXIgYWRkUm93ID0gZnVuY3Rpb24gKCByb3cgKSB7XG5cdFx0XHRjdXJyZW50Um93ID0gcm93UG9zKzE7XG5cdFx0XHRyb3dOb2RlID0gX2NyZWF0ZU5vZGUoIHJlbHMsIFwicm93XCIsIHsgYXR0cjoge3I6Y3VycmVudFJvd30gfSApO1xuXG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49cm93Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHQvLyBDb25jYXQgYm90aCB0aGUgQ2VsbCBDb2x1bW5zIGFzIGEgbGV0dGVyIGFuZCB0aGUgUm93IG9mIHRoZSBjZWxsLlxuXHRcdFx0XHR2YXIgY2VsbElkID0gY3JlYXRlQ2VsbFBvcyhpKSArICcnICsgY3VycmVudFJvdztcblx0XHRcdFx0dmFyIGNlbGwgPSBudWxsO1xuXG5cdFx0XHRcdC8vIEZvciBudWxsLCB1bmRlZmluZWQgb2YgYmxhbmsgY2VsbCwgY29udGludWUgc28gaXQgZG9lc24ndCBjcmVhdGUgdGhlIF9jcmVhdGVOb2RlXG5cdFx0XHRcdGlmICggcm93W2ldID09PSBudWxsIHx8IHJvd1tpXSA9PT0gdW5kZWZpbmVkIHx8IHJvd1tpXSA9PT0gJycgKSB7XG5cdFx0XHRcdFx0aWYgKCBjb25maWcuY3JlYXRlRW1wdHlDZWxscyA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdHJvd1tpXSA9ICcnO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBvcmlnaW5hbENvbnRlbnQgPSByb3dbaV07XG5cdFx0XHRcdHJvd1tpXSA9IHR5cGVvZiByb3dbaV0udHJpbSA9PT0gJ2Z1bmN0aW9uJ1xuXHRcdFx0XHRcdD8gcm93W2ldLnRyaW0oKVxuXHRcdFx0XHRcdDogcm93W2ldO1xuXG5cdFx0XHRcdC8vIFNwZWNpYWwgbnVtYmVyIGZvcm1hdHRpbmcgb3B0aW9uc1xuXHRcdFx0XHRmb3IgKCB2YXIgaj0wLCBqZW49X2V4Y2VsU3BlY2lhbHMubGVuZ3RoIDsgajxqZW4gOyBqKysgKSB7XG5cdFx0XHRcdFx0dmFyIHNwZWNpYWwgPSBfZXhjZWxTcGVjaWFsc1tqXTtcblxuXHRcdFx0XHRcdC8vIFRPRE8gTmVlZCB0byBwcm92aWRlIHRoZSBhYmlsaXR5IGZvciB0aGUgc3BlY2lhbHMgdG8gc2F5XG5cdFx0XHRcdFx0Ly8gaWYgdGhleSBhcmUgcmV0dXJuaW5nIGEgc3RyaW5nLCBzaW5jZSBhdCB0aGUgbW9tZW50IGl0IGlzXG5cdFx0XHRcdFx0Ly8gYXNzdW1lZCB0byBiZSBhIG51bWJlclxuXHRcdFx0XHRcdGlmICggcm93W2ldLm1hdGNoICYmICEgcm93W2ldLm1hdGNoKC9eMFxcZCsvKSAmJiByb3dbaV0ubWF0Y2goIHNwZWNpYWwubWF0Y2ggKSApIHtcblx0XHRcdFx0XHRcdHZhciB2YWwgPSByb3dbaV0ucmVwbGFjZSgvW15cXGRcXC5cXC1dL2csICcnKTtcblxuXHRcdFx0XHRcdFx0aWYgKCBzcGVjaWFsLmZtdCApIHtcblx0XHRcdFx0XHRcdFx0dmFsID0gc3BlY2lhbC5mbXQoIHZhbCApO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRjZWxsID0gX2NyZWF0ZU5vZGUoIHJlbHMsICdjJywge1xuXHRcdFx0XHRcdFx0XHRhdHRyOiB7XG5cdFx0XHRcdFx0XHRcdFx0cjogY2VsbElkLFxuXHRcdFx0XHRcdFx0XHRcdHM6IHNwZWNpYWwuc3R5bGVcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0Y2hpbGRyZW46IFtcblx0XHRcdFx0XHRcdFx0XHRfY3JlYXRlTm9kZSggcmVscywgJ3YnLCB7IHRleHQ6IHZhbCB9IClcblx0XHRcdFx0XHRcdFx0XVxuXHRcdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoICEgY2VsbCApIHtcblx0XHRcdFx0XHRpZiAoIHR5cGVvZiByb3dbaV0gPT09ICdudW1iZXInIHx8IChcblx0XHRcdFx0XHRcdHJvd1tpXS5tYXRjaCAmJlxuXHRcdFx0XHRcdFx0cm93W2ldLm1hdGNoKC9eLT9cXGQrKFxcLlxcZCspPyhbZUVdXFwtP1xcZCspPyQvKSAmJiAvLyBJbmNsdWRlcyBleHBvbmVudGlhbCBmb3JtYXRcblx0XHRcdFx0XHRcdCEgcm93W2ldLm1hdGNoKC9eMFxcZCsvKSApXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHQvLyBEZXRlY3QgbnVtYmVycyAtIGRvbid0IG1hdGNoIG51bWJlcnMgd2l0aCBsZWFkaW5nIHplcm9zXG5cdFx0XHRcdFx0XHQvLyBvciBhIG5lZ2F0aXZlIGFueXdoZXJlIGJ1dCB0aGUgc3RhcnRcblx0XHRcdFx0XHRcdGNlbGwgPSBfY3JlYXRlTm9kZSggcmVscywgJ2MnLCB7XG5cdFx0XHRcdFx0XHRcdGF0dHI6IHtcblx0XHRcdFx0XHRcdFx0XHR0OiAnbicsXG5cdFx0XHRcdFx0XHRcdFx0cjogY2VsbElkXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdGNoaWxkcmVuOiBbXG5cdFx0XHRcdFx0XHRcdFx0X2NyZWF0ZU5vZGUoIHJlbHMsICd2JywgeyB0ZXh0OiByb3dbaV0gfSApXG5cdFx0XHRcdFx0XHRcdF1cblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHQvLyBTdHJpbmcgb3V0cHV0IC0gcmVwbGFjZSBub24gc3RhbmRhcmQgY2hhcmFjdGVycyBmb3IgdGV4dCBvdXRwdXRcblx0XHRcdFx0XHRcdHZhciB0ZXh0ID0gISBvcmlnaW5hbENvbnRlbnQucmVwbGFjZSA/XG5cdFx0XHRcdFx0XHRcdG9yaWdpbmFsQ29udGVudCA6XG5cdFx0XHRcdFx0XHRcdG9yaWdpbmFsQ29udGVudC5yZXBsYWNlKC9bXFx4MDAtXFx4MDlcXHgwQlxceDBDXFx4MEUtXFx4MUZcXHg3Ri1cXHg5Rl0vZywgJycpO1xuXG5cdFx0XHRcdFx0XHRjZWxsID0gX2NyZWF0ZU5vZGUoIHJlbHMsICdjJywge1xuXHRcdFx0XHRcdFx0XHRhdHRyOiB7XG5cdFx0XHRcdFx0XHRcdFx0dDogJ2lubGluZVN0cicsXG5cdFx0XHRcdFx0XHRcdFx0cjogY2VsbElkXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdGNoaWxkcmVuOntcblx0XHRcdFx0XHRcdFx0XHRyb3c6IF9jcmVhdGVOb2RlKCByZWxzLCAnaXMnLCB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjaGlsZHJlbjoge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyb3c6IF9jcmVhdGVOb2RlKCByZWxzLCAndCcsIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0ZXh0OiB0ZXh0LFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGF0dHI6IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd4bWw6c3BhY2UnOiAncHJlc2VydmUnXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9IClcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9IClcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJvd05vZGUuYXBwZW5kQ2hpbGQoIGNlbGwgKTtcblx0XHRcdH1cblxuXHRcdFx0cmVsc0dldC5hcHBlbmRDaGlsZChyb3dOb2RlKTtcblx0XHRcdHJvd1BvcysrO1xuXHRcdH07XG5cblx0XHRpZiAoIGNvbmZpZy5jdXN0b21pemVEYXRhICkge1xuXHRcdFx0Y29uZmlnLmN1c3RvbWl6ZURhdGEoIGRhdGEgKTtcblx0XHR9XG5cblx0XHR2YXIgbWVyZ2VDZWxscyA9IGZ1bmN0aW9uICggcm93LCBjb2xzcGFuICkge1xuXHRcdFx0dmFyIG1lcmdlQ2VsbHMgPSAkKCdtZXJnZUNlbGxzJywgcmVscyk7XG5cblx0XHRcdG1lcmdlQ2VsbHNbMF0uYXBwZW5kQ2hpbGQoIF9jcmVhdGVOb2RlKCByZWxzLCAnbWVyZ2VDZWxsJywge1xuXHRcdFx0XHRhdHRyOiB7XG5cdFx0XHRcdFx0cmVmOiAnQScrcm93Kyc6JytjcmVhdGVDZWxsUG9zKGNvbHNwYW4pK3Jvd1xuXHRcdFx0XHR9XG5cdFx0XHR9ICkgKTtcblx0XHRcdG1lcmdlQ2VsbHMuYXR0ciggJ2NvdW50JywgcGFyc2VGbG9hdChtZXJnZUNlbGxzLmF0dHIoICdjb3VudCcgKSkrMSApO1xuXHRcdFx0JCgncm93OmVxKCcrKHJvdy0xKSsnKSBjJywgcmVscykuYXR0ciggJ3MnLCAnNTEnICk7IC8vIGNlbnRyZVxuXHRcdH07XG5cblx0XHQvLyBUaXRsZSBhbmQgdG9wIG1lc3NhZ2VzXG5cdFx0dmFyIGV4cG9ydEluZm8gPSBkdC5idXR0b25zLmV4cG9ydEluZm8oIGNvbmZpZyApO1xuXHRcdGlmICggZXhwb3J0SW5mby50aXRsZSApIHtcblx0XHRcdGFkZFJvdyggW2V4cG9ydEluZm8udGl0bGVdLCByb3dQb3MgKTtcblx0XHRcdG1lcmdlQ2VsbHMoIHJvd1BvcywgZGF0YS5oZWFkZXIubGVuZ3RoLTEgKTtcblx0XHR9XG5cblx0XHRpZiAoIGV4cG9ydEluZm8ubWVzc2FnZVRvcCApIHtcblx0XHRcdGFkZFJvdyggW2V4cG9ydEluZm8ubWVzc2FnZVRvcF0sIHJvd1BvcyApO1xuXHRcdFx0bWVyZ2VDZWxscyggcm93UG9zLCBkYXRhLmhlYWRlci5sZW5ndGgtMSApO1xuXHRcdH1cblxuXG5cdFx0Ly8gVGFibGUgaXRzZWxmXG5cdFx0aWYgKCBjb25maWcuaGVhZGVyICkge1xuXHRcdFx0YWRkUm93KCBkYXRhLmhlYWRlciwgcm93UG9zICk7XG5cdFx0XHQkKCdyb3c6bGFzdCBjJywgcmVscykuYXR0ciggJ3MnLCAnMicgKTsgLy8gYm9sZFxuXHRcdH1cblx0XG5cdFx0ZGF0YVN0YXJ0Um93ID0gcm93UG9zO1xuXG5cdFx0Zm9yICggdmFyIG49MCwgaWU9ZGF0YS5ib2R5Lmxlbmd0aCA7IG48aWUgOyBuKysgKSB7XG5cdFx0XHRhZGRSb3coIGRhdGEuYm9keVtuXSwgcm93UG9zICk7XG5cdFx0fVxuXHRcblx0XHRkYXRhRW5kUm93ID0gcm93UG9zO1xuXG5cdFx0aWYgKCBjb25maWcuZm9vdGVyICYmIGRhdGEuZm9vdGVyICkge1xuXHRcdFx0YWRkUm93KCBkYXRhLmZvb3Rlciwgcm93UG9zKTtcblx0XHRcdCQoJ3JvdzpsYXN0IGMnLCByZWxzKS5hdHRyKCAncycsICcyJyApOyAvLyBib2xkXG5cdFx0fVxuXG5cdFx0Ly8gQmVsb3cgdGhlIHRhYmxlXG5cdFx0aWYgKCBleHBvcnRJbmZvLm1lc3NhZ2VCb3R0b20gKSB7XG5cdFx0XHRhZGRSb3coIFtleHBvcnRJbmZvLm1lc3NhZ2VCb3R0b21dLCByb3dQb3MgKTtcblx0XHRcdG1lcmdlQ2VsbHMoIHJvd1BvcywgZGF0YS5oZWFkZXIubGVuZ3RoLTEgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgY29sdW1uIHdpZHRoc1xuXHRcdHZhciBjb2xzID0gX2NyZWF0ZU5vZGUoIHJlbHMsICdjb2xzJyApO1xuXHRcdCQoJ3dvcmtzaGVldCcsIHJlbHMpLnByZXBlbmQoIGNvbHMgKTtcblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1kYXRhLmhlYWRlci5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGNvbHMuYXBwZW5kQ2hpbGQoIF9jcmVhdGVOb2RlKCByZWxzLCAnY29sJywge1xuXHRcdFx0XHRhdHRyOiB7XG5cdFx0XHRcdFx0bWluOiBpKzEsXG5cdFx0XHRcdFx0bWF4OiBpKzEsXG5cdFx0XHRcdFx0d2lkdGg6IF9leGNlbENvbFdpZHRoKCBkYXRhLCBpICksXG5cdFx0XHRcdFx0Y3VzdG9tV2lkdGg6IDFcblx0XHRcdFx0fVxuXHRcdFx0fSApICk7XG5cdFx0fVxuXG5cdFx0Ly8gV29ya2Jvb2sgbW9kaWZpY2F0aW9uc1xuXHRcdHZhciB3b3JrYm9vayA9IHhsc3gueGxbJ3dvcmtib29rLnhtbCddO1xuXG5cdFx0JCggJ3NoZWV0cyBzaGVldCcsIHdvcmtib29rICkuYXR0ciggJ25hbWUnLCBfc2hlZXRuYW1lKCBjb25maWcgKSApO1xuXG5cdFx0Ly8gQXV0byBmaWx0ZXIgZm9yIGNvbHVtbnNcblx0XHRpZiAoIGNvbmZpZy5hdXRvRmlsdGVyICkge1xuXHRcdFx0JCgnbWVyZ2VDZWxscycsIHJlbHMpLmJlZm9yZSggX2NyZWF0ZU5vZGUoIHJlbHMsICdhdXRvRmlsdGVyJywge1xuXHRcdFx0XHRhdHRyOiB7XG5cdFx0XHRcdFx0cmVmOiAnQScrZGF0YVN0YXJ0Um93Kyc6JytjcmVhdGVDZWxsUG9zKGRhdGEuaGVhZGVyLmxlbmd0aC0xKStkYXRhRW5kUm93XG5cdFx0XHRcdH1cblx0XHRcdH0gKSApO1xuXG5cdFx0XHQkKCdkZWZpbmVkTmFtZXMnLCB3b3JrYm9vaykuYXBwZW5kKCBfY3JlYXRlTm9kZSggd29ya2Jvb2ssICdkZWZpbmVkTmFtZScsIHtcblx0XHRcdFx0YXR0cjoge1xuXHRcdFx0XHRcdG5hbWU6ICdfeGxubS5fRmlsdGVyRGF0YWJhc2UnLFxuXHRcdFx0XHRcdGxvY2FsU2hlZXRJZDogJzAnLFxuXHRcdFx0XHRcdGhpZGRlbjogMVxuXHRcdFx0XHR9LFxuXHRcdFx0XHR0ZXh0OiBfc2hlZXRuYW1lKGNvbmZpZykrJyEkQSQnK2RhdGFTdGFydFJvdysnOicrY3JlYXRlQ2VsbFBvcyhkYXRhLmhlYWRlci5sZW5ndGgtMSkrZGF0YUVuZFJvd1xuXHRcdFx0fSApICk7XG5cdFx0fVxuXG5cdFx0Ly8gTGV0IHRoZSBkZXZlbG9wZXIgY3VzdG9taXNlIHRoZSBkb2N1bWVudCBpZiB0aGV5IHdhbnQgdG9cblx0XHRpZiAoIGNvbmZpZy5jdXN0b21pemUgKSB7XG5cdFx0XHRjb25maWcuY3VzdG9taXplKCB4bHN4LCBjb25maWcsIGR0ICk7XG5cdFx0fVxuXG5cdFx0Ly8gRXhjZWwgZG9lc24ndCBsaWtlIGFuIGVtcHR5IG1lcmdlQ2VsbHMgdGFnXG5cdFx0aWYgKCAkKCdtZXJnZUNlbGxzJywgcmVscykuY2hpbGRyZW4oKS5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHQkKCdtZXJnZUNlbGxzJywgcmVscykucmVtb3ZlKCk7XG5cdFx0fVxuXG5cdFx0dmFyIGpzemlwID0gX2pzWmlwKCk7XG5cdFx0dmFyIHppcCA9IG5ldyBqc3ppcCgpO1xuXHRcdHZhciB6aXBDb25maWcgPSB7XG5cdFx0XHR0eXBlOiAnYmxvYicsXG5cdFx0XHRtaW1lVHlwZTogJ2FwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC5zcHJlYWRzaGVldG1sLnNoZWV0J1xuXHRcdH07XG5cblx0XHRfYWRkVG9aaXAoIHppcCwgeGxzeCApO1xuXG5cdFx0aWYgKCB6aXAuZ2VuZXJhdGVBc3luYyApIHtcblx0XHRcdC8vIEpTWmlwIDMrXG5cdFx0XHR6aXBcblx0XHRcdFx0LmdlbmVyYXRlQXN5bmMoIHppcENvbmZpZyApXG5cdFx0XHRcdC50aGVuKCBmdW5jdGlvbiAoIGJsb2IgKSB7XG5cdFx0XHRcdFx0X3NhdmVBcyggYmxvYiwgZXhwb3J0SW5mby5maWxlbmFtZSApO1xuXHRcdFx0XHRcdHRoYXQucHJvY2Vzc2luZyggZmFsc2UgKTtcblx0XHRcdFx0fSApO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdC8vIEpTWmlwIDIuNVxuXHRcdFx0X3NhdmVBcyhcblx0XHRcdFx0emlwLmdlbmVyYXRlKCB6aXBDb25maWcgKSxcblx0XHRcdFx0ZXhwb3J0SW5mby5maWxlbmFtZVxuXHRcdFx0KTtcblx0XHRcdHRoaXMucHJvY2Vzc2luZyggZmFsc2UgKTtcblx0XHR9XG5cdH0sXG5cblx0ZmlsZW5hbWU6ICcqJyxcblxuXHRleHRlbnNpb246ICcueGxzeCcsXG5cblx0ZXhwb3J0T3B0aW9uczoge30sXG5cblx0aGVhZGVyOiB0cnVlLFxuXG5cdGZvb3RlcjogZmFsc2UsXG5cblx0dGl0bGU6ICcqJyxcblxuXHRtZXNzYWdlVG9wOiAnKicsXG5cblx0bWVzc2FnZUJvdHRvbTogJyonLFxuXG5cdGNyZWF0ZUVtcHR5Q2VsbHM6IGZhbHNlLFxuXG5cdGF1dG9GaWx0ZXI6IGZhbHNlLFxuXG5cdHNoZWV0TmFtZTogJydcbn07XG5cbi8vXG4vLyBQREYgZXhwb3J0IC0gdXNpbmcgcGRmTWFrZSAtIGh0dHA6Ly9wZGZtYWtlLm9yZ1xuLy9cbkRhdGFUYWJsZS5leHQuYnV0dG9ucy5wZGZIdG1sNSA9IHtcblx0Y2xhc3NOYW1lOiAnYnV0dG9ucy1wZGYgYnV0dG9ucy1odG1sNScsXG5cblx0YXZhaWxhYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHdpbmRvdy5GaWxlUmVhZGVyICE9PSB1bmRlZmluZWQgJiYgX3BkZk1ha2UoKTtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5wZGYnLCAnUERGJyApO1xuXHR9LFxuXG5cdGFjdGlvbjogZnVuY3Rpb24gKCBlLCBkdCwgYnV0dG9uLCBjb25maWcgKSB7XG5cdFx0dGhpcy5wcm9jZXNzaW5nKCB0cnVlICk7XG5cblx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFx0dmFyIGRhdGEgPSBkdC5idXR0b25zLmV4cG9ydERhdGEoIGNvbmZpZy5leHBvcnRPcHRpb25zICk7XG5cdFx0dmFyIGluZm8gPSBkdC5idXR0b25zLmV4cG9ydEluZm8oIGNvbmZpZyApO1xuXHRcdHZhciByb3dzID0gW107XG5cblx0XHRpZiAoIGNvbmZpZy5oZWFkZXIgKSB7XG5cdFx0XHRyb3dzLnB1c2goICQubWFwKCBkYXRhLmhlYWRlciwgZnVuY3Rpb24gKCBkICkge1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHRleHQ6IHR5cGVvZiBkID09PSAnc3RyaW5nJyA/IGQgOiBkKycnLFxuXHRcdFx0XHRcdHN0eWxlOiAndGFibGVIZWFkZXInXG5cdFx0XHRcdH07XG5cdFx0XHR9ICkgKTtcblx0XHR9XG5cblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49ZGF0YS5ib2R5Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0cm93cy5wdXNoKCAkLm1hcCggZGF0YS5ib2R5W2ldLCBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0XHRcdGlmICggZCA9PT0gbnVsbCB8fCBkID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0ZCA9ICcnO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0dGV4dDogdHlwZW9mIGQgPT09ICdzdHJpbmcnID8gZCA6IGQrJycsXG5cdFx0XHRcdFx0c3R5bGU6IGkgJSAyID8gJ3RhYmxlQm9keUV2ZW4nIDogJ3RhYmxlQm9keU9kZCdcblx0XHRcdFx0fTtcblx0XHRcdH0gKSApO1xuXHRcdH1cblxuXHRcdGlmICggY29uZmlnLmZvb3RlciAmJiBkYXRhLmZvb3Rlcikge1xuXHRcdFx0cm93cy5wdXNoKCAkLm1hcCggZGF0YS5mb290ZXIsIGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHR0ZXh0OiB0eXBlb2YgZCA9PT0gJ3N0cmluZycgPyBkIDogZCsnJyxcblx0XHRcdFx0XHRzdHlsZTogJ3RhYmxlRm9vdGVyJ1xuXHRcdFx0XHR9O1xuXHRcdFx0fSApICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRvYyA9IHtcblx0XHRcdHBhZ2VTaXplOiBjb25maWcucGFnZVNpemUsXG5cdFx0XHRwYWdlT3JpZW50YXRpb246IGNvbmZpZy5vcmllbnRhdGlvbixcblx0XHRcdGNvbnRlbnQ6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRhYmxlOiB7XG5cdFx0XHRcdFx0XHRoZWFkZXJSb3dzOiAxLFxuXHRcdFx0XHRcdFx0Ym9keTogcm93c1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bGF5b3V0OiAnbm9Cb3JkZXJzJ1xuXHRcdFx0XHR9XG5cdFx0XHRdLFxuXHRcdFx0c3R5bGVzOiB7XG5cdFx0XHRcdHRhYmxlSGVhZGVyOiB7XG5cdFx0XHRcdFx0Ym9sZDogdHJ1ZSxcblx0XHRcdFx0XHRmb250U2l6ZTogMTEsXG5cdFx0XHRcdFx0Y29sb3I6ICd3aGl0ZScsXG5cdFx0XHRcdFx0ZmlsbENvbG9yOiAnIzJkNDE1NCcsXG5cdFx0XHRcdFx0YWxpZ25tZW50OiAnY2VudGVyJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR0YWJsZUJvZHlFdmVuOiB7fSxcblx0XHRcdFx0dGFibGVCb2R5T2RkOiB7XG5cdFx0XHRcdFx0ZmlsbENvbG9yOiAnI2YzZjNmMydcblx0XHRcdFx0fSxcblx0XHRcdFx0dGFibGVGb290ZXI6IHtcblx0XHRcdFx0XHRib2xkOiB0cnVlLFxuXHRcdFx0XHRcdGZvbnRTaXplOiAxMSxcblx0XHRcdFx0XHRjb2xvcjogJ3doaXRlJyxcblx0XHRcdFx0XHRmaWxsQ29sb3I6ICcjMmQ0MTU0J1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR0aXRsZToge1xuXHRcdFx0XHRcdGFsaWdubWVudDogJ2NlbnRlcicsXG5cdFx0XHRcdFx0Zm9udFNpemU6IDE1XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG1lc3NhZ2U6IHt9XG5cdFx0XHR9LFxuXHRcdFx0ZGVmYXVsdFN0eWxlOiB7XG5cdFx0XHRcdGZvbnRTaXplOiAxMFxuXHRcdFx0fVxuXHRcdH07XG5cblx0XHRpZiAoIGluZm8ubWVzc2FnZVRvcCApIHtcblx0XHRcdGRvYy5jb250ZW50LnVuc2hpZnQoIHtcblx0XHRcdFx0dGV4dDogaW5mby5tZXNzYWdlVG9wLFxuXHRcdFx0XHRzdHlsZTogJ21lc3NhZ2UnLFxuXHRcdFx0XHRtYXJnaW46IFsgMCwgMCwgMCwgMTIgXVxuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGlmICggaW5mby5tZXNzYWdlQm90dG9tICkge1xuXHRcdFx0ZG9jLmNvbnRlbnQucHVzaCgge1xuXHRcdFx0XHR0ZXh0OiBpbmZvLm1lc3NhZ2VCb3R0b20sXG5cdFx0XHRcdHN0eWxlOiAnbWVzc2FnZScsXG5cdFx0XHRcdG1hcmdpbjogWyAwLCAwLCAwLCAxMiBdXG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpbmZvLnRpdGxlICkge1xuXHRcdFx0ZG9jLmNvbnRlbnQudW5zaGlmdCgge1xuXHRcdFx0XHR0ZXh0OiBpbmZvLnRpdGxlLFxuXHRcdFx0XHRzdHlsZTogJ3RpdGxlJyxcblx0XHRcdFx0bWFyZ2luOiBbIDAsIDAsIDAsIDEyIF1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIGNvbmZpZy5jdXN0b21pemUgKSB7XG5cdFx0XHRjb25maWcuY3VzdG9taXplKCBkb2MsIGNvbmZpZywgZHQgKTtcblx0XHR9XG5cblx0XHR2YXIgcGRmID0gX3BkZk1ha2UoKS5jcmVhdGVQZGYoIGRvYyApO1xuXG5cdFx0aWYgKCBjb25maWcuZG93bmxvYWQgPT09ICdvcGVuJyAmJiAhIF9pc0R1ZmZTYWZhcmkoKSApIHtcblx0XHRcdHBkZi5vcGVuKCk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0cGRmLmRvd25sb2FkKCBpbmZvLmZpbGVuYW1lICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5wcm9jZXNzaW5nKCBmYWxzZSApO1xuXHR9LFxuXG5cdHRpdGxlOiAnKicsXG5cblx0ZmlsZW5hbWU6ICcqJyxcblxuXHRleHRlbnNpb246ICcucGRmJyxcblxuXHRleHBvcnRPcHRpb25zOiB7fSxcblxuXHRvcmllbnRhdGlvbjogJ3BvcnRyYWl0JyxcblxuXHRwYWdlU2l6ZTogJ0E0JyxcblxuXHRoZWFkZXI6IHRydWUsXG5cblx0Zm9vdGVyOiBmYWxzZSxcblxuXHRtZXNzYWdlVG9wOiAnKicsXG5cblx0bWVzc2FnZUJvdHRvbTogJyonLFxuXG5cdGN1c3RvbWl6ZTogbnVsbCxcblxuXHRkb3dubG9hZDogJ2Rvd25sb2FkJ1xufTtcblxuXG5yZXR1cm4gRGF0YVRhYmxlLkJ1dHRvbnM7XG59KSk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/buttons.html5.js\n"); /***/ }), /***/ "./node_modules/datatables.net-buttons/js/dataTables.buttons.js": /*!**********************************************************************!*\ !*** ./node_modules/datatables.net-buttons/js/dataTables.buttons.js ***! \**********************************************************************/ /***/ (function(module, exports, __webpack_require__) { eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! Buttons for DataTables 2.2.3\n * ©2016-2022 SpryMedia Ltd - datatables.net/license\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n\n// Used for namespacing events added to the document by each instance, so they\n// can be removed on destroy\nvar _instCounter = 0;\n\n// Button namespacing counter for namespacing events on individual buttons\nvar _buttonCounter = 0;\n\nvar _dtButtons = DataTable.ext.buttons;\n\n// Allow for jQuery slim\nfunction _fadeIn(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeIn( duration, fn );\n\n\t}\n\telse {\n\t\tel.css('display', 'block');\n\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\nfunction _fadeOut(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeOut( duration, fn );\n\t}\n\telse {\n\t\tel.css('display', 'none');\n\t\t\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\n/**\n * [Buttons description]\n * @param {[type]}\n * @param {[type]}\n */\nvar Buttons = function( dt, config )\n{\n\t// If not created with a `new` keyword then we return a wrapper function that\n\t// will take the settings object for a DT. This allows easy use of new instances\n\t// with the `layout` option - e.g. `topLeft: $.fn.dataTable.Buttons( ... )`.\n\tif ( !(this instanceof Buttons) ) {\n\t\treturn function (settings) {\n\t\t\treturn new Buttons( settings, dt ).container();\n\t\t};\n\t}\n\n\t// If there is no config set it to an empty object\n\tif ( typeof( config ) === 'undefined' ) {\n\t\tconfig = {};\t\n\t}\n\t\n\t// Allow a boolean true for defaults\n\tif ( config === true ) {\n\t\tconfig = {};\n\t}\n\n\t// For easy configuration of buttons an array can be given\n\tif ( Array.isArray( config ) ) {\n\t\tconfig = { buttons: config };\n\t}\n\n\tthis.c = $.extend( true, {}, Buttons.defaults, config );\n\n\t// Don't want a deep copy for the buttons\n\tif ( config.buttons ) {\n\t\tthis.c.buttons = config.buttons;\n\t}\n\n\tthis.s = {\n\t\tdt: new DataTable.Api( dt ),\n\t\tbuttons: [],\n\t\tlistenKeys: '',\n\t\tnamespace: 'dtb'+(_instCounter++)\n\t};\n\n\tthis.dom = {\n\t\tcontainer: $('<'+this.c.dom.container.tag+'/>')\n\t\t\t.addClass( this.c.dom.container.className )\n\t};\n\n\tthis._constructor();\n};\n\n\n$.extend( Buttons.prototype, {\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Public methods\n\t */\n\n\t/**\n\t * Get the action of a button\n\t * @param {int|string} Button index\n\t * @return {function}\n\t *//**\n\t * Set the action of a button\n\t * @param {node} node Button element\n\t * @param {function} action Function to set\n\t * @return {Buttons} Self for chaining\n\t */\n\taction: function ( node, action )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( action === undefined ) {\n\t\t\treturn button.conf.action;\n\t\t}\n\n\t\tbutton.conf.action = action;\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add an active class to the button to make to look active or get current\n\t * active state.\n\t * @param {node} node Button element\n\t * @param {boolean} [flag] Enable / disable flag\n\t * @return {Buttons} Self for chaining or boolean for getter\n\t */\n\tactive: function ( node, flag ) {\n\t\tvar button = this._nodeToButton( node );\n\t\tvar klass = this.c.dom.button.active;\n\t\tvar jqNode = $(button.node);\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn jqNode.hasClass( klass );\n\t\t}\n\n\t\tjqNode.toggleClass( klass, flag === undefined ? true : flag );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add a new button\n\t * @param {object} config Button configuration object, base string name or function\n\t * @param {int|string} [idx] Button index for where to insert the button\n\t * @param {boolean} [draw=true] Trigger a draw. Set a false when adding\n\t * lots of buttons, until the last button.\n\t * @return {Buttons} Self for chaining\n\t */\n\tadd: function ( config, idx, draw )\n\t{\n\t\tvar buttons = this.s.buttons;\n\n\t\tif ( typeof idx === 'string' ) {\n\t\t\tvar split = idx.split('-');\n\t\t\tvar base = this.s;\n\n\t\t\tfor ( var i=0, ien=split.length-1 ; i<ien ; i++ ) {\n\t\t\t\tbase = base.buttons[ split[i]*1 ];\n\t\t\t}\n\n\t\t\tbuttons = base.buttons;\n\t\t\tidx = split[ split.length-1 ]*1;\n\t\t}\n\n\t\tthis._expandButton(\n\t\t\tbuttons,\n\t\t\tconfig,\n\t\t\tconfig !== undefined ? config.split : undefined,\n\t\t\t(config === undefined || config.split === undefined || config.split.length === 0) && base !== undefined,\n\t\t\tfalse,\n\t\t\tidx\n\t\t);\n\n\t\tif (draw === undefined || draw === true) {\n\t\t\tthis._draw();\n\t\t}\n\t\n\t\treturn this;\n\t},\n\n\t/**\n\t * Clear buttons from a collection and then insert new buttons\n\t */\n\tcollectionRebuild: function ( node, newButtons )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\t\n\t\tif(newButtons !== undefined) {\n\t\t\tvar i;\n\t\t\t// Need to reverse the array\n\t\t\tfor (i=button.buttons.length-1; i>=0; i--) {\n\t\t\t\tthis.remove(button.buttons[i].node);\n\t\t\t}\n\t\n\t\t\tfor (i=0; i<newButtons.length; i++) {\n\t\t\t\tvar newBtn = newButtons[i];\n\n\t\t\t\tthis._expandButton(\n\t\t\t\t\tbutton.buttons,\n\t\t\t\t\tnewBtn,\n\t\t\t\t\tnewBtn !== undefined && newBtn.config !== undefined && newBtn.config.split !== undefined,\n\t\t\t\t\ttrue,\n\t\t\t\t\tnewBtn.parentConf !== undefined && newBtn.parentConf.split !== undefined,\n\t\t\t\t\ti,\n\t\t\t\t\tnewBtn.parentConf\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._draw(button.collection, button.buttons);\n\t},\n\n\t/**\n\t * Get the container node for the buttons\n\t * @return {jQuery} Buttons node\n\t */\n\tcontainer: function ()\n\t{\n\t\treturn this.dom.container;\n\t},\n\n\t/**\n\t * Disable a button\n\t * @param {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tdisable: function ( node ) {\n\t\tvar button = this._nodeToButton( node );\n\n\t\t$(button.node)\n\t\t\t.addClass( this.c.dom.button.disabled )\n\t\t\t.attr('disabled', true);\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Destroy the instance, cleaning up event handlers and removing DOM\n\t * elements\n\t * @return {Buttons} Self for chaining\n\t */\n\tdestroy: function ()\n\t{\n\t\t// Key event listener\n\t\t$('body').off( 'keyup.'+this.s.namespace );\n\n\t\t// Individual button destroy (so they can remove their own events if\n\t\t// needed). Take a copy as the array is modified by `remove`\n\t\tvar buttons = this.s.buttons.slice();\n\t\tvar i, ien;\n\t\t\n\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.remove( buttons[i].node );\n\t\t}\n\n\t\t// Container\n\t\tthis.dom.container.remove();\n\n\t\t// Remove from the settings object collection\n\t\tvar buttonInsts = this.s.dt.settings()[0];\n\n\t\tfor ( i=0, ien=buttonInsts.length ; i<ien ; i++ ) {\n\t\t\tif ( buttonInsts.inst === this ) {\n\t\t\t\tbuttonInsts.splice( i, 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Enable / disable a button\n\t * @param {node} node Button node\n\t * @param {boolean} [flag=true] Enable / disable flag\n\t * @return {Buttons} Self for chaining\n\t */\n\tenable: function ( node, flag )\n\t{\n\t\tif ( flag === false ) {\n\t\t\treturn this.disable( node );\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\t$(button.node)\n\t\t\t.removeClass( this.c.dom.button.disabled )\n\t\t\t.removeAttr('disabled');\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get a button's index\n\t * \n\t * This is internally recursive\n\t * @param {element} node Button to get the index of\n\t * @return {string} Button index\n\t */\n\tindex: function ( node, nested, buttons )\n\t{\n\t\tif ( ! nested ) {\n\t\t\tnested = '';\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar inner = buttons[i].buttons;\n\n\t\t\tif (buttons[i].node === node) {\n\t\t\t\treturn nested + i;\n\t\t\t}\n\n\t\t\tif ( inner && inner.length ) {\n\t\t\t\tvar match = this.index(node, i + '-', inner);\n\n\t\t\t\tif (match !== null) {\n\t\t\t\t\treturn match;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\n\n\t/**\n\t * Get the instance name for the button set selector\n\t * @return {string} Instance name\n\t */\n\tname: function ()\n\t{\n\t\treturn this.c.name;\n\t},\n\n\t/**\n\t * Get a button's node of the buttons container if no button is given\n\t * @param {node} [node] Button node\n\t * @return {jQuery} Button element, or container\n\t */\n\tnode: function ( node )\n\t{\n\t\tif ( ! node ) {\n\t\t\treturn this.dom.container;\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\treturn $(button.node);\n\t},\n\n\t/**\n\t * Set / get a processing class on the selected button\n\t * @param {element} node Triggering button node\n\t * @param {boolean} flag true to add, false to remove, undefined to get\n\t * @return {boolean|Buttons} Getter value or this if a setter.\n\t */\n\tprocessing: function ( node, flag )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn $(button.node).hasClass( 'processing' );\n\t\t}\n\n\t\t$(button.node).toggleClass( 'processing', flag );\n\n\t\t$(dt.table().node()).triggerHandler( 'buttons-processing.dt', [\n\t\t\tflag, dt.button( node ), dt, $(node), button.conf\n\t\t] );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a button.\n\t * @param {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tremove: function ( node )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar host = this._nodeToHost( node );\n\t\tvar dt = this.s.dt;\n\n\t\t// Remove any child buttons first\n\t\tif ( button.buttons.length ) {\n\t\t\tfor ( var i=button.buttons.length-1 ; i>=0 ; i-- ) {\n\t\t\t\tthis.remove( button.buttons[i].node );\n\t\t\t}\n\t\t}\n\n\t\tbutton.conf.destroying = true;\n\n\t\t// Allow the button to remove event handlers, etc\n\t\tif ( button.conf.destroy ) {\n\t\t\tbutton.conf.destroy.call( dt.button(node), dt, $(node), button.conf );\n\t\t}\n\n\t\tthis._removeKey( button.conf );\n\n\t\t$(button.node).remove();\n\n\t\tvar idx = $.inArray( button, host );\n\t\thost.splice( idx, 1 );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get the text for a button\n\t * @param {int|string} node Button index\n\t * @return {string} Button text\n\t *//**\n\t * Set the text for a button\n\t * @param {int|string|function} node Button index\n\t * @param {string} label Text\n\t * @return {Buttons} Self for chaining\n\t */\n\ttext: function ( node, label )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar buttonLiner = this.c.dom.collection.buttonLiner;\n\t\tvar linerTag = button.inCollection && buttonLiner && buttonLiner.tag ?\n\t\t\tbuttonLiner.tag :\n\t\t\tthis.c.dom.buttonLiner.tag;\n\t\tvar dt = this.s.dt;\n\t\tvar jqNode = $(button.node);\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, jqNode, button.conf ) :\n\t\t\t\topt;\n\t\t};\n\n\t\tif ( label === undefined ) {\n\t\t\treturn text( button.conf.text );\n\t\t}\n\n\t\tbutton.conf.text = label;\n\n\t\tif ( linerTag ) {\n\t\t\tjqNode\n\t\t\t\t.children( linerTag )\n\t\t\t\t.eq(0)\n\t\t\t\t.filter(':not(.dt-down-arrow)')\n\t\t\t\t.html( text(label) );\n\t\t}\n\t\telse {\n\t\t\tjqNode.html( text(label) );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Constructor\n\t */\n\n\t/**\n\t * Buttons constructor\n\t * @private\n\t */\n\t_constructor: function ()\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar dtSettings = dt.settings()[0];\n\t\tvar buttons = this.c.buttons;\n\n\t\tif ( ! dtSettings._buttons ) {\n\t\t\tdtSettings._buttons = [];\n\t\t}\n\n\t\tdtSettings._buttons.push( {\n\t\t\tinst: this,\n\t\t\tname: this.c.name\n\t\t} );\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.add( buttons[i] );\n\t\t}\n\n\t\tdt.on( 'destroy', function ( e, settings ) {\n\t\t\tif ( settings === dtSettings ) {\n\t\t\t\tthat.destroy();\n\t\t\t}\n\t\t} );\n\n\t\t// Global key event binding to listen for button keys\n\t\t$('body').on( 'keyup.'+this.s.namespace, function ( e ) {\n\t\t\tif ( ! document.activeElement || document.activeElement === document.body ) {\n\t\t\t\t// SUse a string of characters for fast lookup of if we need to\n\t\t\t\t// handle this\n\t\t\t\tvar character = String.fromCharCode(e.keyCode).toLowerCase();\n\n\t\t\t\tif ( that.s.listenKeys.toLowerCase().indexOf( character ) !== -1 ) {\n\t\t\t\t\tthat._keypress( character, e );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Private methods\n\t */\n\n\t/**\n\t * Add a new button to the key press listener\n\t * @param {object} conf Resolved button configuration object\n\t * @private\n\t */\n\t_addKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tthis.s.listenKeys += $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\t\t}\n\t},\n\n\t/**\n\t * Insert the buttons into the container. Call without parameters!\n\t * @param {node} [container] Recursive only - Insert point\n\t * @param {array} [buttons] Recursive only - Buttons array\n\t * @private\n\t */\n\t_draw: function ( container, buttons )\n\t{\n\t\tif ( ! container ) {\n\t\t\tcontainer = this.dom.container;\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tcontainer.children().detach();\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tcontainer.append( buttons[i].inserter );\n\t\t\tcontainer.append( ' ' );\n\n\t\t\tif ( buttons[i].buttons && buttons[i].buttons.length ) {\n\t\t\t\tthis._draw( buttons[i].collection, buttons[i].buttons );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Create buttons from an array of buttons\n\t * @param {array} attachTo Buttons array to attach to\n\t * @param {object} button Button definition\n\t * @param {boolean} inCollection true if the button is in a collection\n\t * @private\n\t */\n\t_expandButton: function ( attachTo, button, split, inCollection, inSplit, attachPoint, parentConf )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar buttonCounter = 0;\n\t\tvar isSplit = false;\n\t\tvar buttons = ! Array.isArray( button ) ?\n\t\t\t[ button ] :\n\t\t\tbutton;\n\t\t\n\t\tif(button === undefined ) {\n\t\t\tbuttons = !Array.isArray(split) ?\n\t\t\t\t[ split ] :\n\t\t\t\tsplit;\n\t\t}\n\n\t\tif (button !== undefined && button.split !== undefined) {\n\t\t\tisSplit = true;\n\t\t}\n\t\t\t\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar conf = this._resolveExtends( buttons[i] );\n\n\t\t\tif ( ! conf ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif( conf.config !== undefined && conf.config.split) {\n\t\t\t\tisSplit = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tisSplit = false;\n\t\t\t}\n\t\t\t\n\t\t\t// If the configuration is an array, then expand the buttons at this\n\t\t\t// point\n\t\t\tif ( Array.isArray( conf ) ) {\n\t\t\t\tthis._expandButton( attachTo, conf, built !== undefined && built.conf !== undefined ? built.conf.split : undefined, inCollection, parentConf !== undefined && parentConf.split !== undefined, attachPoint, parentConf );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar built = this._buildButton( conf, inCollection, conf.split !== undefined || (conf.config !== undefined && conf.config.split !== undefined), inSplit );\n\t\t\tif ( ! built ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( attachPoint !== undefined && attachPoint !== null ) {\n\t\t\t\tattachTo.splice( attachPoint, 0, built );\n\t\t\t\tattachPoint++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tattachTo.push( built );\n\t\t\t}\n\n\t\t\t\n\t\t\tif ( built.conf.buttons || built.conf.split ) {\n\t\t\t\tbuilt.collection = $('<'+(isSplit ? this.c.dom.splitCollection.tag : this.c.dom.collection.tag)+'/>');\n\n\t\t\t\tbuilt.conf._collection = built.collection;\n\n\t\t\t\tif(built.conf.split) {\n\t\t\t\t\tfor(var j = 0; j < built.conf.split.length; j++) {\n\t\t\t\t\t\tif(typeof built.conf.split[j] === \"object\") {\n\t\t\t\t\t\t\tbuilt.conf.split[j].parent = parentConf;\n\t\t\t\t\t\t\tif(built.conf.split[j].collectionLayout === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].collectionLayout = built.conf.collectionLayout;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].dropup === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].dropup = built.conf.dropup;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].fade === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].fade = built.conf.fade;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$(built.node).append($('<span class=\"dt-down-arrow\">'+this.c.dom.splitDropdown.text+'</span>'))\n\t\t\t\t}\n\n\t\t\t\tthis._expandButton( built.buttons, built.conf.buttons, built.conf.split, !isSplit, isSplit, attachPoint, built.conf );\n\t\t\t}\n\t\t\tbuilt.conf.parent = parentConf;\n\n\t\t\t// init call is made here, rather than buildButton as it needs to\n\t\t\t// be selectable, and for that it needs to be in the buttons array\n\t\t\tif ( conf.init ) {\n\t\t\t\tconf.init.call( dt.button( built.node ), dt, $(built.node), conf );\n\t\t\t}\n\n\t\t\tbuttonCounter++;\n\t\t}\n\t},\n\n\t/**\n\t * Create an individual button\n\t * @param {object} config Resolved button configuration\n\t * @param {boolean} inCollection `true` if a collection button\n\t * @return {jQuery} Created button node (jQuery)\n\t * @private\n\t */\n\t_buildButton: function ( config, inCollection, isSplit, inSplit )\n\t{\n\t\tvar buttonDom = this.c.dom.button;\n\t\tvar linerDom = this.c.dom.buttonLiner;\n\t\tvar collectionDom = this.c.dom.collection;\n\t\tvar splitDom = this.c.dom.split;\n\t\tvar splitCollectionDom = this.c.dom.splitCollection;\n\t\tvar splitDropdownButton = this.c.dom.splitDropdownButton;\n\t\tvar dt = this.s.dt;\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, button, config ) :\n\t\t\t\topt;\n\t\t};\n\n\t\t// Spacers don't do much other than insert an element into the DOM\n\t\tif (config.spacer) {\n\t\t\tvar spacer = $('<span></span>')\n\t\t\t\t.addClass('dt-button-spacer ' + config.style + ' ' + buttonDom.spacerClass)\n\t\t\t\t.html(text(config.text));\n\n\t\t\treturn {\n\t\t\t\tconf: config,\n\t\t\t\tnode: spacer,\n\t\t\t\tinserter: spacer,\n\t\t\t\tbuttons: [],\n\t\t\t\tinCollection: inCollection,\n\t\t\t\tisSplit:\t isSplit,\n\t\t\t\tinSplit:\t inSplit,\n\t\t\t\tcollection: null\n\t\t\t};\n\t\t}\n\n\t\tif ( !isSplit && inSplit && splitCollectionDom ) {\n\t\t\tbuttonDom = splitDropdownButton;\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.button ) {\n\t\t\tbuttonDom = collectionDom.button;\n\t\t} \n\n\t\tif ( !isSplit && inSplit && splitCollectionDom.buttonLiner ) {\n\t\t\tlinerDom = splitCollectionDom.buttonLiner\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.buttonLiner ) {\n\t\t\tlinerDom = collectionDom.buttonLiner;\n\t\t}\n\n\t\t// Make sure that the button is available based on whatever requirements\n\t\t// it has. For example, PDF button require pdfmake\n\t\tif ( config.available && ! config.available( dt, config ) && !config.hasOwnProperty('html') ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar button;\n\t\tif(!config.hasOwnProperty('html')) {\n\t\t\tvar action = function ( e, dt, button, config ) {\n\t\t\t\tconfig.action.call( dt.button( button ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t};\n\n\t\t\tvar tag = config.tag || buttonDom.tag;\n\t\t\tvar clickBlurs = config.clickBlurs === undefined\n\t\t\t\t? true :\n\t\t\t\tconfig.clickBlurs;\n\n\t\t\tbutton = $('<'+tag+'/>')\n\t\t\t\t.addClass( buttonDom.className )\n\t\t\t\t.addClass( inSplit ? this.c.dom.splitDropdownButton.className : '')\n\t\t\t\t.attr( 'tabindex', this.s.dt.settings()[0].iTabIndex )\n\t\t\t\t.attr( 'aria-controls', this.s.dt.table().node().id )\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\n\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t}\n\t\t\t\t\tif( clickBlurs ) {\n\t\t\t\t\t\tbutton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\n\t\t\t// Make `a` tags act like a link\n\t\t\tif ( tag.toLowerCase() === 'a' ) {\n\t\t\t\tbutton.attr( 'href', '#' );\n\t\t\t}\n\t\n\t\t\t// Button tags should have `type=button` so they don't have any default behaviour\n\t\t\tif ( tag.toLowerCase() === 'button' ) {\n\t\t\t\tbutton.attr( 'type', 'button' );\n\t\t\t}\n\t\n\t\t\tif ( linerDom.tag ) {\n\t\t\t\tvar liner = $('<'+linerDom.tag+'/>')\n\t\t\t\t\t.html( text( config.text ) )\n\t\t\t\t\t.addClass( linerDom.className );\n\t\n\t\t\t\tif ( linerDom.tag.toLowerCase() === 'a' ) {\n\t\t\t\t\tliner.attr( 'href', '#' );\n\t\t\t\t}\n\t\n\t\t\t\tbutton.append( liner );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbutton.html( text( config.text ) );\n\t\t\t}\n\t\n\t\t\tif ( config.enabled === false ) {\n\t\t\t\tbutton.addClass( buttonDom.disabled );\n\t\t\t}\n\t\n\t\t\tif ( config.className ) {\n\t\t\t\tbutton.addClass( config.className );\n\t\t\t}\n\t\n\t\t\tif ( config.titleAttr ) {\n\t\t\t\tbutton.attr( 'title', text( config.titleAttr ) );\n\t\t\t}\n\t\n\t\t\tif ( config.attr ) {\n\t\t\t\tbutton.attr( config.attr );\n\t\t\t}\n\t\n\t\t\tif ( ! config.namespace ) {\n\t\t\t\tconfig.namespace = '.dt-button-'+(_buttonCounter++);\n\t\t\t}\n\n\t\t\tif ( config.config !== undefined && config.config.split ) {\n\t\t\t\tconfig.split = config.config.split;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbutton = $(config.html)\n\t\t}\n\t\n\t\tvar buttonContainer = this.c.dom.buttonContainer;\n\t\tvar inserter;\n\t\tif ( buttonContainer && buttonContainer.tag ) {\n\t\t\tinserter = $('<'+buttonContainer.tag+'/>')\n\t\t\t\t.addClass( buttonContainer.className )\n\t\t\t\t.append( button );\n\t\t}\n\t\telse {\n\t\t\tinserter = button;\n\t\t}\n\n\t\tthis._addKey( config );\n\n\t\t// Style integration callback for DOM manipulation\n\t\t// Note that this is _not_ documented. It is currently\n\t\t// for style integration only\n\t\tif( this.c.buttonCreated ) {\n\t\t\tinserter = this.c.buttonCreated( config, inserter );\n\t\t}\n\n\t\tvar splitDiv;\n\t\tif(isSplit) {\n\t\t\tsplitDiv = $('<div/>').addClass(this.c.dom.splitWrapper.className)\n\t\t\tsplitDiv.append(button);\n\t\t\tvar dropButtonConfig = $.extend(config, {\n\t\t\t\ttext: this.c.dom.splitDropdown.text,\n\t\t\t\tclassName: this.c.dom.splitDropdown.className,\n\t\t\t\tcloseButton: false,\n\t\t\t\tattr: {\n\t\t\t\t\t'aria-haspopup': 'dialog',\n\t\t\t\t\t'aria-expanded': false\n\t\t\t\t},\n\t\t\t\talign: this.c.dom.splitDropdown.align,\n\t\t\t\tsplitAlignClass: this.c.dom.splitDropdown.splitAlignClass\n\t\t\t\t\n\t\t\t})\n\n\t\t\tthis._addKey(dropButtonConfig);\n\n\t\t\tvar splitAction = function ( e, dt, button, config ) {\n\t\t\t\t_dtButtons.split.action.call( dt.button($('div.dt-btn-split-wrapper')[0] ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t\tbutton.attr('aria-expanded', true)\n\t\t\t};\n\t\t\t\n\t\t\tvar dropButton = $('<button class=\"' + this.c.dom.splitDropdown.className + ' dt-button\"><span class=\"dt-btn-split-drop-arrow\">'+this.c.dom.splitDropdown.text+'</span></button>')\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\n\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled )) {\n\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t}\n\t\t\t\t\tif ( clickBlurs ) {\n\t\t\t\t\t\tdropButton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled ) ) {\n\t\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tif(config.split.length === 0) {\n\t\t\t\tdropButton.addClass('dtb-hide-drop');\n\t\t\t}\n\n\t\t\tsplitDiv.append(dropButton).attr(dropButtonConfig.attr);\n\t\t}\n\n\t\treturn {\n\t\t\tconf: config,\n\t\t\tnode: isSplit ? splitDiv.get(0) : button.get(0),\n\t\t\tinserter: isSplit ? splitDiv : inserter,\n\t\t\tbuttons: [],\n\t\t\tinCollection: inCollection,\n\t\t\tisSplit:\t isSplit,\n\t\t\tinSplit:\t inSplit,\n\t\t\tcollection: null\n\t\t};\n\t},\n\n\t/**\n\t * Get the button object from a node (recursive)\n\t * @param {node} node Button node\n\t * @param {array} [buttons] Button array, uses base if not defined\n\t * @return {object} Button object\n\t * @private\n\t */\n\t_nodeToButton: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons[i];\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToButton( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Get container array for a button from a button node (recursive)\n\t * @param {node} node Button node\n\t * @param {array} [buttons] Button array, uses base if not defined\n\t * @return {array} Button's host array\n\t * @private\n\t */\n\t_nodeToHost: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons;\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToHost( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handle a key press - determine if any button's key configured matches\n\t * what was typed and trigger the action if so.\n\t * @param {string} character The character pressed\n\t * @param {object} e Key event that triggered this call\n\t * @private\n\t */\n\t_keypress: function ( character, e )\n\t{\n\t\t// Check if this button press already activated on another instance of Buttons\n\t\tif ( e._buttonsHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar run = function ( conf, node ) {\n\t\t\tif ( ! conf.key ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( conf.key === character ) {\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t\telse if ( $.isPlainObject( conf.key ) ) {\n\t\t\t\tif ( conf.key.key !== character ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.shiftKey && ! e.shiftKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.altKey && ! e.altKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.ctrlKey && ! e.ctrlKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.metaKey && ! e.metaKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Made it this far - it is good\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t};\n\n\t\tvar recurse = function ( a ) {\n\t\t\tfor ( var i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\trun( a[i].conf, a[i].node );\n\n\t\t\t\tif ( a[i].buttons.length ) {\n\t\t\t\t\trecurse( a[i].buttons );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trecurse( this.s.buttons );\n\t},\n\n\t/**\n\t * Remove a key from the key listener for this instance (to be used when a\n\t * button is removed)\n\t * @param {object} conf Button configuration\n\t * @private\n\t */\n\t_removeKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tvar character = $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\n\t\t\t// Remove only one character, as multiple buttons could have the\n\t\t\t// same listening key\n\t\t\tvar a = this.s.listenKeys.split('');\n\t\t\tvar idx = $.inArray( character, a );\n\t\t\ta.splice( idx, 1 );\n\t\t\tthis.s.listenKeys = a.join('');\n\t\t}\n\t},\n\n\t/**\n\t * Resolve a button configuration\n\t * @param {string|function|object} conf Button config to resolve\n\t * @return {object} Button configuration\n\t * @private\n\t */\n\t_resolveExtends: function ( conf )\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar i, ien;\n\t\tvar toConfObject = function ( base ) {\n\t\t\tvar loop = 0;\n\n\t\t\t// Loop until we have resolved to a button configuration, or an\n\t\t\t// array of button configurations (which will be iterated\n\t\t\t// separately)\n\t\t\twhile ( ! $.isPlainObject(base) && ! Array.isArray(base) ) {\n\t\t\t\tif ( base === undefined ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( typeof base === 'function' ) {\n\t\t\t\t\tbase = base.call( that, dt, conf );\n\n\t\t\t\t\tif ( ! base ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( typeof base === 'string' ) {\n\t\t\t\t\tif ( ! _dtButtons[ base ] ) {\n\t\t\t\t\t\treturn {html: base}\n\t\t\t\t\t}\n\n\t\t\t\t\tbase = _dtButtons[ base ];\n\t\t\t\t}\n\n\t\t\t\tloop++;\n\t\t\t\tif ( loop > 30 ) {\n\t\t\t\t\t// Protect against misconfiguration killing the browser\n\t\t\t\t\tthrow 'Buttons: Too many iterations';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Array.isArray( base ) ?\n\t\t\t\tbase :\n\t\t\t\t$.extend( {}, base );\n\t\t};\n\n\t\tconf = toConfObject( conf );\n\n\t\twhile ( conf && conf.extend ) {\n\t\t\t// Use `toConfObject` in case the button definition being extended\n\t\t\t// is itself a string or a function\n\t\t\tif ( ! _dtButtons[ conf.extend ] ) {\n\t\t\t\tthrow 'Cannot extend unknown button type: '+conf.extend;\n\t\t\t}\n\n\t\t\tvar objArray = toConfObject( _dtButtons[ conf.extend ] );\n\t\t\tif ( Array.isArray( objArray ) ) {\n\t\t\t\treturn objArray;\n\t\t\t}\n\t\t\telse if ( ! objArray ) {\n\t\t\t\t// This is a little brutal as it might be possible to have a\n\t\t\t\t// valid button without the extend, but if there is no extend\n\t\t\t\t// then the host button would be acting in an undefined state\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Stash the current class name\n\t\t\tvar originalClassName = objArray.className;\n\n\t\t\tif (conf.config !== undefined && objArray.config !== undefined) {\n\t\t\t\tconf.config = $.extend({}, objArray.config, conf.config)\n\t\t\t}\n\n\t\t\tconf = $.extend( {}, objArray, conf );\n\n\t\t\t// The extend will have overwritten the original class name if the\n\t\t\t// `conf` object also assigned a class, but we want to concatenate\n\t\t\t// them so they are list that is combined from all extended buttons\n\t\t\tif ( originalClassName && conf.className !== originalClassName ) {\n\t\t\t\tconf.className = originalClassName+' '+conf.className;\n\t\t\t}\n\n\t\t\t// Buttons to be added to a collection -gives the ability to define\n\t\t\t// if buttons should be added to the start or end of a collection\n\t\t\tvar postfixButtons = conf.postfixButtons;\n\t\t\tif ( postfixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=postfixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.push( postfixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.postfixButtons = null;\n\t\t\t}\n\n\t\t\tvar prefixButtons = conf.prefixButtons;\n\t\t\tif ( prefixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=prefixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.splice( i, 0, prefixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.prefixButtons = null;\n\t\t\t}\n\n\t\t\t// Although we want the `conf` object to overwrite almost all of\n\t\t\t// the properties of the object being extended, the `extend`\n\t\t\t// property should come from the object being extended\n\t\t\tconf.extend = objArray.extend;\n\t\t}\n\n\t\treturn conf;\n\t},\n\n\t/**\n\t * Display (and replace if there is an existing one) a popover attached to a button\n\t * @param {string|node} content Content to show\n\t * @param {DataTable.Api} hostButton DT API instance of the button\n\t * @param {object} inOpts Options (see object below for all options)\n\t */\n\t_popover: function ( content, hostButton, inOpts, e ) {\n\t\tvar dt = hostButton;\n\t\tvar buttonsSettings = this.c;\n\t\tvar closed = false;\n\t\tvar options = $.extend( {\n\t\t\talign: 'button-left', // button-right, dt-container, split-left, split-right\n\t\t\tautoClose: false,\n\t\t\tbackground: true,\n\t\t\tbackgroundClassName: 'dt-button-background',\n\t\t\tcloseButton: true,\n\t\t\tcontentClassName: buttonsSettings.dom.collection.className,\n\t\t\tcollectionLayout: '',\n\t\t\tcollectionTitle: '',\n\t\t\tdropup: false,\n\t\t\tfade: 400,\n\t\t\tpopoverTitle: '',\n\t\t\trightAlignClassName: 'dt-button-right',\n\t\t\ttag: buttonsSettings.dom.collection.tag\n\t\t}, inOpts );\n\n\t\tvar hostNode = hostButton.node();\n\n\t\tvar close = function () {\n\t\t\tclosed = true;\n\n\t\t\t_fadeOut(\n\t\t\t\t$('.dt-button-collection'),\n\t\t\t\toptions.fade,\n\t\t\t\tfunction () {\n\t\t\t\t\t$(this).detach();\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t$(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes())\n\t\t\t\t.attr('aria-expanded', 'false');\n\n\t\t\t$('div.dt-button-background').off( 'click.dtb-collection' );\n\t\t\tButtons.background( false, options.backgroundClassName, options.fade, hostNode );\n\n\t\t\t$(window).off('resize.resize.dtb-collection');\n\t\t\t$('body').off( '.dtb-collection' );\n\t\t\tdt.off( 'buttons-action.b-internal' );\n\t\t\tdt.off( 'destroy' );\n\t\t};\n\n\t\tif (content === false) {\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tvar existingExpanded = $(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes());\n\t\tif ( existingExpanded.length ) {\n\t\t\t// Reuse the current position if the button that was triggered is inside an existing collection\n\t\t\tif (hostNode.closest('div.dt-button-collection').length) {\n\t\t\t\thostNode = existingExpanded.eq(0);\n\t\t\t}\n\n\t\t\tclose();\n\t\t}\n\n\t\t// Try to be smart about the layout\n\t\tvar cnt = $('.dt-button', content).length;\n\t\tvar mod = '';\n\n\t\tif (cnt === 3) {\n\t\t\tmod = 'dtb-b3';\n\t\t}\n\t\telse if (cnt === 2) {\n\t\t\tmod = 'dtb-b2';\n\t\t}\n\t\telse if (cnt === 1) {\n\t\t\tmod = 'dtb-b1';\n\t\t}\n\n\t\tvar display = $('<div/>')\n\t\t\t.addClass('dt-button-collection')\n\t\t\t.addClass(options.collectionLayout)\n\t\t\t.addClass(options.splitAlignClass)\n\t\t\t.addClass(mod)\n\t\t\t.css('display', 'none')\n\t\t\t.attr({\n\t\t\t\t'aria-modal': true,\n\t\t\t\trole: 'dialog'\n\t\t\t});\n\n\t\tcontent = $(content)\n\t\t\t.addClass(options.contentClassName)\n\t\t\t.attr('role', 'menu')\n\t\t\t.appendTo(display);\n\n\t\thostNode.attr( 'aria-expanded', 'true' );\n\n\t\tif ( hostNode.parents('body')[0] !== document.body ) {\n\t\t\thostNode = document.body.lastChild;\n\t\t}\n\n\t\tif ( options.popoverTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.popoverTitle+'</div>');\n\t\t}\n\t\telse if ( options.collectionTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.collectionTitle+'</div>');\n\t\t}\n\n\t\tif (options.closeButton) {\n\t\t\tdisplay.prepend('<div class=\"dtb-popover-close\">x</div>').addClass('dtb-collection-closeable')\n\t\t}\n\n\t\t_fadeIn( display.insertAfter( hostNode ), options.fade );\n\n\t\tvar tableContainer = $( hostButton.table().container() );\n\t\tvar position = display.css( 'position' );\n\n\t\tif ( options.span === 'container' || options.align === 'dt-container' ) {\n\t\t\thostNode = hostNode.parent();\n\t\t\tdisplay.css('width', tableContainer.width());\n\t\t}\n\n\t\t// Align the popover relative to the DataTables container\n\t\t// Useful for wide popovers such as SearchPanes\n\t\tif (position === 'absolute') {\n\t\t\t// Align relative to the host button\n\t\t\tvar offsetParent = $(hostNode[0].offsetParent);\n\t\t\tvar buttonPosition = hostNode.position();\n\t\t\tvar buttonOffset = hostNode.offset();\n\t\t\tvar tableSizes = offsetParent.offset();\n\t\t\tvar containerPosition = offsetParent.position();\n\t\t\tvar computed = window.getComputedStyle(offsetParent[0]);\n\n\t\t\ttableSizes.height = offsetParent.outerHeight();\n\t\t\ttableSizes.width = offsetParent.width() + parseFloat(computed.paddingLeft);\n\t\t\ttableSizes.right = tableSizes.left + tableSizes.width;\n\t\t\ttableSizes.bottom = tableSizes.top + tableSizes.height;\n\n\t\t\t// Set the initial position so we can read height / width\n\t\t\tvar top = buttonPosition.top + hostNode.outerHeight();\n\t\t\tvar left = buttonPosition.left;\n\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\n\t\t\t// Get the popover position\n\t\t\tcomputed = window.getComputedStyle(display[0]);\n\t\t\tvar popoverSizes = display.offset();\n\n\t\t\tpopoverSizes.height = display.outerHeight();\n\t\t\tpopoverSizes.width = display.outerWidth();\n\t\t\tpopoverSizes.right = popoverSizes.left + popoverSizes.width;\n\t\t\tpopoverSizes.bottom = popoverSizes.top + popoverSizes.height;\n\t\t\tpopoverSizes.marginTop = parseFloat(computed.marginTop);\n\t\t\tpopoverSizes.marginBottom = parseFloat(computed.marginBottom);\n\n\t\t\t// First position per the class requirements - pop up and right align\n\t\t\tif (options.dropup) {\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (options.align === 'button-right' || display.hasClass( options.rightAlignClassName )) {\n\t\t\t\tleft = buttonPosition.left - popoverSizes.width + hostNode.outerWidth(); \n\t\t\t}\n\n\t\t\t// Container alignment - make sure it doesn't overflow the table container\n\t\t\tif (options.align === 'dt-container' || options.align === 'container') {\n\t\t\t\tif (left < buttonPosition.left) {\n\t\t\t\t\tleft = -buttonPosition.left;\n\t\t\t\t}\n\n\t\t\t\tif (left + popoverSizes.width > tableSizes.width) {\n\t\t\t\t\tleft = tableSizes.width - popoverSizes.width;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Window adjustment\n\t\t\tif (containerPosition.left + left + popoverSizes.width > $(window).width()) {\n\t\t\t\t// Overflowing the document to the right\n\t\t\t\tleft = $(window).width() - popoverSizes.width - containerPosition.left;\n\t\t\t}\n\n\t\t\tif (buttonOffset.left + left < 0) {\n\t\t\t\t// Off to the left of the document\n\t\t\t\tleft = -buttonOffset.left;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top + popoverSizes.height > $(window).height() + $(window).scrollTop()) {\n\t\t\t\t// Pop up if otherwise we'd need the user to scroll down\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top < $(window).scrollTop()) {\n\t\t\t\t// Correction for when the top is beyond the top of the page\n\t\t\t\ttop = buttonPosition.top + hostNode.outerHeight();\n\t\t\t}\n\n\t\t\t// Calculations all done - now set it\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\t\t}\n\t\telse {\n\t\t\t// Fix position - centre on screen\n\t\t\tvar position = function () {\n\t\t\t\tvar half = $(window).height() / 2;\n\n\t\t\t\tvar top = display.height() / 2;\n\t\t\t\tif ( top > half ) {\n\t\t\t\t\ttop = half;\n\t\t\t\t}\n\n\t\t\t\tdisplay.css( 'marginTop', top*-1 );\n\t\t\t};\n\n\t\t\tposition();\n\n\t\t\t$(window).on('resize.dtb-collection', function () {\n\t\t\t\tposition();\n\t\t\t});\n\t\t}\n\n\t\tif ( options.background ) {\n\t\t\tButtons.background(\n\t\t\t\ttrue,\n\t\t\t\toptions.backgroundClassName,\n\t\t\t\toptions.fade,\n\t\t\t\toptions.backgroundHost || hostNode\n\t\t\t);\n\t\t}\n\n\t\t// This is bonkers, but if we don't have a click listener on the\n\t\t// background element, iOS Safari will ignore the body click\n\t\t// listener below. An empty function here is all that is\n\t\t// required to make it work...\n\t\t$('div.dt-button-background').on( 'click.dtb-collection', function () {} );\n\n\t\tif ( options.autoClose ) {\n\t\t\tsetTimeout( function () {\n\t\t\t\tdt.on( 'buttons-action.b-internal', function (e, btn, dt, node) {\n\t\t\t\t\tif ( node[0] === hostNode[0] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclose();\n\t\t\t\t} );\n\t\t\t}, 0);\n\t\t}\n\t\t\n\t\t$(display).trigger('buttons-popover.dt');\n\n\n\t\tdt.on('destroy', close);\n\n\t\tsetTimeout(function() {\n\t\t\tclosed = false;\n\t\t\t$('body')\n\t\t\t\t.on( 'click.dtb-collection', function (e) {\n\t\t\t\t\tif (closed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// andSelf is deprecated in jQ1.8, but we want 1.7 compat\n\t\t\t\t\tvar back = $.fn.addBack ? 'addBack' : 'andSelf';\n\t\t\t\t\tvar parent = $(e.target).parent()[0];\n\t\n\t\t\t\t\tif (( ! $(e.target).parents()[back]().filter( content ).length && !$(parent).hasClass('dt-buttons')) || $(e.target).hasClass('dt-button-background')) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keyup.dtb-collection', function (e) {\n\t\t\t\t\tif ( e.keyCode === 27 ) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keydown.dtb-collection', function (e) {\n\t\t\t\t\t// Focus trap for tab key\n\t\t\t\t\tvar elements = $('a, button', content);\n\t\t\t\t\tvar active = document.activeElement;\n\n\t\t\t\t\tif (e.keyCode !== 9) { // tab\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (elements.index(active) === -1) {\n\t\t\t\t\t\t// If current focus is not inside the popover\n\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.shiftKey) {\n\t\t\t\t\t\t// Reverse tabbing order when shift key is pressed\n\t\t\t\t\t\tif (active === elements[0]) {\n\t\t\t\t\t\t\telements.last().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (active === elements.last()[0]) {\n\t\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, 0);\n\t}\n} );\n\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Statics\n */\n\n/**\n * Show / hide a background layer behind a collection\n * @param {boolean} Flag to indicate if the background should be shown or\n * hidden \n * @param {string} Class to assign to the background\n * @static\n */\nButtons.background = function ( show, className, fade, insertPoint ) {\n\tif ( fade === undefined ) {\n\t\tfade = 400;\n\t}\n\tif ( ! insertPoint ) {\n\t\tinsertPoint = document.body;\n\t}\n\n\tif ( show ) {\n\t\t_fadeIn(\n\t\t\t$('<div/>')\n\t\t\t\t.addClass( className )\n\t\t\t\t.css( 'display', 'none' )\n\t\t\t\t.insertAfter( insertPoint ),\n\t\t\tfade\n\t\t);\n\t}\n\telse {\n\t\t_fadeOut(\n\t\t\t$('div.'+className),\n\t\t\tfade,\n\t\t\tfunction () {\n\t\t\t\t$(this)\n\t\t\t\t\t.removeClass( className )\n\t\t\t\t\t.remove();\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Instance selector - select Buttons instances based on an instance selector\n * value from the buttons assigned to a DataTable. This is only useful if\n * multiple instances are attached to a DataTable.\n * @param {string|int|array} Instance selector - see `instance-selector`\n * documentation on the DataTables site\n * @param {array} Button instance array that was attached to the DataTables\n * settings object\n * @return {array} Buttons instances\n * @static\n */\nButtons.instanceSelector = function ( group, buttons )\n{\n\tif ( group === undefined || group === null ) {\n\t\treturn $.map( buttons, function ( v ) {\n\t\t\treturn v.inst;\n\t\t} );\n\t}\n\n\tvar ret = [];\n\tvar names = $.map( buttons, function ( v ) {\n\t\treturn v.name;\n\t} );\n\n\t// Flatten the group selector into an array of single options\n\tvar process = function ( input ) {\n\t\tif ( Array.isArray( input ) ) {\n\t\t\tfor ( var i=0, ien=input.length ; i<ien ; i++ ) {\n\t\t\t\tprocess( input[i] );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( typeof input === 'string' ) {\n\t\t\tif ( input.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// String selector, list of names\n\t\t\t\tprocess( input.split(',') );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// String selector individual name\n\t\t\t\tvar idx = $.inArray( input.trim(), names );\n\n\t\t\t\tif ( idx !== -1 ) {\n\t\t\t\t\tret.push( buttons[ idx ].inst );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ( typeof input === 'number' ) {\n\t\t\t// Index selector\n\t\t\tret.push( buttons[ input ].inst );\n\t\t}\n\t\telse if ( typeof input === 'object' ) {\n\t\t\t// Actual instance selector\n\t\t\tret.push( input );\n\t\t}\n\t};\n\t\n\tprocess( group );\n\n\treturn ret;\n};\n\n/**\n * Button selector - select one or more buttons from a selector input so some\n * operation can be performed on them.\n * @param {array} Button instances array that the selector should operate on\n * @param {string|int|node|jQuery|array} Button selector - see\n * `button-selector` documentation on the DataTables site\n * @return {array} Array of objects containing `inst` and `idx` properties of\n * the selected buttons so you know which instance each button belongs to.\n * @static\n */\nButtons.buttonSelector = function ( insts, selector )\n{\n\tvar ret = [];\n\tvar nodeBuilder = function ( a, buttons, baseIdx ) {\n\t\tvar button;\n\t\tvar idx;\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tbutton = buttons[i];\n\n\t\t\tif ( button ) {\n\t\t\t\tidx = baseIdx !== undefined ?\n\t\t\t\t\tbaseIdx+i :\n\t\t\t\t\ti+'';\n\n\t\t\t\ta.push( {\n\t\t\t\t\tnode: button.node,\n\t\t\t\t\tname: button.conf.name,\n\t\t\t\t\tidx: idx\n\t\t\t\t} );\n\n\t\t\t\tif ( button.buttons ) {\n\t\t\t\t\tnodeBuilder( a, button.buttons, idx+'-' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tvar run = function ( selector, inst ) {\n\t\tvar i, ien;\n\t\tvar buttons = [];\n\t\tnodeBuilder( buttons, inst.s.buttons );\n\n\t\tvar nodes = $.map( buttons, function (v) {\n\t\t\treturn v.node;\n\t\t} );\n\n\t\tif ( Array.isArray( selector ) || selector instanceof $ ) {\n\t\t\tfor ( i=0, ien=selector.length ; i<ien ; i++ ) {\n\t\t\t\trun( selector[i], inst );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( selector === null || selector === undefined || selector === '*' ) {\n\t\t\t// Select all\n\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'number' ) {\n\t\t\t// Main button index selector\n\t\t\tif (inst.s.buttons[ selector ]) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: inst.s.buttons[ selector ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'string' ) {\n\t\t\tif ( selector.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// Split\n\t\t\t\tvar a = selector.split(',');\n\n\t\t\t\tfor ( i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\t\trun( a[i].trim(), inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( selector.match( /^\\d+(\\-\\d+)*$/ ) ) {\n\t\t\t\t// Sub-button index selector\n\t\t\t\tvar indexes = $.map( buttons, function (v) {\n\t\t\t\t\treturn v.idx;\n\t\t\t\t} );\n\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[ $.inArray( selector, indexes ) ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t\telse if ( selector.indexOf( ':name' ) !== -1 ) {\n\t\t\t\t// Button name selector\n\t\t\t\tvar name = selector.replace( ':name', '' );\n\n\t\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\t\tif ( buttons[i].name === name ) {\n\t\t\t\t\t\tret.push( {\n\t\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// jQuery selector on the nodes\n\t\t\t\t$( nodes ).filter( selector ).each( function () {\n\t\t\t\t\tret.push( {\n\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\tnode: this\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'object' && selector.nodeName ) {\n\t\t\t// Node selector\n\t\t\tvar idx = $.inArray( selector, nodes );\n\n\t\t\tif ( idx !== -1 ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: nodes[ idx ]\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\n\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\tvar inst = insts[i];\n\n\t\trun( selector, inst );\n\t}\n\n\treturn ret;\n};\n\n/**\n * Default function used for formatting output data.\n * @param {*} str Data to strip\n */\nButtons.stripData = function ( str, config ) {\n\tif ( typeof str !== 'string' ) {\n\t\treturn str;\n\t}\n\n\t// Always remove script tags\n\tstr = str.replace( /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '' );\n\n\t// Always remove comments\n\tstr = str.replace( /<!\\-\\-.*?\\-\\->/g, '' );\n\n\tif ( ! config || config.stripHtml ) {\n\t\tstr = str.replace( /<[^>]*>/g, '' );\n\t}\n\n\tif ( ! config || config.trim ) {\n\t\tstr = str.replace( /^\\s+|\\s+$/g, '' );\n\t}\n\n\tif ( ! config || config.stripNewlines ) {\n\t\tstr = str.replace( /\\n/g, ' ' );\n\t}\n\n\tif ( ! config || config.decodeEntities ) {\n\t\t_exportTextarea.innerHTML = str;\n\t\tstr = _exportTextarea.value;\n\t}\n\n\treturn str;\n};\n\n\n/**\n * Buttons defaults. For full documentation, please refer to the docs/option\n * directory or the DataTables site.\n * @type {Object}\n * @static\n */\nButtons.defaults = {\n\tbuttons: [ 'copy', 'excel', 'csv', 'pdf', 'print' ],\n\tname: 'main',\n\ttabIndex: 0,\n\tdom: {\n\t\tcontainer: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-buttons'\n\t\t},\n\t\tcollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: ''\n\t\t},\n\t\tbutton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-button',\n\t\t\tactive: 'active',\n\t\t\tdisabled: 'disabled',\n\t\t\tspacerClass: ''\n\t\t},\n\t\tbuttonLiner: {\n\t\t\ttag: 'span',\n\t\t\tclassName: ''\n\t\t},\n\t\tsplit: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split',\n\t\t},\n\t\tsplitWrapper: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-btn-split-wrapper',\n\t\t},\n\t\tsplitDropdown: {\n\t\t\ttag: 'button',\n\t\t\ttext: '▼',\n\t\t\tclassName: 'dt-btn-split-drop',\n\t\t\talign: 'split-right',\n\t\t\tsplitAlignClass: 'dt-button-split-left'\n\t\t},\n\t\tsplitDropdownButton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-btn-split-drop-button dt-button',\n\t\t},\n\t\tsplitCollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split-collection',\n\t\t}\n\t}\n};\n\n/**\n * Version information\n * @type {string}\n * @static\n */\nButtons.version = '2.2.3';\n\n\n$.extend( _dtButtons, {\n\tcollection: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.collection', 'Collection' );\n\t\t},\n\t\tclassName: 'buttons-collection',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\tbutton.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tif ( config._collection.parents('body').length ) {\n\t\t\t\tthis.popover(false, config);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.popover(config._collection, config);\n\t\t\t}\n\n\t\t\t// When activated using a key - auto focus on the\n\t\t\t// first item in the popover\n\t\t\tif (e.type === 'keypress') {\n\t\t\t\t$('a, button', config._collection).eq(0).focus();\n\t\t\t}\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tsplit: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.split', 'Split' );\n\t\t},\n\t\tclassName: 'buttons-split',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\treturn button.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tthis.popover(config._collection, config);\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tcopy: function ( dt, conf ) {\n\t\tif ( _dtButtons.copyHtml5 ) {\n\t\t\treturn 'copyHtml5';\n\t\t}\n\t},\n\tcsv: function ( dt, conf ) {\n\t\tif ( _dtButtons.csvHtml5 && _dtButtons.csvHtml5.available( dt, conf ) ) {\n\t\t\treturn 'csvHtml5';\n\t\t}\n\t},\n\texcel: function ( dt, conf ) {\n\t\tif ( _dtButtons.excelHtml5 && _dtButtons.excelHtml5.available( dt, conf ) ) {\n\t\t\treturn 'excelHtml5';\n\t\t}\n\t},\n\tpdf: function ( dt, conf ) {\n\t\tif ( _dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available( dt, conf ) ) {\n\t\t\treturn 'pdfHtml5';\n\t\t}\n\t},\n\tpageLength: function ( dt ) {\n\t\tvar lengthMenu = dt.settings()[0].aLengthMenu;\n\t\tvar vals = [];\n\t\tvar lang = [];\n\t\tvar text = function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.pageLength', {\n\t\t\t\t\"-1\": 'Show all rows',\n\t\t\t\t_: 'Show %d rows'\n\t\t\t}, dt.page.len() );\n\t\t};\n\n\t\t// Support for DataTables 1.x 2D array\n\t\tif (Array.isArray( lengthMenu[0] )) {\n\t\t\tvals = lengthMenu[0];\n\t\t\tlang = lengthMenu[1];\n\t\t}\n\t\telse {\n\t\t\tfor (var i=0 ; i<lengthMenu.length ; i++) {\n\t\t\t\tvar option = lengthMenu[i];\n\n\t\t\t\t// Support for DataTables 2 object in the array\n\t\t\t\tif ($.isPlainObject(option)) {\n\t\t\t\t\tvals.push(option.value);\n\t\t\t\t\tlang.push(option.label);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvals.push(option);\n\t\t\t\t\tlang.push(option);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\textend: 'collection',\n\t\t\ttext: text,\n\t\t\tclassName: 'buttons-page-length',\n\t\t\tautoClose: true,\n\t\t\tbuttons: $.map( vals, function ( val, i ) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: lang[i],\n\t\t\t\t\tclassName: 'button-page-length',\n\t\t\t\t\taction: function ( e, dt ) {\n\t\t\t\t\t\tdt.page.len( val ).draw();\n\t\t\t\t\t},\n\t\t\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\t\t\tvar that = this;\n\t\t\t\t\t\tvar fn = function () {\n\t\t\t\t\t\t\tthat.active( dt.page.len() === val );\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tdt.on( 'length.dt'+conf.namespace, fn );\n\t\t\t\t\t\tfn();\n\t\t\t\t\t},\n\t\t\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} ),\n\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\tvar that = this;\n\t\t\t\tdt.on( 'length.dt'+conf.namespace, function () {\n\t\t\t\t\tthat.text( conf.text );\n\t\t\t\t} );\n\t\t\t},\n\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t}\n\t\t};\n\t},\n\tspacer: {\n\t\tstyle: 'empty',\n\t\tspacer: true,\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.spacer', '' );\n\t\t}\n\t}\n} );\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables API\n *\n * For complete documentation, please refer to the docs/api directory or the\n * DataTables site\n */\n\n// Buttons group and individual button selector\nDataTable.Api.register( 'buttons()', function ( group, selector ) {\n\t// Argument shifting\n\tif ( selector === undefined ) {\n\t\tselector = group;\n\t\tgroup = undefined;\n\t}\n\n\tthis.selector.buttonGroup = group;\n\n\tvar res = this.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\treturn Buttons.buttonSelector(\n\t\t\t\tButtons.instanceSelector( group, ctx._buttons ),\n\t\t\t\tselector\n\t\t\t);\n\t\t}\n\t}, true );\n\n\tres._groupSelector = group;\n\treturn res;\n} );\n\n// Individual button selector\nDataTable.Api.register( 'button()', function ( group, selector ) {\n\t// just run buttons() and truncate\n\tvar buttons = this.buttons( group, selector );\n\n\tif ( buttons.length > 1 ) {\n\t\tbuttons.splice( 1, buttons.length );\n\t}\n\n\treturn buttons;\n} );\n\n// Active buttons\nDataTable.Api.registerPlural( 'buttons().active()', 'button().active()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.active( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.active( set.node, flag );\n\t} );\n} );\n\n// Get / set button action\nDataTable.Api.registerPlural( 'buttons().action()', 'button().action()', function ( action ) {\n\tif ( action === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.action( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.action( set.node, action );\n\t} );\n} );\n\n// Collection control\nDataTable.Api.registerPlural( 'buttons().collectionRebuild()', 'button().collectionRebuild()', function ( buttons ) {\n\treturn this.each( function ( set ) {\n\t\tfor(var i = 0; i < buttons.length; i++) {\n\t\t\tif(typeof buttons[i] === 'object') {\n\t\t\t\tbuttons[i].parentConf = set;\n\t\t\t}\n\t\t}\n\t\tset.inst.collectionRebuild( set.node, buttons );\n\t} );\n} );\n\n// Enable / disable buttons\nDataTable.Api.register( ['buttons().enable()', 'button().enable()'], function ( flag ) {\n\treturn this.each( function ( set ) {\n\t\tset.inst.enable( set.node, flag );\n\t} );\n} );\n\n// Disable buttons\nDataTable.Api.register( ['buttons().disable()', 'button().disable()'], function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.disable( set.node );\n\t} );\n} );\n\n// Button index\nDataTable.Api.register( 'button().index()', function () {\n\tvar idx = null;\n\n\tthis.each( function ( set ) {\n\t\tvar res = set.inst.index( set.node );\n\n\t\tif (res !== null) {\n\t\t\tidx = res;\n\t\t}\n\t} );\n\n\treturn idx;\n} );\n\n// Get button nodes\nDataTable.Api.registerPlural( 'buttons().nodes()', 'button().node()', function () {\n\tvar jq = $();\n\n\t// jQuery will automatically reduce duplicates to a single entry\n\t$( this.each( function ( set ) {\n\t\tjq = jq.add( set.inst.node( set.node ) );\n\t} ) );\n\n\treturn jq;\n} );\n\n// Get / set button processing state\nDataTable.Api.registerPlural( 'buttons().processing()', 'button().processing()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.processing( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.processing( set.node, flag );\n\t} );\n} );\n\n// Get / set button text (i.e. the button labels)\nDataTable.Api.registerPlural( 'buttons().text()', 'button().text()', function ( label ) {\n\tif ( label === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.text( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.text( set.node, label );\n\t} );\n} );\n\n// Trigger a button's action\nDataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.node( set.node ).trigger( 'click' );\n\t} );\n} );\n\n// Button resolver to the popover\nDataTable.Api.register( 'button().popover()', function (content, options) {\n\treturn this.map( function ( set ) {\n\t\treturn set.inst._popover( content, this.button(this[0].node), options );\n\t} );\n} );\n\n// Get the container elements\nDataTable.Api.register( 'buttons().containers()', function () {\n\tvar jq = $();\n\tvar groupSelector = this._groupSelector;\n\n\t// We need to use the group selector directly, since if there are no buttons\n\t// the result set will be empty\n\tthis.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\tvar insts = Buttons.instanceSelector( groupSelector, ctx._buttons );\n\n\t\t\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\t\t\tjq = jq.add( insts[i].container() );\n\t\t\t}\n\t\t}\n\t} );\n\n\treturn jq;\n} );\n\nDataTable.Api.register( 'buttons().container()', function () {\n\t// API level of nesting is `buttons()` so we can zip into the containers method\n\treturn this.containers().eq(0);\n} );\n\n// Add a new button\nDataTable.Api.register( 'button().add()', function ( idx, conf, draw ) {\n\tvar ctx = this.context;\n\n\t// Don't use `this` as it could be empty - select the instances directly\n\tif ( ctx.length ) {\n\t\tvar inst = Buttons.instanceSelector( this._groupSelector, ctx[0]._buttons );\n\n\t\tif ( inst.length ) {\n\t\t\tinst[0].add( conf, idx , draw);\n\t\t}\n\t}\n\n\treturn this.button( this._groupSelector, idx );\n} );\n\n// Destroy the button sets selected\nDataTable.Api.register( 'buttons().destroy()', function () {\n\tthis.pluck( 'inst' ).unique().each( function ( inst ) {\n\t\tinst.destroy();\n\t} );\n\n\treturn this;\n} );\n\n// Remove a button\nDataTable.Api.registerPlural( 'buttons().remove()', 'buttons().remove()', function () {\n\tthis.each( function ( set ) {\n\t\tset.inst.remove( set.node );\n\t} );\n\n\treturn this;\n} );\n\n// Information box that can be used by buttons\nvar _infoTimer;\nDataTable.Api.register( 'buttons.info()', function ( title, message, time ) {\n\tvar that = this;\n\n\tif ( title === false ) {\n\t\tthis.off('destroy.btn-info');\n\t\t_fadeOut(\n\t\t\t$('#datatables_buttons_info'),\n\t\t\t400,\n\t\t\tfunction () {\n\t\t\t\t$(this).remove();\n\t\t\t}\n\t\t);\n\t\tclearTimeout( _infoTimer );\n\t\t_infoTimer = null;\n\n\t\treturn this;\n\t}\n\n\tif ( _infoTimer ) {\n\t\tclearTimeout( _infoTimer );\n\t}\n\n\tif ( $('#datatables_buttons_info').length ) {\n\t\t$('#datatables_buttons_info').remove();\n\t}\n\n\ttitle = title ? '<h2>'+title+'</h2>' : '';\n\n\t_fadeIn(\n\t\t$('<div id=\"datatables_buttons_info\" class=\"dt-button-info\"/>')\n\t\t\t.html( title )\n\t\t\t.append( $('<div/>')[ typeof message === 'string' ? 'html' : 'append' ]( message ) )\n\t\t\t.css( 'display', 'none' )\n\t\t\t.appendTo( 'body' )\n\t);\n\n\tif ( time !== undefined && time !== 0 ) {\n\t\t_infoTimer = setTimeout( function () {\n\t\t\tthat.buttons.info( false );\n\t\t}, time );\n\t}\n\n\tthis.on('destroy.btn-info', function () {\n\t\tthat.buttons.info(false);\n\t});\n\n\treturn this;\n} );\n\n// Get data from the table for export - this is common to a number of plug-in\n// buttons so it is included in the Buttons core library\nDataTable.Api.register( 'buttons.exportData()', function ( options ) {\n\tif ( this.context.length ) {\n\t\treturn _exportData( new DataTable.Api( this.context[0] ), options );\n\t}\n} );\n\n// Get information about the export that is common to many of the export data\n// types (DRY)\nDataTable.Api.register( 'buttons.exportInfo()', function ( conf ) {\n\tif ( ! conf ) {\n\t\tconf = {};\n\t}\n\n\treturn {\n\t\tfilename: _filename( conf ),\n\t\ttitle: _title( conf ),\n\t\tmessageTop: _message(this, conf.message || conf.messageTop, 'top'),\n\t\tmessageBottom: _message(this, conf.messageBottom, 'bottom')\n\t};\n} );\n\n\n\n/**\n * Get the file name for an exported file.\n *\n * @param {object}\tconfig Button configuration\n * @param {boolean} incExtension Include the file name extension\n */\nvar _filename = function ( config )\n{\n\t// Backwards compatibility\n\tvar filename = config.filename === '*' && config.title !== '*' && config.title !== undefined && config.title !== null && config.title !== '' ?\n\t\tconfig.title :\n\t\tconfig.filename;\n\n\tif ( typeof filename === 'function' ) {\n\t\tfilename = filename();\n\t}\n\n\tif ( filename === undefined || filename === null ) {\n\t\treturn null;\n\t}\n\n\tif ( filename.indexOf( '*' ) !== -1 ) {\n\t\tfilename = filename.replace( '*', $('head > title').text() ).trim();\n\t}\n\n\t// Strip characters which the OS will object to\n\tfilename = filename.replace(/[^a-zA-Z0-9_\\u00A1-\\uFFFF\\.,\\-_ !\\(\\)]/g, \"\");\n\n\tvar extension = _stringOrFunction( config.extension );\n\tif ( ! extension ) {\n\t\textension = '';\n\t}\n\n\treturn filename + extension;\n};\n\n/**\n * Simply utility method to allow parameters to be given as a function\n *\n * @param {undefined|string|function} option Option\n * @return {null|string} Resolved value\n */\nvar _stringOrFunction = function ( option )\n{\n\tif ( option === null || option === undefined ) {\n\t\treturn null;\n\t}\n\telse if ( typeof option === 'function' ) {\n\t\treturn option();\n\t}\n\treturn option;\n};\n\n/**\n * Get the title for an exported file.\n *\n * @param {object} config\tButton configuration\n */\nvar _title = function ( config )\n{\n\tvar title = _stringOrFunction( config.title );\n\n\treturn title === null ?\n\t\tnull : title.indexOf( '*' ) !== -1 ?\n\t\t\ttitle.replace( '*', $('head > title').text() || 'Exported data' ) :\n\t\t\ttitle;\n};\n\nvar _message = function ( dt, option, position )\n{\n\tvar message = _stringOrFunction( option );\n\tif ( message === null ) {\n\t\treturn null;\n\t}\n\n\tvar caption = $('caption', dt.table().container()).eq(0);\n\tif ( message === '*' ) {\n\t\tvar side = caption.css( 'caption-side' );\n\t\tif ( side !== position ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn caption.length ?\n\t\t\tcaption.text() :\n\t\t\t'';\n\t}\n\n\treturn message;\n};\n\n\n\n\nvar _exportTextarea = $('<textarea/>')[0];\nvar _exportData = function ( dt, inOpts )\n{\n\tvar config = $.extend( true, {}, {\n\t\trows: null,\n\t\tcolumns: '',\n\t\tmodifier: {\n\t\t\tsearch: 'applied',\n\t\t\torder: 'applied'\n\t\t},\n\t\torthogonal: 'display',\n\t\tstripHtml: true,\n\t\tstripNewlines: true,\n\t\tdecodeEntities: true,\n\t\ttrim: true,\n\t\tformat: {\n\t\t\theader: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tfooter: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tbody: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t}\n\t\t},\n\t\tcustomizeData: null\n\t}, inOpts );\n\n\tvar header = dt.columns( config.columns ).indexes().map( function (idx) {\n\t\tvar el = dt.column( idx ).header();\n\t\treturn config.format.header( el.innerHTML, idx, el );\n\t} ).toArray();\n\n\tvar footer = dt.table().footer() ?\n\t\tdt.columns( config.columns ).indexes().map( function (idx) {\n\t\t\tvar el = dt.column( idx ).footer();\n\t\t\treturn config.format.footer( el ? el.innerHTML : '', idx, el );\n\t\t} ).toArray() :\n\t\tnull;\n\t\n\t// If Select is available on this table, and any rows are selected, limit the export\n\t// to the selected rows. If no rows are selected, all rows will be exported. Specify\n\t// a `selected` modifier to control directly.\n\tvar modifier = $.extend( {}, config.modifier );\n\tif ( dt.select && typeof dt.select.info === 'function' && modifier.selected === undefined ) {\n\t\tif ( dt.rows( config.rows, $.extend( { selected: true }, modifier ) ).any() ) {\n\t\t\t$.extend( modifier, { selected: true } )\n\t\t}\n\t}\n\n\tvar rowIndexes = dt.rows( config.rows, modifier ).indexes().toArray();\n\tvar selectedCells = dt.cells( rowIndexes, config.columns );\n\tvar cells = selectedCells\n\t\t.render( config.orthogonal )\n\t\t.toArray();\n\tvar cellNodes = selectedCells\n\t\t.nodes()\n\t\t.toArray();\n\n\tvar columns = header.length;\n\tvar rows = columns > 0 ? cells.length / columns : 0;\n\tvar body = [];\n\tvar cellCounter = 0;\n\n\tfor ( var i=0, ien=rows ; i<ien ; i++ ) {\n\t\tvar row = [ columns ];\n\n\t\tfor ( var j=0 ; j<columns ; j++ ) {\n\t\t\trow[j] = config.format.body( cells[ cellCounter ], i, j, cellNodes[ cellCounter ] );\n\t\t\tcellCounter++;\n\t\t}\n\n\t\tbody[i] = row;\n\t}\n\n\tvar data = {\n\t\theader: header,\n\t\tfooter: footer,\n\t\tbody: body\n\t};\n\n\tif ( config.customizeData ) {\n\t\tconfig.customizeData( data );\n\t}\n\n\treturn data;\n};\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables interface\n */\n\n// Attach to DataTables objects for global access\n$.fn.dataTable.Buttons = Buttons;\n$.fn.DataTable.Buttons = Buttons;\n\n\n\n// DataTables creation - check if the buttons have been defined for this table,\n// they will have been if the `B` option was used in `dom`, otherwise we should\n// create the buttons instance here so they can be inserted into the document\n// using the API. Listen for `init` for compatibility with pre 1.10.10, but to\n// be removed in future.\n$(document).on( 'init.dt plugin-init.dt', function (e, settings) {\n\tif ( e.namespace !== 'dt' ) {\n\t\treturn;\n\t}\n\n\tvar opts = settings.oInit.buttons || DataTable.defaults.buttons;\n\n\tif ( opts && ! settings._buttons ) {\n\t\tnew Buttons( settings, opts ).container();\n\t}\n} );\n\nfunction _init ( settings, options ) {\n\tvar api = new DataTable.Api( settings );\n\tvar opts = options\n\t\t? options\n\t\t: api.init().buttons || DataTable.defaults.buttons;\n\n\treturn new Buttons( api, opts ).container();\n}\n\n// DataTables `dom` feature option\nDataTable.ext.feature.push( {\n\tfnInit: _init,\n\tcFeature: \"B\"\n} );\n\n// DataTables 2 layout feature\nif ( DataTable.ext.features ) {\n\tDataTable.ext.features.register( 'buttons', _init );\n}\n\n\nreturn Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnV0dG9ucy9qcy9kYXRhVGFibGVzLmJ1dHRvbnMuanMuanMiLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTSxJQUEwQztBQUNoRDtBQUNBLEVBQUUsaUNBQVEsQ0FBQywyQ0FBUSxFQUFFLDJEQUFnQixDQUFDLG1DQUFFO0FBQ3hDO0FBQ0EsR0FBRztBQUFBLGtHQUFFO0FBQ0w7QUFDQSxNQUFNLEVBaUJKO0FBQ0YsQ0FBQztBQUNEO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUEsNEJBQTRCOztBQUU1QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QixhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLFVBQVU7QUFDdkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsU0FBUztBQUN0QixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEIsWUFBWSxZQUFZO0FBQ3hCLFlBQVksU0FBUztBQUNyQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLFFBQVE7QUFDL0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxNQUFNO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBLGFBQWEscUJBQXFCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsU0FBUztBQUN0QixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksU0FBUztBQUNyQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFFBQVE7QUFDOUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCLGFBQWEsU0FBUztBQUN0QixhQUFhLGlCQUFpQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLE9BQU87QUFDaEQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFlBQVk7QUFDekIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQSxhQUFhLHFCQUFxQjtBQUNsQyxhQUFhLFFBQVE7QUFDckIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUosc0NBQXNDLFFBQVE7QUFDOUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsUUFBUTtBQUM5Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0JBQW9CLDZCQUE2QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsYUFBYSxTQUFTO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFFBQVE7QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLGFBQWEsd0JBQXdCO0FBQ3JDLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDZCQUE2QjtBQUM3Qjs7QUFFQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkMsUUFBUTtBQUNuRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQ0FBMEMsUUFBUTtBQUNsRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLFlBQVksYUFBYTtBQUN6QixZQUFZLGVBQWU7QUFDM0IsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkVBQTJFOztBQUUzRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixJQUFJO0FBQ0o7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7QUFDNUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sR0FBRztBQUNIO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGtCQUFrQjtBQUM5QjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxRQUFRO0FBQzdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLE9BQU87QUFDbkIsWUFBWSw4QkFBOEI7QUFDMUM7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQyxRQUFRO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQSxvQ0FBb0MsUUFBUTtBQUM1QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DLFFBQVE7QUFDM0M7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhCQUE4QixRQUFRO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DLFFBQVE7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7O0FBR0EsbUNBQW1DLFFBQVE7QUFDM0M7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHNCQUFzQjtBQUN4Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsb0JBQW9CO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFDQUFxQyxRQUFRO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsMkJBQTJCO0FBQ3RDLFlBQVksYUFBYTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQSx5Q0FBeUMsZ0JBQWdCO0FBQ3pELHlCQUF5QixpQkFBaUI7QUFDMUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDJCQUEyQixRQUFRO0FBQ25DOztBQUVBLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9WdWV4eS8uL25vZGVfbW9kdWxlcy9kYXRhdGFibGVzLm5ldC1idXR0b25zL2pzL2RhdGFUYWJsZXMuYnV0dG9ucy5qcz8xMDUxIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISBCdXR0b25zIGZvciBEYXRhVGFibGVzIDIuMi4zXG4gKiDCqTIwMTYtMjAyMiBTcHJ5TWVkaWEgTHRkIC0gZGF0YXRhYmxlcy5uZXQvbGljZW5zZVxuICovXG5cbihmdW5jdGlvbiggZmFjdG9yeSApe1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoIFsnanF1ZXJ5JywgJ2RhdGF0YWJsZXMubmV0J10sIGZ1bmN0aW9uICggJCApIHtcblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCB3aW5kb3csIGRvY3VtZW50ICk7XG5cdFx0fSApO1xuXHR9XG5cdGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyb290LCAkKSB7XG5cdFx0XHRpZiAoICEgcm9vdCApIHtcblx0XHRcdFx0cm9vdCA9IHdpbmRvdztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQgfHwgISAkLmZuLmRhdGFUYWJsZSApIHtcblx0XHRcdFx0JCA9IHJlcXVpcmUoJ2RhdGF0YWJsZXMubmV0Jykocm9vdCwgJCkuJDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhY3RvcnkoICQsIHJvb3QsIHJvb3QuZG9jdW1lbnQgKTtcblx0XHR9O1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEJyb3dzZXJcblx0XHRmYWN0b3J5KCBqUXVlcnksIHdpbmRvdywgZG9jdW1lbnQgKTtcblx0fVxufShmdW5jdGlvbiggJCwgd2luZG93LCBkb2N1bWVudCwgdW5kZWZpbmVkICkge1xuJ3VzZSBzdHJpY3QnO1xudmFyIERhdGFUYWJsZSA9ICQuZm4uZGF0YVRhYmxlO1xuXG5cbi8vIFVzZWQgZm9yIG5hbWVzcGFjaW5nIGV2ZW50cyBhZGRlZCB0byB0aGUgZG9jdW1lbnQgYnkgZWFjaCBpbnN0YW5jZSwgc28gdGhleVxuLy8gY2FuIGJlIHJlbW92ZWQgb24gZGVzdHJveVxudmFyIF9pbnN0Q291bnRlciA9IDA7XG5cbi8vIEJ1dHRvbiBuYW1lc3BhY2luZyBjb3VudGVyIGZvciBuYW1lc3BhY2luZyBldmVudHMgb24gaW5kaXZpZHVhbCBidXR0b25zXG52YXIgX2J1dHRvbkNvdW50ZXIgPSAwO1xuXG52YXIgX2R0QnV0dG9ucyA9IERhdGFUYWJsZS5leHQuYnV0dG9ucztcblxuLy8gQWxsb3cgZm9yIGpRdWVyeSBzbGltXG5mdW5jdGlvbiBfZmFkZUluKGVsLCBkdXJhdGlvbiwgZm4pIHtcblx0aWYgKCQuZm4uYW5pbWF0ZSkge1xuXHRcdGVsXG5cdFx0XHQuc3RvcCgpXG5cdFx0XHQuZmFkZUluKCBkdXJhdGlvbiwgZm4gKTtcblxuXHR9XG5cdGVsc2Uge1xuXHRcdGVsLmNzcygnZGlzcGxheScsICdibG9jaycpO1xuXG5cdFx0aWYgKGZuKSB7XG5cdFx0XHRmbi5jYWxsKGVsKTtcblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gX2ZhZGVPdXQoZWwsIGR1cmF0aW9uLCBmbikge1xuXHRpZiAoJC5mbi5hbmltYXRlKSB7XG5cdFx0ZWxcblx0XHRcdC5zdG9wKClcblx0XHRcdC5mYWRlT3V0KCBkdXJhdGlvbiwgZm4gKTtcblx0fVxuXHRlbHNlIHtcblx0XHRlbC5jc3MoJ2Rpc3BsYXknLCAnbm9uZScpO1xuXHRcdFxuXHRcdGlmIChmbikge1xuXHRcdFx0Zm4uY2FsbChlbCk7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogW0J1dHRvbnMgZGVzY3JpcHRpb25dXG4gKiBAcGFyYW0ge1t0eXBlXX1cbiAqIEBwYXJhbSB7W3R5cGVdfVxuICovXG52YXIgQnV0dG9ucyA9IGZ1bmN0aW9uKCBkdCwgY29uZmlnIClcbntcblx0Ly8gSWYgbm90IGNyZWF0ZWQgd2l0aCBhIGBuZXdgIGtleXdvcmQgdGhlbiB3ZSByZXR1cm4gYSB3cmFwcGVyIGZ1bmN0aW9uIHRoYXRcblx0Ly8gd2lsbCB0YWtlIHRoZSBzZXR0aW5ncyBvYmplY3QgZm9yIGEgRFQuIFRoaXMgYWxsb3dzIGVhc3kgdXNlIG9mIG5ldyBpbnN0YW5jZXNcblx0Ly8gd2l0aCB0aGUgYGxheW91dGAgb3B0aW9uIC0gZS5nLiBgdG9wTGVmdDogJC5mbi5kYXRhVGFibGUuQnV0dG9ucyggLi4uIClgLlxuXHRpZiAoICEodGhpcyBpbnN0YW5jZW9mIEJ1dHRvbnMpICkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoc2V0dGluZ3MpIHtcblx0XHRcdHJldHVybiBuZXcgQnV0dG9ucyggc2V0dGluZ3MsIGR0ICkuY29udGFpbmVyKCk7XG5cdFx0fTtcblx0fVxuXG5cdC8vIElmIHRoZXJlIGlzIG5vIGNvbmZpZyBzZXQgaXQgdG8gYW4gZW1wdHkgb2JqZWN0XG5cdGlmICggdHlwZW9mKCBjb25maWcgKSA9PT0gJ3VuZGVmaW5lZCcgKSB7XG5cdFx0Y29uZmlnID0ge307XHRcblx0fVxuXHRcblx0Ly8gQWxsb3cgYSBib29sZWFuIHRydWUgZm9yIGRlZmF1bHRzXG5cdGlmICggY29uZmlnID09PSB0cnVlICkge1xuXHRcdGNvbmZpZyA9IHt9O1xuXHR9XG5cblx0Ly8gRm9yIGVhc3kgY29uZmlndXJhdGlvbiBvZiBidXR0b25zIGFuIGFycmF5IGNhbiBiZSBnaXZlblxuXHRpZiAoIEFycmF5LmlzQXJyYXkoIGNvbmZpZyApICkge1xuXHRcdGNvbmZpZyA9IHsgYnV0dG9uczogY29uZmlnIH07XG5cdH1cblxuXHR0aGlzLmMgPSAkLmV4dGVuZCggdHJ1ZSwge30sIEJ1dHRvbnMuZGVmYXVsdHMsIGNvbmZpZyApO1xuXG5cdC8vIERvbid0IHdhbnQgYSBkZWVwIGNvcHkgZm9yIHRoZSBidXR0b25zXG5cdGlmICggY29uZmlnLmJ1dHRvbnMgKSB7XG5cdFx0dGhpcy5jLmJ1dHRvbnMgPSBjb25maWcuYnV0dG9ucztcblx0fVxuXG5cdHRoaXMucyA9IHtcblx0XHRkdDogbmV3IERhdGFUYWJsZS5BcGkoIGR0ICksXG5cdFx0YnV0dG9uczogW10sXG5cdFx0bGlzdGVuS2V5czogJycsXG5cdFx0bmFtZXNwYWNlOiAnZHRiJysoX2luc3RDb3VudGVyKyspXG5cdH07XG5cblx0dGhpcy5kb20gPSB7XG5cdFx0Y29udGFpbmVyOiAkKCc8Jyt0aGlzLmMuZG9tLmNvbnRhaW5lci50YWcrJy8+Jylcblx0XHRcdC5hZGRDbGFzcyggdGhpcy5jLmRvbS5jb250YWluZXIuY2xhc3NOYW1lIClcblx0fTtcblxuXHR0aGlzLl9jb25zdHJ1Y3RvcigpO1xufTtcblxuXG4kLmV4dGVuZCggQnV0dG9ucy5wcm90b3R5cGUsIHtcblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKlxuXHQgKiBQdWJsaWMgbWV0aG9kc1xuXHQgKi9cblxuXHQvKipcblx0ICogR2V0IHRoZSBhY3Rpb24gb2YgYSBidXR0b25cblx0ICogQHBhcmFtICB7aW50fHN0cmluZ30gQnV0dG9uIGluZGV4XG5cdCAqIEByZXR1cm4ge2Z1bmN0aW9ufVxuXHQgKi8vKipcblx0ICogU2V0IHRoZSBhY3Rpb24gb2YgYSBidXR0b25cblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gZWxlbWVudFxuXHQgKiBAcGFyYW0gIHtmdW5jdGlvbn0gYWN0aW9uIEZ1bmN0aW9uIHRvIHNldFxuXHQgKiBAcmV0dXJuIHtCdXR0b25zfSBTZWxmIGZvciBjaGFpbmluZ1xuXHQgKi9cblx0YWN0aW9uOiBmdW5jdGlvbiAoIG5vZGUsIGFjdGlvbiApXG5cdHtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cblx0XHRpZiAoIGFjdGlvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGJ1dHRvbi5jb25mLmFjdGlvbjtcblx0XHR9XG5cblx0XHRidXR0b24uY29uZi5hY3Rpb24gPSBhY3Rpb247XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogQWRkIGFuIGFjdGl2ZSBjbGFzcyB0byB0aGUgYnV0dG9uIHRvIG1ha2UgdG8gbG9vayBhY3RpdmUgb3IgZ2V0IGN1cnJlbnRcblx0ICogYWN0aXZlIHN0YXRlLlxuXHQgKiBAcGFyYW0gIHtub2RlfSBub2RlIEJ1dHRvbiBlbGVtZW50XG5cdCAqIEBwYXJhbSAge2Jvb2xlYW59IFtmbGFnXSBFbmFibGUgLyBkaXNhYmxlIGZsYWdcblx0ICogQHJldHVybiB7QnV0dG9uc30gU2VsZiBmb3IgY2hhaW5pbmcgb3IgYm9vbGVhbiBmb3IgZ2V0dGVyXG5cdCAqL1xuXHRhY3RpdmU6IGZ1bmN0aW9uICggbm9kZSwgZmxhZyApIHtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cdFx0dmFyIGtsYXNzID0gdGhpcy5jLmRvbS5idXR0b24uYWN0aXZlO1xuXHRcdHZhciBqcU5vZGUgPSAkKGJ1dHRvbi5ub2RlKTtcblxuXHRcdGlmICggZmxhZyA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIGpxTm9kZS5oYXNDbGFzcygga2xhc3MgKTtcblx0XHR9XG5cblx0XHRqcU5vZGUudG9nZ2xlQ2xhc3MoIGtsYXNzLCBmbGFnID09PSB1bmRlZmluZWQgPyB0cnVlIDogZmxhZyApO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0LyoqXG5cdCAqIEFkZCBhIG5ldyBidXR0b25cblx0ICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZyBCdXR0b24gY29uZmlndXJhdGlvbiBvYmplY3QsIGJhc2Ugc3RyaW5nIG5hbWUgb3IgZnVuY3Rpb25cblx0ICogQHBhcmFtIHtpbnR8c3RyaW5nfSBbaWR4XSBCdXR0b24gaW5kZXggZm9yIHdoZXJlIHRvIGluc2VydCB0aGUgYnV0dG9uXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW2RyYXc9dHJ1ZV0gVHJpZ2dlciBhIGRyYXcuIFNldCBhIGZhbHNlIHdoZW4gYWRkaW5nXG5cdCAqICAgbG90cyBvZiBidXR0b25zLCB1bnRpbCB0aGUgbGFzdCBidXR0b24uXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRhZGQ6IGZ1bmN0aW9uICggY29uZmlnLCBpZHgsIGRyYXcgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbnMgPSB0aGlzLnMuYnV0dG9ucztcblxuXHRcdGlmICggdHlwZW9mIGlkeCA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHR2YXIgc3BsaXQgPSBpZHguc3BsaXQoJy0nKTtcblx0XHRcdHZhciBiYXNlID0gdGhpcy5zO1xuXG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c3BsaXQubGVuZ3RoLTEgOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0YmFzZSA9IGJhc2UuYnV0dG9uc1sgc3BsaXRbaV0qMSBdO1xuXHRcdFx0fVxuXG5cdFx0XHRidXR0b25zID0gYmFzZS5idXR0b25zO1xuXHRcdFx0aWR4ID0gc3BsaXRbIHNwbGl0Lmxlbmd0aC0xIF0qMTtcblx0XHR9XG5cblx0XHR0aGlzLl9leHBhbmRCdXR0b24oXG5cdFx0XHRidXR0b25zLFxuXHRcdFx0Y29uZmlnLFxuXHRcdFx0Y29uZmlnICE9PSB1bmRlZmluZWQgPyBjb25maWcuc3BsaXQgOiB1bmRlZmluZWQsXG5cdFx0XHQoY29uZmlnID09PSB1bmRlZmluZWQgfHwgY29uZmlnLnNwbGl0ID09PSB1bmRlZmluZWQgfHwgY29uZmlnLnNwbGl0Lmxlbmd0aCA9PT0gMCkgJiYgYmFzZSAhPT0gdW5kZWZpbmVkLFxuXHRcdFx0ZmFsc2UsXG5cdFx0XHRpZHhcblx0XHQpO1xuXG5cdFx0aWYgKGRyYXcgPT09IHVuZGVmaW5lZCB8fCBkcmF3ID09PSB0cnVlKSB7XG5cdFx0XHR0aGlzLl9kcmF3KCk7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogQ2xlYXIgYnV0dG9ucyBmcm9tIGEgY29sbGVjdGlvbiBhbmQgdGhlbiBpbnNlcnQgbmV3IGJ1dHRvbnNcblx0ICovXG5cdGNvbGxlY3Rpb25SZWJ1aWxkOiBmdW5jdGlvbiAoIG5vZGUsIG5ld0J1dHRvbnMgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdFxuXHRcdGlmKG5ld0J1dHRvbnMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dmFyIGk7XG5cdFx0XHQvLyBOZWVkIHRvIHJldmVyc2UgdGhlIGFycmF5XG5cdFx0XHRmb3IgKGk9YnV0dG9uLmJ1dHRvbnMubGVuZ3RoLTE7IGk+PTA7IGktLSkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZShidXR0b24uYnV0dG9uc1tpXS5ub2RlKTtcblx0XHRcdH1cblx0XG5cdFx0XHRmb3IgKGk9MDsgaTxuZXdCdXR0b25zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHZhciBuZXdCdG4gPSBuZXdCdXR0b25zW2ldO1xuXG5cdFx0XHRcdHRoaXMuX2V4cGFuZEJ1dHRvbihcblx0XHRcdFx0XHRidXR0b24uYnV0dG9ucyxcblx0XHRcdFx0XHRuZXdCdG4sXG5cdFx0XHRcdFx0bmV3QnRuICE9PSB1bmRlZmluZWQgJiYgbmV3QnRuLmNvbmZpZyAhPT0gdW5kZWZpbmVkICYmIG5ld0J0bi5jb25maWcuc3BsaXQgIT09IHVuZGVmaW5lZCxcblx0XHRcdFx0XHR0cnVlLFxuXHRcdFx0XHRcdG5ld0J0bi5wYXJlbnRDb25mICE9PSB1bmRlZmluZWQgJiYgbmV3QnRuLnBhcmVudENvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRpLFxuXHRcdFx0XHRcdG5ld0J0bi5wYXJlbnRDb25mXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhdyhidXR0b24uY29sbGVjdGlvbiwgYnV0dG9uLmJ1dHRvbnMpO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIGNvbnRhaW5lciBub2RlIGZvciB0aGUgYnV0dG9uc1xuXHQgKiBAcmV0dXJuIHtqUXVlcnl9IEJ1dHRvbnMgbm9kZVxuXHQgKi9cblx0Y29udGFpbmVyOiBmdW5jdGlvbiAoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuZG9tLmNvbnRhaW5lcjtcblx0fSxcblxuXHQvKipcblx0ICogRGlzYWJsZSBhIGJ1dHRvblxuXHQgKiBAcGFyYW0gIHtub2RlfSBub2RlIEJ1dHRvbiBub2RlXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRkaXNhYmxlOiBmdW5jdGlvbiAoIG5vZGUgKSB7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXG5cdFx0JChidXR0b24ubm9kZSlcblx0XHRcdC5hZGRDbGFzcyggdGhpcy5jLmRvbS5idXR0b24uZGlzYWJsZWQgKVxuXHRcdFx0LmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvKipcblx0ICogRGVzdHJveSB0aGUgaW5zdGFuY2UsIGNsZWFuaW5nIHVwIGV2ZW50IGhhbmRsZXJzIGFuZCByZW1vdmluZyBET01cblx0ICogZWxlbWVudHNcblx0ICogQHJldHVybiB7QnV0dG9uc30gU2VsZiBmb3IgY2hhaW5pbmdcblx0ICovXG5cdGRlc3Ryb3k6IGZ1bmN0aW9uICgpXG5cdHtcblx0XHQvLyBLZXkgZXZlbnQgbGlzdGVuZXJcblx0XHQkKCdib2R5Jykub2ZmKCAna2V5dXAuJyt0aGlzLnMubmFtZXNwYWNlICk7XG5cblx0XHQvLyBJbmRpdmlkdWFsIGJ1dHRvbiBkZXN0cm95IChzbyB0aGV5IGNhbiByZW1vdmUgdGhlaXIgb3duIGV2ZW50cyBpZlxuXHRcdC8vIG5lZWRlZCkuIFRha2UgYSBjb3B5IGFzIHRoZSBhcnJheSBpcyBtb2RpZmllZCBieSBgcmVtb3ZlYFxuXHRcdHZhciBidXR0b25zID0gdGhpcy5zLmJ1dHRvbnMuc2xpY2UoKTtcblx0XHR2YXIgaSwgaWVuO1xuXHRcdFxuXHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR0aGlzLnJlbW92ZSggYnV0dG9uc1tpXS5ub2RlICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udGFpbmVyXG5cdFx0dGhpcy5kb20uY29udGFpbmVyLnJlbW92ZSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGZyb20gdGhlIHNldHRpbmdzIG9iamVjdCBjb2xsZWN0aW9uXG5cdFx0dmFyIGJ1dHRvbkluc3RzID0gdGhpcy5zLmR0LnNldHRpbmdzKClbMF07XG5cblx0XHRmb3IgKCBpPTAsIGllbj1idXR0b25JbnN0cy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggYnV0dG9uSW5zdHMuaW5zdCA9PT0gdGhpcyApIHtcblx0XHRcdFx0YnV0dG9uSW5zdHMuc3BsaWNlKCBpLCAxICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBFbmFibGUgLyBkaXNhYmxlIGEgYnV0dG9uXG5cdCAqIEBwYXJhbSAge25vZGV9IG5vZGUgQnV0dG9uIG5vZGVcblx0ICogQHBhcmFtICB7Ym9vbGVhbn0gW2ZsYWc9dHJ1ZV0gRW5hYmxlIC8gZGlzYWJsZSBmbGFnXG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHRlbmFibGU6IGZ1bmN0aW9uICggbm9kZSwgZmxhZyApXG5cdHtcblx0XHRpZiAoIGZsYWcgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSggbm9kZSApO1xuXHRcdH1cblxuXHRcdHZhciBidXR0b24gPSB0aGlzLl9ub2RlVG9CdXR0b24oIG5vZGUgKTtcblx0XHQkKGJ1dHRvbi5ub2RlKVxuXHRcdFx0LnJlbW92ZUNsYXNzKCB0aGlzLmMuZG9tLmJ1dHRvbi5kaXNhYmxlZCApXG5cdFx0XHQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgYSBidXR0b24ncyBpbmRleFxuXHQgKiBcblx0ICogVGhpcyBpcyBpbnRlcm5hbGx5IHJlY3Vyc2l2ZVxuXHQgKiBAcGFyYW0ge2VsZW1lbnR9IG5vZGUgQnV0dG9uIHRvIGdldCB0aGUgaW5kZXggb2Zcblx0ICogQHJldHVybiB7c3RyaW5nfSBCdXR0b24gaW5kZXhcblx0ICovXG5cdGluZGV4OiBmdW5jdGlvbiAoIG5vZGUsIG5lc3RlZCwgYnV0dG9ucyApXG5cdHtcblx0XHRpZiAoICEgbmVzdGVkICkge1xuXHRcdFx0bmVzdGVkID0gJyc7XG5cdFx0XHRidXR0b25zID0gdGhpcy5zLmJ1dHRvbnM7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YXIgaW5uZXIgPSBidXR0b25zW2ldLmJ1dHRvbnM7XG5cblx0XHRcdGlmIChidXR0b25zW2ldLm5vZGUgPT09IG5vZGUpIHtcblx0XHRcdFx0cmV0dXJuIG5lc3RlZCArIGk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaW5uZXIgJiYgaW5uZXIubGVuZ3RoICkge1xuXHRcdFx0XHR2YXIgbWF0Y2ggPSB0aGlzLmluZGV4KG5vZGUsIGkgKyAnLScsIGlubmVyKTtcblxuXHRcdFx0XHRpZiAobWF0Y2ggIT09IG51bGwpIHtcblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2g7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbnVsbDtcblx0fSxcblxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIGluc3RhbmNlIG5hbWUgZm9yIHRoZSBidXR0b24gc2V0IHNlbGVjdG9yXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gSW5zdGFuY2UgbmFtZVxuXHQgKi9cblx0bmFtZTogZnVuY3Rpb24gKClcblx0e1xuXHRcdHJldHVybiB0aGlzLmMubmFtZTtcblx0fSxcblxuXHQvKipcblx0ICogR2V0IGEgYnV0dG9uJ3Mgbm9kZSBvZiB0aGUgYnV0dG9ucyBjb250YWluZXIgaWYgbm8gYnV0dG9uIGlzIGdpdmVuXG5cdCAqIEBwYXJhbSAge25vZGV9IFtub2RlXSBCdXR0b24gbm9kZVxuXHQgKiBAcmV0dXJuIHtqUXVlcnl9IEJ1dHRvbiBlbGVtZW50LCBvciBjb250YWluZXJcblx0ICovXG5cdG5vZGU6IGZ1bmN0aW9uICggbm9kZSApXG5cdHtcblx0XHRpZiAoICEgbm9kZSApIHtcblx0XHRcdHJldHVybiB0aGlzLmRvbS5jb250YWluZXI7XG5cdFx0fVxuXG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdHJldHVybiAkKGJ1dHRvbi5ub2RlKTtcblx0fSxcblxuXHQvKipcblx0ICogU2V0IC8gZ2V0IGEgcHJvY2Vzc2luZyBjbGFzcyBvbiB0aGUgc2VsZWN0ZWQgYnV0dG9uXG5cdCAqIEBwYXJhbSB7ZWxlbWVudH0gbm9kZSBUcmlnZ2VyaW5nIGJ1dHRvbiBub2RlXG5cdCAqIEBwYXJhbSAge2Jvb2xlYW59IGZsYWcgdHJ1ZSB0byBhZGQsIGZhbHNlIHRvIHJlbW92ZSwgdW5kZWZpbmVkIHRvIGdldFxuXHQgKiBAcmV0dXJuIHtib29sZWFufEJ1dHRvbnN9IEdldHRlciB2YWx1ZSBvciB0aGlzIGlmIGEgc2V0dGVyLlxuXHQgKi9cblx0cHJvY2Vzc2luZzogZnVuY3Rpb24gKCBub2RlLCBmbGFnIClcblx0e1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgYnV0dG9uID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlICk7XG5cblx0XHRpZiAoIGZsYWcgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiAkKGJ1dHRvbi5ub2RlKS5oYXNDbGFzcyggJ3Byb2Nlc3NpbmcnICk7XG5cdFx0fVxuXG5cdFx0JChidXR0b24ubm9kZSkudG9nZ2xlQ2xhc3MoICdwcm9jZXNzaW5nJywgZmxhZyApO1xuXG5cdFx0JChkdC50YWJsZSgpLm5vZGUoKSkudHJpZ2dlckhhbmRsZXIoICdidXR0b25zLXByb2Nlc3NpbmcuZHQnLCBbXG5cdFx0XHRmbGFnLCBkdC5idXR0b24oIG5vZGUgKSwgZHQsICQobm9kZSksIGJ1dHRvbi5jb25mXG5cdFx0XSApO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJlbW92ZSBhIGJ1dHRvbi5cblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gbm9kZVxuXHQgKiBAcmV0dXJuIHtCdXR0b25zfSBTZWxmIGZvciBjaGFpbmluZ1xuXHQgKi9cblx0cmVtb3ZlOiBmdW5jdGlvbiAoIG5vZGUgKVxuXHR7XG5cdFx0dmFyIGJ1dHRvbiA9IHRoaXMuX25vZGVUb0J1dHRvbiggbm9kZSApO1xuXHRcdHZhciBob3N0ID0gdGhpcy5fbm9kZVRvSG9zdCggbm9kZSApO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblxuXHRcdC8vIFJlbW92ZSBhbnkgY2hpbGQgYnV0dG9ucyBmaXJzdFxuXHRcdGlmICggYnV0dG9uLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0Zm9yICggdmFyIGk9YnV0dG9uLmJ1dHRvbnMubGVuZ3RoLTEgOyBpPj0wIDsgaS0tICkge1xuXHRcdFx0XHR0aGlzLnJlbW92ZSggYnV0dG9uLmJ1dHRvbnNbaV0ubm9kZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGJ1dHRvbi5jb25mLmRlc3Ryb3lpbmcgPSB0cnVlO1xuXG5cdFx0Ly8gQWxsb3cgdGhlIGJ1dHRvbiB0byByZW1vdmUgZXZlbnQgaGFuZGxlcnMsIGV0Y1xuXHRcdGlmICggYnV0dG9uLmNvbmYuZGVzdHJveSApIHtcblx0XHRcdGJ1dHRvbi5jb25mLmRlc3Ryb3kuY2FsbCggZHQuYnV0dG9uKG5vZGUpLCBkdCwgJChub2RlKSwgYnV0dG9uLmNvbmYgKTtcblx0XHR9XG5cblx0XHR0aGlzLl9yZW1vdmVLZXkoIGJ1dHRvbi5jb25mICk7XG5cblx0XHQkKGJ1dHRvbi5ub2RlKS5yZW1vdmUoKTtcblxuXHRcdHZhciBpZHggPSAkLmluQXJyYXkoIGJ1dHRvbiwgaG9zdCApO1xuXHRcdGhvc3Quc3BsaWNlKCBpZHgsIDEgKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIHRleHQgZm9yIGEgYnV0dG9uXG5cdCAqIEBwYXJhbSAge2ludHxzdHJpbmd9IG5vZGUgQnV0dG9uIGluZGV4XG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQnV0dG9uIHRleHRcblx0ICovLyoqXG5cdCAqIFNldCB0aGUgdGV4dCBmb3IgYSBidXR0b25cblx0ICogQHBhcmFtICB7aW50fHN0cmluZ3xmdW5jdGlvbn0gbm9kZSBCdXR0b24gaW5kZXhcblx0ICogQHBhcmFtICB7c3RyaW5nfSBsYWJlbCBUZXh0XG5cdCAqIEByZXR1cm4ge0J1dHRvbnN9IFNlbGYgZm9yIGNoYWluaW5nXG5cdCAqL1xuXHR0ZXh0OiBmdW5jdGlvbiAoIG5vZGUsIGxhYmVsIClcblx0e1xuXHRcdHZhciBidXR0b24gPSB0aGlzLl9ub2RlVG9CdXR0b24oIG5vZGUgKTtcblx0XHR2YXIgYnV0dG9uTGluZXIgPSB0aGlzLmMuZG9tLmNvbGxlY3Rpb24uYnV0dG9uTGluZXI7XG5cdFx0dmFyIGxpbmVyVGFnID0gYnV0dG9uLmluQ29sbGVjdGlvbiAmJiBidXR0b25MaW5lciAmJiBidXR0b25MaW5lci50YWcgP1xuXHRcdFx0YnV0dG9uTGluZXIudGFnIDpcblx0XHRcdHRoaXMuYy5kb20uYnV0dG9uTGluZXIudGFnO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIganFOb2RlID0gJChidXR0b24ubm9kZSk7XG5cdFx0dmFyIHRleHQgPSBmdW5jdGlvbiAoIG9wdCApIHtcblx0XHRcdHJldHVybiB0eXBlb2Ygb3B0ID09PSAnZnVuY3Rpb24nID9cblx0XHRcdFx0b3B0KCBkdCwganFOb2RlLCBidXR0b24uY29uZiApIDpcblx0XHRcdFx0b3B0O1xuXHRcdH07XG5cblx0XHRpZiAoIGxhYmVsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXR1cm4gdGV4dCggYnV0dG9uLmNvbmYudGV4dCApO1xuXHRcdH1cblxuXHRcdGJ1dHRvbi5jb25mLnRleHQgPSBsYWJlbDtcblxuXHRcdGlmICggbGluZXJUYWcgKSB7XG5cdFx0XHRqcU5vZGVcblx0XHRcdFx0LmNoaWxkcmVuKCBsaW5lclRhZyApXG5cdFx0XHRcdC5lcSgwKVxuXHRcdFx0XHQuZmlsdGVyKCc6bm90KC5kdC1kb3duLWFycm93KScpXG5cdFx0XHRcdC5odG1sKCB0ZXh0KGxhYmVsKSApO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGpxTm9kZS5odG1sKCB0ZXh0KGxhYmVsKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKlxuXHQgKiBDb25zdHJ1Y3RvclxuXHQgKi9cblxuXHQvKipcblx0ICogQnV0dG9ucyBjb25zdHJ1Y3RvclxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2NvbnN0cnVjdG9yOiBmdW5jdGlvbiAoKVxuXHR7XG5cdFx0dmFyIHRoYXQgPSB0aGlzO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgZHRTZXR0aW5ncyA9IGR0LnNldHRpbmdzKClbMF07XG5cdFx0dmFyIGJ1dHRvbnMgPSAgdGhpcy5jLmJ1dHRvbnM7XG5cblx0XHRpZiAoICEgZHRTZXR0aW5ncy5fYnV0dG9ucyApIHtcblx0XHRcdGR0U2V0dGluZ3MuX2J1dHRvbnMgPSBbXTtcblx0XHR9XG5cblx0XHRkdFNldHRpbmdzLl9idXR0b25zLnB1c2goIHtcblx0XHRcdGluc3Q6IHRoaXMsXG5cdFx0XHRuYW1lOiB0aGlzLmMubmFtZVxuXHRcdH0gKTtcblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0dGhpcy5hZGQoIGJ1dHRvbnNbaV0gKTtcblx0XHR9XG5cblx0XHRkdC5vbiggJ2Rlc3Ryb3knLCBmdW5jdGlvbiAoIGUsIHNldHRpbmdzICkge1xuXHRcdFx0aWYgKCBzZXR0aW5ncyA9PT0gZHRTZXR0aW5ncyApIHtcblx0XHRcdFx0dGhhdC5kZXN0cm95KCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0Ly8gR2xvYmFsIGtleSBldmVudCBiaW5kaW5nIHRvIGxpc3RlbiBmb3IgYnV0dG9uIGtleXNcblx0XHQkKCdib2R5Jykub24oICdrZXl1cC4nK3RoaXMucy5uYW1lc3BhY2UsIGZ1bmN0aW9uICggZSApIHtcblx0XHRcdGlmICggISBkb2N1bWVudC5hY3RpdmVFbGVtZW50IHx8IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkgKSB7XG5cdFx0XHRcdC8vIFNVc2UgYSBzdHJpbmcgb2YgY2hhcmFjdGVycyBmb3IgZmFzdCBsb29rdXAgb2YgaWYgd2UgbmVlZCB0b1xuXHRcdFx0XHQvLyBoYW5kbGUgdGhpc1xuXHRcdFx0XHR2YXIgY2hhcmFjdGVyID0gU3RyaW5nLmZyb21DaGFyQ29kZShlLmtleUNvZGUpLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRcdFx0aWYgKCB0aGF0LnMubGlzdGVuS2V5cy50b0xvd2VyQ2FzZSgpLmluZGV4T2YoIGNoYXJhY3RlciApICE9PSAtMSApIHtcblx0XHRcdFx0XHR0aGF0Ll9rZXlwcmVzcyggY2hhcmFjdGVyLCBlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblxuXHQvKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG5cdCAqIFByaXZhdGUgbWV0aG9kc1xuXHQgKi9cblxuXHQvKipcblx0ICogQWRkIGEgbmV3IGJ1dHRvbiB0byB0aGUga2V5IHByZXNzIGxpc3RlbmVyXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBjb25mIFJlc29sdmVkIGJ1dHRvbiBjb25maWd1cmF0aW9uIG9iamVjdFxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2FkZEtleTogZnVuY3Rpb24gKCBjb25mIClcblx0e1xuXHRcdGlmICggY29uZi5rZXkgKSB7XG5cdFx0XHR0aGlzLnMubGlzdGVuS2V5cyArPSAkLmlzUGxhaW5PYmplY3QoIGNvbmYua2V5ICkgP1xuXHRcdFx0XHRjb25mLmtleS5rZXkgOlxuXHRcdFx0XHRjb25mLmtleTtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIEluc2VydCB0aGUgYnV0dG9ucyBpbnRvIHRoZSBjb250YWluZXIuIENhbGwgd2l0aG91dCBwYXJhbWV0ZXJzIVxuXHQgKiBAcGFyYW0gIHtub2RlfSBbY29udGFpbmVyXSBSZWN1cnNpdmUgb25seSAtIEluc2VydCBwb2ludFxuXHQgKiBAcGFyYW0gIHthcnJheX0gW2J1dHRvbnNdIFJlY3Vyc2l2ZSBvbmx5IC0gQnV0dG9ucyBhcnJheVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2RyYXc6IGZ1bmN0aW9uICggY29udGFpbmVyLCBidXR0b25zIClcblx0e1xuXHRcdGlmICggISBjb250YWluZXIgKSB7XG5cdFx0XHRjb250YWluZXIgPSB0aGlzLmRvbS5jb250YWluZXI7XG5cdFx0XHRidXR0b25zID0gdGhpcy5zLmJ1dHRvbnM7XG5cdFx0fVxuXG5cdFx0Y29udGFpbmVyLmNoaWxkcmVuKCkuZGV0YWNoKCk7XG5cblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49YnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGNvbnRhaW5lci5hcHBlbmQoIGJ1dHRvbnNbaV0uaW5zZXJ0ZXIgKTtcblx0XHRcdGNvbnRhaW5lci5hcHBlbmQoICcgJyApO1xuXG5cdFx0XHRpZiAoIGJ1dHRvbnNbaV0uYnV0dG9ucyAmJiBidXR0b25zW2ldLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0XHR0aGlzLl9kcmF3KCBidXR0b25zW2ldLmNvbGxlY3Rpb24sIGJ1dHRvbnNbaV0uYnV0dG9ucyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogQ3JlYXRlIGJ1dHRvbnMgZnJvbSBhbiBhcnJheSBvZiBidXR0b25zXG5cdCAqIEBwYXJhbSAge2FycmF5fSBhdHRhY2hUbyBCdXR0b25zIGFycmF5IHRvIGF0dGFjaCB0b1xuXHQgKiBAcGFyYW0gIHtvYmplY3R9IGJ1dHRvbiBCdXR0b24gZGVmaW5pdGlvblxuXHQgKiBAcGFyYW0gIHtib29sZWFufSBpbkNvbGxlY3Rpb24gdHJ1ZSBpZiB0aGUgYnV0dG9uIGlzIGluIGEgY29sbGVjdGlvblxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2V4cGFuZEJ1dHRvbjogZnVuY3Rpb24gKCBhdHRhY2hUbywgYnV0dG9uLCBzcGxpdCwgaW5Db2xsZWN0aW9uLCBpblNwbGl0LCBhdHRhY2hQb2ludCwgcGFyZW50Q29uZiApXG5cdHtcblx0XHR2YXIgZHQgPSB0aGlzLnMuZHQ7XG5cdFx0dmFyIGJ1dHRvbkNvdW50ZXIgPSAwO1xuXHRcdHZhciBpc1NwbGl0ID0gZmFsc2U7XG5cdFx0dmFyIGJ1dHRvbnMgPSAhIEFycmF5LmlzQXJyYXkoIGJ1dHRvbiApID9cblx0XHRcdFsgYnV0dG9uIF0gOlxuXHRcdFx0YnV0dG9uO1xuXHRcdFxuXHRcdGlmKGJ1dHRvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0YnV0dG9ucyA9ICFBcnJheS5pc0FycmF5KHNwbGl0KSA/XG5cdFx0XHRcdFsgc3BsaXQgXSA6XG5cdFx0XHRcdHNwbGl0O1xuXHRcdH1cblxuXHRcdGlmIChidXR0b24gIT09IHVuZGVmaW5lZCAmJiBidXR0b24uc3BsaXQgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0aXNTcGxpdCA9IHRydWU7XG5cdFx0fVxuXHRcdFx0XG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YXIgY29uZiA9IHRoaXMuX3Jlc29sdmVFeHRlbmRzKCBidXR0b25zW2ldICk7XG5cblx0XHRcdGlmICggISBjb25mICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYoIGNvbmYuY29uZmlnICE9PSB1bmRlZmluZWQgJiYgY29uZi5jb25maWcuc3BsaXQpIHtcblx0XHRcdFx0aXNTcGxpdCA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0aXNTcGxpdCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvLyBJZiB0aGUgY29uZmlndXJhdGlvbiBpcyBhbiBhcnJheSwgdGhlbiBleHBhbmQgdGhlIGJ1dHRvbnMgYXQgdGhpc1xuXHRcdFx0Ly8gcG9pbnRcblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggY29uZiApICkge1xuXHRcdFx0XHR0aGlzLl9leHBhbmRCdXR0b24oIGF0dGFjaFRvLCBjb25mLCBidWlsdCAhPT0gdW5kZWZpbmVkICYmIGJ1aWx0LmNvbmYgIT09IHVuZGVmaW5lZCA/IGJ1aWx0LmNvbmYuc3BsaXQgOiB1bmRlZmluZWQsIGluQ29sbGVjdGlvbiwgcGFyZW50Q29uZiAhPT0gdW5kZWZpbmVkICYmIHBhcmVudENvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCwgYXR0YWNoUG9pbnQsIHBhcmVudENvbmYgKTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBidWlsdCA9IHRoaXMuX2J1aWxkQnV0dG9uKCBjb25mLCBpbkNvbGxlY3Rpb24sIGNvbmYuc3BsaXQgIT09IHVuZGVmaW5lZCB8fCAoY29uZi5jb25maWcgIT09IHVuZGVmaW5lZCAmJiBjb25mLmNvbmZpZy5zcGxpdCAhPT0gdW5kZWZpbmVkKSwgaW5TcGxpdCApO1xuXHRcdFx0aWYgKCAhIGJ1aWx0ICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBhdHRhY2hQb2ludCAhPT0gdW5kZWZpbmVkICYmIGF0dGFjaFBvaW50ICE9PSBudWxsICkge1xuXHRcdFx0XHRhdHRhY2hUby5zcGxpY2UoIGF0dGFjaFBvaW50LCAwLCBidWlsdCApO1xuXHRcdFx0XHRhdHRhY2hQb2ludCsrO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGF0dGFjaFRvLnB1c2goIGJ1aWx0ICk7XG5cdFx0XHR9XG5cblx0XHRcdFxuXHRcdFx0aWYgKCBidWlsdC5jb25mLmJ1dHRvbnMgfHwgYnVpbHQuY29uZi5zcGxpdCApIHtcblx0XHRcdFx0YnVpbHQuY29sbGVjdGlvbiA9ICQoJzwnKyhpc1NwbGl0ID8gdGhpcy5jLmRvbS5zcGxpdENvbGxlY3Rpb24udGFnIDogdGhpcy5jLmRvbS5jb2xsZWN0aW9uLnRhZykrJy8+Jyk7XG5cblx0XHRcdFx0YnVpbHQuY29uZi5fY29sbGVjdGlvbiA9IGJ1aWx0LmNvbGxlY3Rpb247XG5cblx0XHRcdFx0aWYoYnVpbHQuY29uZi5zcGxpdCkge1xuXHRcdFx0XHRcdGZvcih2YXIgaiA9IDA7IGogPCBidWlsdC5jb25mLnNwbGl0Lmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0XHRpZih0eXBlb2YgYnVpbHQuY29uZi5zcGxpdFtqXSA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0XHRcdFx0XHRidWlsdC5jb25mLnNwbGl0W2pdLnBhcmVudCA9IHBhcmVudENvbmY7XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uY29sbGVjdGlvbkxheW91dCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0YnVpbHQuY29uZi5zcGxpdFtqXS5jb2xsZWN0aW9uTGF5b3V0ID0gYnVpbHQuY29uZi5jb2xsZWN0aW9uTGF5b3V0O1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uZHJvcHVwID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRcdFx0XHRidWlsdC5jb25mLnNwbGl0W2pdLmRyb3B1cCA9IGJ1aWx0LmNvbmYuZHJvcHVwO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmKGJ1aWx0LmNvbmYuc3BsaXRbal0uZmFkZSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0YnVpbHQuY29uZi5zcGxpdFtqXS5mYWRlID0gYnVpbHQuY29uZi5mYWRlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdCQoYnVpbHQubm9kZSkuYXBwZW5kKCQoJzxzcGFuIGNsYXNzPVwiZHQtZG93bi1hcnJvd1wiPicrdGhpcy5jLmRvbS5zcGxpdERyb3Bkb3duLnRleHQrJzwvc3Bhbj4nKSlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuX2V4cGFuZEJ1dHRvbiggYnVpbHQuYnV0dG9ucywgYnVpbHQuY29uZi5idXR0b25zLCBidWlsdC5jb25mLnNwbGl0LCAhaXNTcGxpdCwgaXNTcGxpdCwgYXR0YWNoUG9pbnQsIGJ1aWx0LmNvbmYgKTtcblx0XHRcdH1cblx0XHRcdGJ1aWx0LmNvbmYucGFyZW50ID0gcGFyZW50Q29uZjtcblxuXHRcdFx0Ly8gaW5pdCBjYWxsIGlzIG1hZGUgaGVyZSwgcmF0aGVyIHRoYW4gYnVpbGRCdXR0b24gYXMgaXQgbmVlZHMgdG9cblx0XHRcdC8vIGJlIHNlbGVjdGFibGUsIGFuZCBmb3IgdGhhdCBpdCBuZWVkcyB0byBiZSBpbiB0aGUgYnV0dG9ucyBhcnJheVxuXHRcdFx0aWYgKCBjb25mLmluaXQgKSB7XG5cdFx0XHRcdGNvbmYuaW5pdC5jYWxsKCBkdC5idXR0b24oIGJ1aWx0Lm5vZGUgKSwgZHQsICQoYnVpbHQubm9kZSksIGNvbmYgKTtcblx0XHRcdH1cblxuXHRcdFx0YnV0dG9uQ291bnRlcisrO1xuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogQ3JlYXRlIGFuIGluZGl2aWR1YWwgYnV0dG9uXG5cdCAqIEBwYXJhbSAge29iamVjdH0gY29uZmlnICAgICAgICAgICAgUmVzb2x2ZWQgYnV0dG9uIGNvbmZpZ3VyYXRpb25cblx0ICogQHBhcmFtICB7Ym9vbGVhbn0gaW5Db2xsZWN0aW9uIGB0cnVlYCBpZiBhIGNvbGxlY3Rpb24gYnV0dG9uXG5cdCAqIEByZXR1cm4ge2pRdWVyeX0gQ3JlYXRlZCBidXR0b24gbm9kZSAoalF1ZXJ5KVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2J1aWxkQnV0dG9uOiBmdW5jdGlvbiAoIGNvbmZpZywgaW5Db2xsZWN0aW9uLCBpc1NwbGl0LCBpblNwbGl0IClcblx0e1xuXHRcdHZhciBidXR0b25Eb20gPSB0aGlzLmMuZG9tLmJ1dHRvbjtcblx0XHR2YXIgbGluZXJEb20gPSB0aGlzLmMuZG9tLmJ1dHRvbkxpbmVyO1xuXHRcdHZhciBjb2xsZWN0aW9uRG9tID0gdGhpcy5jLmRvbS5jb2xsZWN0aW9uO1xuXHRcdHZhciBzcGxpdERvbSA9IHRoaXMuYy5kb20uc3BsaXQ7XG5cdFx0dmFyIHNwbGl0Q29sbGVjdGlvbkRvbSA9IHRoaXMuYy5kb20uc3BsaXRDb2xsZWN0aW9uO1xuXHRcdHZhciBzcGxpdERyb3Bkb3duQnV0dG9uID0gdGhpcy5jLmRvbS5zcGxpdERyb3Bkb3duQnV0dG9uO1xuXHRcdHZhciBkdCA9IHRoaXMucy5kdDtcblx0XHR2YXIgdGV4dCA9IGZ1bmN0aW9uICggb3B0ICkge1xuXHRcdFx0cmV0dXJuIHR5cGVvZiBvcHQgPT09ICdmdW5jdGlvbicgP1xuXHRcdFx0XHRvcHQoIGR0LCBidXR0b24sIGNvbmZpZyApIDpcblx0XHRcdFx0b3B0O1xuXHRcdH07XG5cblx0XHQvLyBTcGFjZXJzIGRvbid0IGRvIG11Y2ggb3RoZXIgdGhhbiBpbnNlcnQgYW4gZWxlbWVudCBpbnRvIHRoZSBET01cblx0XHRpZiAoY29uZmlnLnNwYWNlcikge1xuXHRcdFx0dmFyIHNwYWNlciA9ICQoJzxzcGFuPjwvc3Bhbj4nKVxuXHRcdFx0XHQuYWRkQ2xhc3MoJ2R0LWJ1dHRvbi1zcGFjZXIgJyArIGNvbmZpZy5zdHlsZSArICcgJyArIGJ1dHRvbkRvbS5zcGFjZXJDbGFzcylcblx0XHRcdFx0Lmh0bWwodGV4dChjb25maWcudGV4dCkpO1xuXG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRjb25mOiAgICAgICAgIGNvbmZpZyxcblx0XHRcdFx0bm9kZTogICAgICAgICBzcGFjZXIsXG5cdFx0XHRcdGluc2VydGVyOiAgICAgc3BhY2VyLFxuXHRcdFx0XHRidXR0b25zOiAgICAgIFtdLFxuXHRcdFx0XHRpbkNvbGxlY3Rpb246IGluQ29sbGVjdGlvbixcblx0XHRcdFx0aXNTcGxpdDpcdCAgaXNTcGxpdCxcblx0XHRcdFx0aW5TcGxpdDpcdCAgaW5TcGxpdCxcblx0XHRcdFx0Y29sbGVjdGlvbjogICBudWxsXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdGlmICggIWlzU3BsaXQgJiYgaW5TcGxpdCAmJiBzcGxpdENvbGxlY3Rpb25Eb20gKSB7XG5cdFx0XHRidXR0b25Eb20gPSBzcGxpdERyb3Bkb3duQnV0dG9uO1xuXHRcdH1cblx0XHRlbHNlIGlmICggIWlzU3BsaXQgJiYgaW5Db2xsZWN0aW9uICYmIGNvbGxlY3Rpb25Eb20uYnV0dG9uICkge1xuXHRcdFx0YnV0dG9uRG9tID0gY29sbGVjdGlvbkRvbS5idXR0b247XG5cdFx0fSBcblxuXHRcdGlmICggIWlzU3BsaXQgJiYgaW5TcGxpdCAmJiBzcGxpdENvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXIgKSB7XG5cdFx0XHRsaW5lckRvbSA9IHNwbGl0Q29sbGVjdGlvbkRvbS5idXR0b25MaW5lclxuXHRcdH1cblx0XHRlbHNlIGlmICggIWlzU3BsaXQgJiYgaW5Db2xsZWN0aW9uICYmIGNvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXIgKSB7XG5cdFx0XHRsaW5lckRvbSA9IGNvbGxlY3Rpb25Eb20uYnV0dG9uTGluZXI7XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgdGhlIGJ1dHRvbiBpcyBhdmFpbGFibGUgYmFzZWQgb24gd2hhdGV2ZXIgcmVxdWlyZW1lbnRzXG5cdFx0Ly8gaXQgaGFzLiBGb3IgZXhhbXBsZSwgUERGIGJ1dHRvbiByZXF1aXJlIHBkZm1ha2Vcblx0XHRpZiAoIGNvbmZpZy5hdmFpbGFibGUgJiYgISBjb25maWcuYXZhaWxhYmxlKCBkdCwgY29uZmlnICkgJiYgIWNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciBidXR0b247XG5cdFx0aWYoIWNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnaHRtbCcpKSB7XG5cdFx0XHR2YXIgYWN0aW9uID0gZnVuY3Rpb24gKCBlLCBkdCwgYnV0dG9uLCBjb25maWcgKSB7XG5cdFx0XHRcdGNvbmZpZy5hY3Rpb24uY2FsbCggZHQuYnV0dG9uKCBidXR0b24gKSwgZSwgZHQsIGJ1dHRvbiwgY29uZmlnICk7XG5cdFxuXHRcdFx0XHQkKGR0LnRhYmxlKCkubm9kZSgpKS50cmlnZ2VySGFuZGxlciggJ2J1dHRvbnMtYWN0aW9uLmR0JywgW1xuXHRcdFx0XHRcdGR0LmJ1dHRvbiggYnV0dG9uICksIGR0LCBidXR0b24sIGNvbmZpZyBcblx0XHRcdFx0XSApO1xuXHRcdFx0fTtcblxuXHRcdFx0dmFyIHRhZyA9IGNvbmZpZy50YWcgfHwgYnV0dG9uRG9tLnRhZztcblx0XHRcdHZhciBjbGlja0JsdXJzID0gY29uZmlnLmNsaWNrQmx1cnMgPT09IHVuZGVmaW5lZFxuXHRcdFx0XHQ/IHRydWUgOlxuXHRcdFx0XHRjb25maWcuY2xpY2tCbHVycztcblxuXHRcdFx0YnV0dG9uID0gJCgnPCcrdGFnKycvPicpXG5cdFx0XHRcdC5hZGRDbGFzcyggYnV0dG9uRG9tLmNsYXNzTmFtZSApXG5cdFx0XHRcdC5hZGRDbGFzcyggaW5TcGxpdCA/IHRoaXMuYy5kb20uc3BsaXREcm9wZG93bkJ1dHRvbi5jbGFzc05hbWUgOiAnJylcblx0XHRcdFx0LmF0dHIoICd0YWJpbmRleCcsIHRoaXMucy5kdC5zZXR0aW5ncygpWzBdLmlUYWJJbmRleCApXG5cdFx0XHRcdC5hdHRyKCAnYXJpYS1jb250cm9scycsIHRoaXMucy5kdC50YWJsZSgpLm5vZGUoKS5pZCApXG5cdFx0XHRcdC5vbiggJ2NsaWNrLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcblx0XHRcdFx0XHRpZiAoICEgYnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSAmJiBjb25maWcuYWN0aW9uICkge1xuXHRcdFx0XHRcdFx0YWN0aW9uKCBlLCBkdCwgYnV0dG9uLCBjb25maWcgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYoIGNsaWNrQmx1cnMgKSB7XG5cdFx0XHRcdFx0XHRidXR0b24udHJpZ2dlcignYmx1cicpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApXG5cdFx0XHRcdC5vbiggJ2tleXByZXNzLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKCBlLmtleUNvZGUgPT09IDEzICkge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoICEgYnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSAmJiBjb25maWcuYWN0aW9uICkge1xuXHRcdFx0XHRcdFx0XHRhY3Rpb24oIGUsIGR0LCBidXR0b24sIGNvbmZpZyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcblx0XHRcdC8vIE1ha2UgYGFgIHRhZ3MgYWN0IGxpa2UgYSBsaW5rXG5cdFx0XHRpZiAoIHRhZy50b0xvd2VyQ2FzZSgpID09PSAnYScgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCAnaHJlZicsICcjJyApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIEJ1dHRvbiB0YWdzIHNob3VsZCBoYXZlIGB0eXBlPWJ1dHRvbmAgc28gdGhleSBkb24ndCBoYXZlIGFueSBkZWZhdWx0IGJlaGF2aW91clxuXHRcdFx0aWYgKCB0YWcudG9Mb3dlckNhc2UoKSA9PT0gJ2J1dHRvbicgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCAndHlwZScsICdidXR0b24nICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBsaW5lckRvbS50YWcgKSB7XG5cdFx0XHRcdHZhciBsaW5lciA9ICQoJzwnK2xpbmVyRG9tLnRhZysnLz4nKVxuXHRcdFx0XHRcdC5odG1sKCB0ZXh0KCBjb25maWcudGV4dCApIClcblx0XHRcdFx0XHQuYWRkQ2xhc3MoIGxpbmVyRG9tLmNsYXNzTmFtZSApO1xuXHRcblx0XHRcdFx0aWYgKCBsaW5lckRvbS50YWcudG9Mb3dlckNhc2UoKSA9PT0gJ2EnICkge1xuXHRcdFx0XHRcdGxpbmVyLmF0dHIoICdocmVmJywgJyMnICk7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdGJ1dHRvbi5hcHBlbmQoIGxpbmVyICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0YnV0dG9uLmh0bWwoIHRleHQoIGNvbmZpZy50ZXh0ICkgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIGNvbmZpZy5lbmFibGVkID09PSBmYWxzZSApIHtcblx0XHRcdFx0YnV0dG9uLmFkZENsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIGNvbmZpZy5jbGFzc05hbWUgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hZGRDbGFzcyggY29uZmlnLmNsYXNzTmFtZSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggY29uZmlnLnRpdGxlQXR0ciApIHtcblx0XHRcdFx0YnV0dG9uLmF0dHIoICd0aXRsZScsIHRleHQoIGNvbmZpZy50aXRsZUF0dHIgKSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggY29uZmlnLmF0dHIgKSB7XG5cdFx0XHRcdGJ1dHRvbi5hdHRyKCBjb25maWcuYXR0ciApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggISBjb25maWcubmFtZXNwYWNlICkge1xuXHRcdFx0XHRjb25maWcubmFtZXNwYWNlID0gJy5kdC1idXR0b24tJysoX2J1dHRvbkNvdW50ZXIrKyk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICAoIGNvbmZpZy5jb25maWcgIT09IHVuZGVmaW5lZCAmJiBjb25maWcuY29uZmlnLnNwbGl0ICkge1xuXHRcdFx0XHRjb25maWcuc3BsaXQgPSBjb25maWcuY29uZmlnLnNwbGl0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGJ1dHRvbiA9ICQoY29uZmlnLmh0bWwpXG5cdFx0fVxuXHRcblx0XHR2YXIgYnV0dG9uQ29udGFpbmVyID0gdGhpcy5jLmRvbS5idXR0b25Db250YWluZXI7XG5cdFx0dmFyIGluc2VydGVyO1xuXHRcdGlmICggYnV0dG9uQ29udGFpbmVyICYmIGJ1dHRvbkNvbnRhaW5lci50YWcgKSB7XG5cdFx0XHRpbnNlcnRlciA9ICQoJzwnK2J1dHRvbkNvbnRhaW5lci50YWcrJy8+Jylcblx0XHRcdFx0LmFkZENsYXNzKCBidXR0b25Db250YWluZXIuY2xhc3NOYW1lIClcblx0XHRcdFx0LmFwcGVuZCggYnV0dG9uICk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0aW5zZXJ0ZXIgPSBidXR0b247XG5cdFx0fVxuXG5cdFx0dGhpcy5fYWRkS2V5KCBjb25maWcgKTtcblxuXHRcdC8vIFN0eWxlIGludGVncmF0aW9uIGNhbGxiYWNrIGZvciBET00gbWFuaXB1bGF0aW9uXG5cdFx0Ly8gTm90ZSB0aGF0IHRoaXMgaXMgX25vdF8gZG9jdW1lbnRlZC4gSXQgaXMgY3VycmVudGx5XG5cdFx0Ly8gZm9yIHN0eWxlIGludGVncmF0aW9uIG9ubHlcblx0XHRpZiggdGhpcy5jLmJ1dHRvbkNyZWF0ZWQgKSB7XG5cdFx0XHRpbnNlcnRlciA9IHRoaXMuYy5idXR0b25DcmVhdGVkKCBjb25maWcsIGluc2VydGVyICk7XG5cdFx0fVxuXG5cdFx0dmFyIHNwbGl0RGl2O1xuXHRcdGlmKGlzU3BsaXQpIHtcblx0XHRcdHNwbGl0RGl2ID0gJCgnPGRpdi8+JykuYWRkQ2xhc3ModGhpcy5jLmRvbS5zcGxpdFdyYXBwZXIuY2xhc3NOYW1lKVxuXHRcdFx0c3BsaXREaXYuYXBwZW5kKGJ1dHRvbik7XG5cdFx0XHR2YXIgZHJvcEJ1dHRvbkNvbmZpZyA9ICQuZXh0ZW5kKGNvbmZpZywge1xuXHRcdFx0XHR0ZXh0OiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24udGV4dCxcblx0XHRcdFx0Y2xhc3NOYW1lOiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24uY2xhc3NOYW1lLFxuXHRcdFx0XHRjbG9zZUJ1dHRvbjogZmFsc2UsXG5cdFx0XHRcdGF0dHI6IHtcblx0XHRcdFx0XHQnYXJpYS1oYXNwb3B1cCc6ICdkaWFsb2cnLFxuXHRcdFx0XHRcdCdhcmlhLWV4cGFuZGVkJzogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0YWxpZ246IHRoaXMuYy5kb20uc3BsaXREcm9wZG93bi5hbGlnbixcblx0XHRcdFx0c3BsaXRBbGlnbkNsYXNzOiB0aGlzLmMuZG9tLnNwbGl0RHJvcGRvd24uc3BsaXRBbGlnbkNsYXNzXG5cdFx0XHRcdFxuXHRcdFx0fSlcblxuXHRcdFx0dGhpcy5fYWRkS2V5KGRyb3BCdXR0b25Db25maWcpO1xuXG5cdFx0XHR2YXIgc3BsaXRBY3Rpb24gPSBmdW5jdGlvbiAoIGUsIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdFx0X2R0QnV0dG9ucy5zcGxpdC5hY3Rpb24uY2FsbCggZHQuYnV0dG9uKCQoJ2Rpdi5kdC1idG4tc3BsaXQtd3JhcHBlcicpWzBdICksIGUsIGR0LCBidXR0b24sIGNvbmZpZyApO1xuXHRcblx0XHRcdFx0JChkdC50YWJsZSgpLm5vZGUoKSkudHJpZ2dlckhhbmRsZXIoICdidXR0b25zLWFjdGlvbi5kdCcsIFtcblx0XHRcdFx0XHRkdC5idXR0b24oIGJ1dHRvbiApLCBkdCwgYnV0dG9uLCBjb25maWcgXG5cdFx0XHRcdF0gKTtcblx0XHRcdFx0YnV0dG9uLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKVxuXHRcdFx0fTtcblx0XHRcdFxuXHRcdFx0dmFyIGRyb3BCdXR0b24gPSAkKCc8YnV0dG9uIGNsYXNzPVwiJyArIHRoaXMuYy5kb20uc3BsaXREcm9wZG93bi5jbGFzc05hbWUgKyAnIGR0LWJ1dHRvblwiPjxzcGFuIGNsYXNzPVwiZHQtYnRuLXNwbGl0LWRyb3AtYXJyb3dcIj4nK3RoaXMuYy5kb20uc3BsaXREcm9wZG93bi50ZXh0Kyc8L3NwYW4+PC9idXR0b24+Jylcblx0XHRcdFx0Lm9uKCAnY2xpY2suZHRiJywgZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdFx0XHRcdGlmICggISBkcm9wQnV0dG9uLmhhc0NsYXNzKCBidXR0b25Eb20uZGlzYWJsZWQgKSkge1xuXHRcdFx0XHRcdFx0c3BsaXRBY3Rpb24oIGUsIGR0LCBkcm9wQnV0dG9uLCBkcm9wQnV0dG9uQ29uZmlnICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggY2xpY2tCbHVycyApIHtcblx0XHRcdFx0XHRcdGRyb3BCdXR0b24udHJpZ2dlcignYmx1cicpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApXG5cdFx0XHRcdC5vbiggJ2tleXByZXNzLmR0YicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKCBlLmtleUNvZGUgPT09IDEzICkge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoICEgZHJvcEJ1dHRvbi5oYXNDbGFzcyggYnV0dG9uRG9tLmRpc2FibGVkICkgKSB7XG5cdFx0XHRcdFx0XHRcdHNwbGl0QWN0aW9uKCBlLCBkdCwgZHJvcEJ1dHRvbiwgZHJvcEJ1dHRvbkNvbmZpZyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHRpZihjb25maWcuc3BsaXQubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdGRyb3BCdXR0b24uYWRkQ2xhc3MoJ2R0Yi1oaWRlLWRyb3AnKTtcblx0XHRcdH1cblxuXHRcdFx0c3BsaXREaXYuYXBwZW5kKGRyb3BCdXR0b24pLmF0dHIoZHJvcEJ1dHRvbkNvbmZpZy5hdHRyKTtcblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29uZjogICAgICAgICBjb25maWcsXG5cdFx0XHRub2RlOiAgICAgICAgIGlzU3BsaXQgPyBzcGxpdERpdi5nZXQoMCkgOiBidXR0b24uZ2V0KDApLFxuXHRcdFx0aW5zZXJ0ZXI6ICAgICBpc1NwbGl0ID8gc3BsaXREaXYgOiBpbnNlcnRlcixcblx0XHRcdGJ1dHRvbnM6ICAgICAgW10sXG5cdFx0XHRpbkNvbGxlY3Rpb246IGluQ29sbGVjdGlvbixcblx0XHRcdGlzU3BsaXQ6XHQgIGlzU3BsaXQsXG5cdFx0XHRpblNwbGl0Olx0ICBpblNwbGl0LFxuXHRcdFx0Y29sbGVjdGlvbjogICBudWxsXG5cdFx0fTtcblx0fSxcblxuXHQvKipcblx0ICogR2V0IHRoZSBidXR0b24gb2JqZWN0IGZyb20gYSBub2RlIChyZWN1cnNpdmUpXG5cdCAqIEBwYXJhbSAge25vZGV9IG5vZGUgQnV0dG9uIG5vZGVcblx0ICogQHBhcmFtICB7YXJyYXl9IFtidXR0b25zXSBCdXR0b24gYXJyYXksIHVzZXMgYmFzZSBpZiBub3QgZGVmaW5lZFxuXHQgKiBAcmV0dXJuIHtvYmplY3R9IEJ1dHRvbiBvYmplY3Rcblx0ICogQHByaXZhdGVcblx0ICovXG5cdF9ub2RlVG9CdXR0b246IGZ1bmN0aW9uICggbm9kZSwgYnV0dG9ucyApXG5cdHtcblx0XHRpZiAoICEgYnV0dG9ucyApIHtcblx0XHRcdGJ1dHRvbnMgPSB0aGlzLnMuYnV0dG9ucztcblx0XHR9XG5cblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49YnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggYnV0dG9uc1tpXS5ub2RlID09PSBub2RlICkge1xuXHRcdFx0XHRyZXR1cm4gYnV0dG9uc1tpXTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBidXR0b25zW2ldLmJ1dHRvbnMubGVuZ3RoICkge1xuXHRcdFx0XHR2YXIgcmV0ID0gdGhpcy5fbm9kZVRvQnV0dG9uKCBub2RlLCBidXR0b25zW2ldLmJ1dHRvbnMgKTtcblxuXHRcdFx0XHRpZiAoIHJldCApIHtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8qKlxuXHQgKiBHZXQgY29udGFpbmVyIGFycmF5IGZvciBhIGJ1dHRvbiBmcm9tIGEgYnV0dG9uIG5vZGUgKHJlY3Vyc2l2ZSlcblx0ICogQHBhcmFtICB7bm9kZX0gbm9kZSBCdXR0b24gbm9kZVxuXHQgKiBAcGFyYW0gIHthcnJheX0gW2J1dHRvbnNdIEJ1dHRvbiBhcnJheSwgdXNlcyBiYXNlIGlmIG5vdCBkZWZpbmVkXG5cdCAqIEByZXR1cm4ge2FycmF5fSBCdXR0b24ncyBob3N0IGFycmF5XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfbm9kZVRvSG9zdDogZnVuY3Rpb24gKCBub2RlLCBidXR0b25zIClcblx0e1xuXHRcdGlmICggISBidXR0b25zICkge1xuXHRcdFx0YnV0dG9ucyA9IHRoaXMucy5idXR0b25zO1xuXHRcdH1cblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0aWYgKCBidXR0b25zW2ldLm5vZGUgPT09IG5vZGUgKSB7XG5cdFx0XHRcdHJldHVybiBidXR0b25zO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbnNbaV0uYnV0dG9ucy5sZW5ndGggKSB7XG5cdFx0XHRcdHZhciByZXQgPSB0aGlzLl9ub2RlVG9Ib3N0KCBub2RlLCBidXR0b25zW2ldLmJ1dHRvbnMgKTtcblxuXHRcdFx0XHRpZiAoIHJldCApIHtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8qKlxuXHQgKiBIYW5kbGUgYSBrZXkgcHJlc3MgLSBkZXRlcm1pbmUgaWYgYW55IGJ1dHRvbidzIGtleSBjb25maWd1cmVkIG1hdGNoZXNcblx0ICogd2hhdCB3YXMgdHlwZWQgYW5kIHRyaWdnZXIgdGhlIGFjdGlvbiBpZiBzby5cblx0ICogQHBhcmFtICB7c3RyaW5nfSBjaGFyYWN0ZXIgVGhlIGNoYXJhY3RlciBwcmVzc2VkXG5cdCAqIEBwYXJhbSAge29iamVjdH0gZSBLZXkgZXZlbnQgdGhhdCB0cmlnZ2VyZWQgdGhpcyBjYWxsXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfa2V5cHJlc3M6IGZ1bmN0aW9uICggY2hhcmFjdGVyLCBlIClcblx0e1xuXHRcdC8vIENoZWNrIGlmIHRoaXMgYnV0dG9uIHByZXNzIGFscmVhZHkgYWN0aXZhdGVkIG9uIGFub3RoZXIgaW5zdGFuY2Ugb2YgQnV0dG9uc1xuXHRcdGlmICggZS5fYnV0dG9uc0hhbmRsZWQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHJ1biA9IGZ1bmN0aW9uICggY29uZiwgbm9kZSApIHtcblx0XHRcdGlmICggISBjb25mLmtleSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGNvbmYua2V5ID09PSBjaGFyYWN0ZXIgKSB7XG5cdFx0XHRcdGUuX2J1dHRvbnNIYW5kbGVkID0gdHJ1ZTtcblx0XHRcdFx0JChub2RlKS5jbGljaygpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoICQuaXNQbGFpbk9iamVjdCggY29uZi5rZXkgKSApIHtcblx0XHRcdFx0aWYgKCBjb25mLmtleS5rZXkgIT09IGNoYXJhY3RlciApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5LnNoaWZ0S2V5ICYmICEgZS5zaGlmdEtleSApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5LmFsdEtleSAmJiAhIGUuYWx0S2V5ICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggY29uZi5rZXkuY3RybEtleSAmJiAhIGUuY3RybEtleSApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNvbmYua2V5Lm1ldGFLZXkgJiYgISBlLm1ldGFLZXkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTWFkZSBpdCB0aGlzIGZhciAtIGl0IGlzIGdvb2Rcblx0XHRcdFx0ZS5fYnV0dG9uc0hhbmRsZWQgPSB0cnVlO1xuXHRcdFx0XHQkKG5vZGUpLmNsaWNrKCk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHZhciByZWN1cnNlID0gZnVuY3Rpb24gKCBhICkge1xuXHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPWEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJ1biggYVtpXS5jb25mLCBhW2ldLm5vZGUgKTtcblxuXHRcdFx0XHRpZiAoIGFbaV0uYnV0dG9ucy5sZW5ndGggKSB7XG5cdFx0XHRcdFx0cmVjdXJzZSggYVtpXS5idXR0b25zICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0cmVjdXJzZSggdGhpcy5zLmJ1dHRvbnMgKTtcblx0fSxcblxuXHQvKipcblx0ICogUmVtb3ZlIGEga2V5IGZyb20gdGhlIGtleSBsaXN0ZW5lciBmb3IgdGhpcyBpbnN0YW5jZSAodG8gYmUgdXNlZCB3aGVuIGFcblx0ICogYnV0dG9uIGlzIHJlbW92ZWQpXG5cdCAqIEBwYXJhbSAge29iamVjdH0gY29uZiBCdXR0b24gY29uZmlndXJhdGlvblxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X3JlbW92ZUtleTogZnVuY3Rpb24gKCBjb25mIClcblx0e1xuXHRcdGlmICggY29uZi5rZXkgKSB7XG5cdFx0XHR2YXIgY2hhcmFjdGVyID0gJC5pc1BsYWluT2JqZWN0KCBjb25mLmtleSApID9cblx0XHRcdFx0Y29uZi5rZXkua2V5IDpcblx0XHRcdFx0Y29uZi5rZXk7XG5cblx0XHRcdC8vIFJlbW92ZSBvbmx5IG9uZSBjaGFyYWN0ZXIsIGFzIG11bHRpcGxlIGJ1dHRvbnMgY291bGQgaGF2ZSB0aGVcblx0XHRcdC8vIHNhbWUgbGlzdGVuaW5nIGtleVxuXHRcdFx0dmFyIGEgPSB0aGlzLnMubGlzdGVuS2V5cy5zcGxpdCgnJyk7XG5cdFx0XHR2YXIgaWR4ID0gJC5pbkFycmF5KCBjaGFyYWN0ZXIsIGEgKTtcblx0XHRcdGEuc3BsaWNlKCBpZHgsIDEgKTtcblx0XHRcdHRoaXMucy5saXN0ZW5LZXlzID0gYS5qb2luKCcnKTtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJlc29sdmUgYSBidXR0b24gY29uZmlndXJhdGlvblxuXHQgKiBAcGFyYW0gIHtzdHJpbmd8ZnVuY3Rpb258b2JqZWN0fSBjb25mIEJ1dHRvbiBjb25maWcgdG8gcmVzb2x2ZVxuXHQgKiBAcmV0dXJuIHtvYmplY3R9IEJ1dHRvbiBjb25maWd1cmF0aW9uXG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRfcmVzb2x2ZUV4dGVuZHM6IGZ1bmN0aW9uICggY29uZiApXG5cdHtcblx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFx0dmFyIGR0ID0gdGhpcy5zLmR0O1xuXHRcdHZhciBpLCBpZW47XG5cdFx0dmFyIHRvQ29uZk9iamVjdCA9IGZ1bmN0aW9uICggYmFzZSApIHtcblx0XHRcdHZhciBsb29wID0gMDtcblxuXHRcdFx0Ly8gTG9vcCB1bnRpbCB3ZSBoYXZlIHJlc29sdmVkIHRvIGEgYnV0dG9uIGNvbmZpZ3VyYXRpb24sIG9yIGFuXG5cdFx0XHQvLyBhcnJheSBvZiBidXR0b24gY29uZmlndXJhdGlvbnMgKHdoaWNoIHdpbGwgYmUgaXRlcmF0ZWRcblx0XHRcdC8vIHNlcGFyYXRlbHkpXG5cdFx0XHR3aGlsZSAoICEgJC5pc1BsYWluT2JqZWN0KGJhc2UpICYmICEgQXJyYXkuaXNBcnJheShiYXNlKSApIHtcblx0XHRcdFx0aWYgKCBiYXNlID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCB0eXBlb2YgYmFzZSA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0XHRiYXNlID0gYmFzZS5jYWxsKCB0aGF0LCBkdCwgY29uZiApO1xuXG5cdFx0XHRcdFx0aWYgKCAhIGJhc2UgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKCB0eXBlb2YgYmFzZSA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHRcdFx0aWYgKCAhIF9kdEJ1dHRvbnNbIGJhc2UgXSApIHtcblx0XHRcdFx0XHRcdHJldHVybiB7aHRtbDogYmFzZX1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRiYXNlID0gX2R0QnV0dG9uc1sgYmFzZSBdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0bG9vcCsrO1xuXHRcdFx0XHRpZiAoIGxvb3AgPiAzMCApIHtcblx0XHRcdFx0XHQvLyBQcm90ZWN0IGFnYWluc3QgbWlzY29uZmlndXJhdGlvbiBraWxsaW5nIHRoZSBicm93c2VyXG5cdFx0XHRcdFx0dGhyb3cgJ0J1dHRvbnM6IFRvbyBtYW55IGl0ZXJhdGlvbnMnO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBBcnJheS5pc0FycmF5KCBiYXNlICkgP1xuXHRcdFx0XHRiYXNlIDpcblx0XHRcdFx0JC5leHRlbmQoIHt9LCBiYXNlICk7XG5cdFx0fTtcblxuXHRcdGNvbmYgPSB0b0NvbmZPYmplY3QoIGNvbmYgKTtcblxuXHRcdHdoaWxlICggY29uZiAmJiBjb25mLmV4dGVuZCApIHtcblx0XHRcdC8vIFVzZSBgdG9Db25mT2JqZWN0YCBpbiBjYXNlIHRoZSBidXR0b24gZGVmaW5pdGlvbiBiZWluZyBleHRlbmRlZFxuXHRcdFx0Ly8gaXMgaXRzZWxmIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb25cblx0XHRcdGlmICggISBfZHRCdXR0b25zWyBjb25mLmV4dGVuZCBdICkge1xuXHRcdFx0XHR0aHJvdyAnQ2Fubm90IGV4dGVuZCB1bmtub3duIGJ1dHRvbiB0eXBlOiAnK2NvbmYuZXh0ZW5kO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgb2JqQXJyYXkgPSB0b0NvbmZPYmplY3QoIF9kdEJ1dHRvbnNbIGNvbmYuZXh0ZW5kIF0gKTtcblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggb2JqQXJyYXkgKSApIHtcblx0XHRcdFx0cmV0dXJuIG9iakFycmF5O1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoICEgb2JqQXJyYXkgKSB7XG5cdFx0XHRcdC8vIFRoaXMgaXMgYSBsaXR0bGUgYnJ1dGFsIGFzIGl0IG1pZ2h0IGJlIHBvc3NpYmxlIHRvIGhhdmUgYVxuXHRcdFx0XHQvLyB2YWxpZCBidXR0b24gd2l0aG91dCB0aGUgZXh0ZW5kLCBidXQgaWYgdGhlcmUgaXMgbm8gZXh0ZW5kXG5cdFx0XHRcdC8vIHRoZW4gdGhlIGhvc3QgYnV0dG9uIHdvdWxkIGJlIGFjdGluZyBpbiBhbiB1bmRlZmluZWQgc3RhdGVcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFzaCB0aGUgY3VycmVudCBjbGFzcyBuYW1lXG5cdFx0XHR2YXIgb3JpZ2luYWxDbGFzc05hbWUgPSBvYmpBcnJheS5jbGFzc05hbWU7XG5cblx0XHRcdGlmIChjb25mLmNvbmZpZyAhPT0gdW5kZWZpbmVkICYmIG9iakFycmF5LmNvbmZpZyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGNvbmYuY29uZmlnID0gJC5leHRlbmQoe30sIG9iakFycmF5LmNvbmZpZywgY29uZi5jb25maWcpXG5cdFx0XHR9XG5cblx0XHRcdGNvbmYgPSAkLmV4dGVuZCgge30sIG9iakFycmF5LCBjb25mICk7XG5cblx0XHRcdC8vIFRoZSBleHRlbmQgd2lsbCBoYXZlIG92ZXJ3cml0dGVuIHRoZSBvcmlnaW5hbCBjbGFzcyBuYW1lIGlmIHRoZVxuXHRcdFx0Ly8gYGNvbmZgIG9iamVjdCBhbHNvIGFzc2lnbmVkIGEgY2xhc3MsIGJ1dCB3ZSB3YW50IHRvIGNvbmNhdGVuYXRlXG5cdFx0XHQvLyB0aGVtIHNvIHRoZXkgYXJlIGxpc3QgdGhhdCBpcyBjb21iaW5lZCBmcm9tIGFsbCBleHRlbmRlZCBidXR0b25zXG5cdFx0XHRpZiAoIG9yaWdpbmFsQ2xhc3NOYW1lICYmIGNvbmYuY2xhc3NOYW1lICE9PSBvcmlnaW5hbENsYXNzTmFtZSApIHtcblx0XHRcdFx0Y29uZi5jbGFzc05hbWUgPSBvcmlnaW5hbENsYXNzTmFtZSsnICcrY29uZi5jbGFzc05hbWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEJ1dHRvbnMgdG8gYmUgYWRkZWQgdG8gYSBjb2xsZWN0aW9uICAtZ2l2ZXMgdGhlIGFiaWxpdHkgdG8gZGVmaW5lXG5cdFx0XHQvLyBpZiBidXR0b25zIHNob3VsZCBiZSBhZGRlZCB0byB0aGUgc3RhcnQgb3IgZW5kIG9mIGEgY29sbGVjdGlvblxuXHRcdFx0dmFyIHBvc3RmaXhCdXR0b25zID0gY29uZi5wb3N0Zml4QnV0dG9ucztcblx0XHRcdGlmICggcG9zdGZpeEJ1dHRvbnMgKSB7XG5cdFx0XHRcdGlmICggISBjb25mLmJ1dHRvbnMgKSB7XG5cdFx0XHRcdFx0Y29uZi5idXR0b25zID0gW107XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRmb3IgKCBpPTAsIGllbj1wb3N0Zml4QnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRjb25mLmJ1dHRvbnMucHVzaCggcG9zdGZpeEJ1dHRvbnNbaV0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbmYucG9zdGZpeEJ1dHRvbnMgPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgcHJlZml4QnV0dG9ucyA9IGNvbmYucHJlZml4QnV0dG9ucztcblx0XHRcdGlmICggcHJlZml4QnV0dG9ucyApIHtcblx0XHRcdFx0aWYgKCAhIGNvbmYuYnV0dG9ucyApIHtcblx0XHRcdFx0XHRjb25mLmJ1dHRvbnMgPSBbXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPXByZWZpeEJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0Y29uZi5idXR0b25zLnNwbGljZSggaSwgMCwgcHJlZml4QnV0dG9uc1tpXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uZi5wcmVmaXhCdXR0b25zID0gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWx0aG91Z2ggd2Ugd2FudCB0aGUgYGNvbmZgIG9iamVjdCB0byBvdmVyd3JpdGUgYWxtb3N0IGFsbCBvZlxuXHRcdFx0Ly8gdGhlIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdCBiZWluZyBleHRlbmRlZCwgdGhlIGBleHRlbmRgXG5cdFx0XHQvLyBwcm9wZXJ0eSBzaG91bGQgY29tZSBmcm9tIHRoZSBvYmplY3QgYmVpbmcgZXh0ZW5kZWRcblx0XHRcdGNvbmYuZXh0ZW5kID0gb2JqQXJyYXkuZXh0ZW5kO1xuXHRcdH1cblxuXHRcdHJldHVybiBjb25mO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBEaXNwbGF5IChhbmQgcmVwbGFjZSBpZiB0aGVyZSBpcyBhbiBleGlzdGluZyBvbmUpIGEgcG9wb3ZlciBhdHRhY2hlZCB0byBhIGJ1dHRvblxuXHQgKiBAcGFyYW0ge3N0cmluZ3xub2RlfSBjb250ZW50IENvbnRlbnQgdG8gc2hvd1xuXHQgKiBAcGFyYW0ge0RhdGFUYWJsZS5BcGl9IGhvc3RCdXR0b24gRFQgQVBJIGluc3RhbmNlIG9mIHRoZSBidXR0b25cblx0ICogQHBhcmFtIHtvYmplY3R9IGluT3B0cyBPcHRpb25zIChzZWUgb2JqZWN0IGJlbG93IGZvciBhbGwgb3B0aW9ucylcblx0ICovXG5cdF9wb3BvdmVyOiBmdW5jdGlvbiAoIGNvbnRlbnQsIGhvc3RCdXR0b24sIGluT3B0cywgZSApIHtcblx0XHR2YXIgZHQgPSBob3N0QnV0dG9uO1xuXHRcdHZhciBidXR0b25zU2V0dGluZ3MgPSB0aGlzLmM7XG5cdFx0dmFyIGNsb3NlZCA9IGZhbHNlO1xuXHRcdHZhciBvcHRpb25zID0gJC5leHRlbmQoIHtcblx0XHRcdGFsaWduOiAnYnV0dG9uLWxlZnQnLCAvLyBidXR0b24tcmlnaHQsIGR0LWNvbnRhaW5lciwgc3BsaXQtbGVmdCwgc3BsaXQtcmlnaHRcblx0XHRcdGF1dG9DbG9zZTogZmFsc2UsXG5cdFx0XHRiYWNrZ3JvdW5kOiB0cnVlLFxuXHRcdFx0YmFja2dyb3VuZENsYXNzTmFtZTogJ2R0LWJ1dHRvbi1iYWNrZ3JvdW5kJyxcblx0XHRcdGNsb3NlQnV0dG9uOiB0cnVlLFxuXHRcdFx0Y29udGVudENsYXNzTmFtZTogYnV0dG9uc1NldHRpbmdzLmRvbS5jb2xsZWN0aW9uLmNsYXNzTmFtZSxcblx0XHRcdGNvbGxlY3Rpb25MYXlvdXQ6ICcnLFxuXHRcdFx0Y29sbGVjdGlvblRpdGxlOiAnJyxcblx0XHRcdGRyb3B1cDogZmFsc2UsXG5cdFx0XHRmYWRlOiA0MDAsXG5cdFx0XHRwb3BvdmVyVGl0bGU6ICcnLFxuXHRcdFx0cmlnaHRBbGlnbkNsYXNzTmFtZTogJ2R0LWJ1dHRvbi1yaWdodCcsXG5cdFx0XHR0YWc6IGJ1dHRvbnNTZXR0aW5ncy5kb20uY29sbGVjdGlvbi50YWdcblx0XHR9LCBpbk9wdHMgKTtcblxuXHRcdHZhciBob3N0Tm9kZSA9IGhvc3RCdXR0b24ubm9kZSgpO1xuXG5cdFx0dmFyIGNsb3NlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0Y2xvc2VkID0gdHJ1ZTtcblxuXHRcdFx0X2ZhZGVPdXQoXG5cdFx0XHRcdCQoJy5kdC1idXR0b24tY29sbGVjdGlvbicpLFxuXHRcdFx0XHRvcHRpb25zLmZhZGUsXG5cdFx0XHRcdGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHQkKHRoaXMpLmRldGFjaCgpO1xuXHRcdFx0XHR9XG5cdFx0XHQpO1xuXG5cdFx0XHQkKGR0LmJ1dHRvbnMoICdbYXJpYS1oYXNwb3B1cD1cImRpYWxvZ1wiXVthcmlhLWV4cGFuZGVkPVwidHJ1ZVwiXScgKS5ub2RlcygpKVxuXHRcdFx0XHQuYXR0cignYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXG5cdFx0XHQkKCdkaXYuZHQtYnV0dG9uLWJhY2tncm91bmQnKS5vZmYoICdjbGljay5kdGItY29sbGVjdGlvbicgKTtcblx0XHRcdEJ1dHRvbnMuYmFja2dyb3VuZCggZmFsc2UsIG9wdGlvbnMuYmFja2dyb3VuZENsYXNzTmFtZSwgb3B0aW9ucy5mYWRlLCBob3N0Tm9kZSApO1xuXG5cdFx0XHQkKHdpbmRvdykub2ZmKCdyZXNpemUucmVzaXplLmR0Yi1jb2xsZWN0aW9uJyk7XG5cdFx0XHQkKCdib2R5Jykub2ZmKCAnLmR0Yi1jb2xsZWN0aW9uJyApO1xuXHRcdFx0ZHQub2ZmKCAnYnV0dG9ucy1hY3Rpb24uYi1pbnRlcm5hbCcgKTtcblx0XHRcdGR0Lm9mZiggJ2Rlc3Ryb3knICk7XG5cdFx0fTtcblxuXHRcdGlmIChjb250ZW50ID09PSBmYWxzZSkge1xuXHRcdFx0Y2xvc2UoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgZXhpc3RpbmdFeHBhbmRlZCA9ICQoZHQuYnV0dG9ucyggJ1thcmlhLWhhc3BvcHVwPVwiZGlhbG9nXCJdW2FyaWEtZXhwYW5kZWQ9XCJ0cnVlXCJdJyApLm5vZGVzKCkpO1xuXHRcdGlmICggZXhpc3RpbmdFeHBhbmRlZC5sZW5ndGggKSB7XG5cdFx0XHQvLyBSZXVzZSB0aGUgY3VycmVudCBwb3NpdGlvbiBpZiB0aGUgYnV0dG9uIHRoYXQgd2FzIHRyaWdnZXJlZCBpcyBpbnNpZGUgYW4gZXhpc3RpbmcgY29sbGVjdGlvblxuXHRcdFx0aWYgKGhvc3ROb2RlLmNsb3Nlc3QoJ2Rpdi5kdC1idXR0b24tY29sbGVjdGlvbicpLmxlbmd0aCkge1xuXHRcdFx0XHRob3N0Tm9kZSA9IGV4aXN0aW5nRXhwYW5kZWQuZXEoMCk7XG5cdFx0XHR9XG5cblx0XHRcdGNsb3NlKCk7XG5cdFx0fVxuXG5cdFx0Ly8gVHJ5IHRvIGJlIHNtYXJ0IGFib3V0IHRoZSBsYXlvdXRcblx0XHR2YXIgY250ID0gJCgnLmR0LWJ1dHRvbicsIGNvbnRlbnQpLmxlbmd0aDtcblx0XHR2YXIgbW9kID0gJyc7XG5cblx0XHRpZiAoY250ID09PSAzKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIzJztcblx0XHR9XG5cdFx0ZWxzZSBpZiAoY250ID09PSAyKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIyJztcblx0XHR9XG5cdFx0ZWxzZSBpZiAoY250ID09PSAxKSB7XG5cdFx0XHRtb2QgPSAnZHRiLWIxJztcblx0XHR9XG5cblx0XHR2YXIgZGlzcGxheSA9ICQoJzxkaXYvPicpXG5cdFx0XHQuYWRkQ2xhc3MoJ2R0LWJ1dHRvbi1jb2xsZWN0aW9uJylcblx0XHRcdC5hZGRDbGFzcyhvcHRpb25zLmNvbGxlY3Rpb25MYXlvdXQpXG5cdFx0XHQuYWRkQ2xhc3Mob3B0aW9ucy5zcGxpdEFsaWduQ2xhc3MpXG5cdFx0XHQuYWRkQ2xhc3MobW9kKVxuXHRcdFx0LmNzcygnZGlzcGxheScsICdub25lJylcblx0XHRcdC5hdHRyKHtcblx0XHRcdFx0J2FyaWEtbW9kYWwnOiB0cnVlLFxuXHRcdFx0XHRyb2xlOiAnZGlhbG9nJ1xuXHRcdFx0fSk7XG5cblx0XHRjb250ZW50ID0gJChjb250ZW50KVxuXHRcdFx0LmFkZENsYXNzKG9wdGlvbnMuY29udGVudENsYXNzTmFtZSlcblx0XHRcdC5hdHRyKCdyb2xlJywgJ21lbnUnKVxuXHRcdFx0LmFwcGVuZFRvKGRpc3BsYXkpO1xuXG5cdFx0aG9zdE5vZGUuYXR0ciggJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScgKTtcblxuXHRcdGlmICggaG9zdE5vZGUucGFyZW50cygnYm9keScpWzBdICE9PSBkb2N1bWVudC5ib2R5ICkge1xuXHRcdFx0aG9zdE5vZGUgPSBkb2N1bWVudC5ib2R5Lmxhc3RDaGlsZDtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMucG9wb3ZlclRpdGxlICkge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHQtYnV0dG9uLWNvbGxlY3Rpb24tdGl0bGVcIj4nK29wdGlvbnMucG9wb3ZlclRpdGxlKyc8L2Rpdj4nKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG9wdGlvbnMuY29sbGVjdGlvblRpdGxlICkge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHQtYnV0dG9uLWNvbGxlY3Rpb24tdGl0bGVcIj4nK29wdGlvbnMuY29sbGVjdGlvblRpdGxlKyc8L2Rpdj4nKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5jbG9zZUJ1dHRvbikge1xuXHRcdFx0ZGlzcGxheS5wcmVwZW5kKCc8ZGl2IGNsYXNzPVwiZHRiLXBvcG92ZXItY2xvc2VcIj54PC9kaXY+JykuYWRkQ2xhc3MoJ2R0Yi1jb2xsZWN0aW9uLWNsb3NlYWJsZScpXG5cdFx0fVxuXG5cdFx0X2ZhZGVJbiggZGlzcGxheS5pbnNlcnRBZnRlciggaG9zdE5vZGUgKSwgb3B0aW9ucy5mYWRlICk7XG5cblx0XHR2YXIgdGFibGVDb250YWluZXIgPSAkKCBob3N0QnV0dG9uLnRhYmxlKCkuY29udGFpbmVyKCkgKTtcblx0XHR2YXIgcG9zaXRpb24gPSBkaXNwbGF5LmNzcyggJ3Bvc2l0aW9uJyApO1xuXG5cdFx0aWYgKCBvcHRpb25zLnNwYW4gPT09ICdjb250YWluZXInIHx8IG9wdGlvbnMuYWxpZ24gPT09ICdkdC1jb250YWluZXInICkge1xuXHRcdFx0aG9zdE5vZGUgPSBob3N0Tm9kZS5wYXJlbnQoKTtcblx0XHRcdGRpc3BsYXkuY3NzKCd3aWR0aCcsIHRhYmxlQ29udGFpbmVyLndpZHRoKCkpO1xuXHRcdH1cblxuXHRcdC8vIEFsaWduIHRoZSBwb3BvdmVyIHJlbGF0aXZlIHRvIHRoZSBEYXRhVGFibGVzIGNvbnRhaW5lclxuXHRcdC8vIFVzZWZ1bCBmb3Igd2lkZSBwb3BvdmVycyBzdWNoIGFzIFNlYXJjaFBhbmVzXG5cdFx0aWYgKHBvc2l0aW9uID09PSAnYWJzb2x1dGUnKSB7XG5cdFx0XHQvLyBBbGlnbiByZWxhdGl2ZSB0byB0aGUgaG9zdCBidXR0b25cblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSAkKGhvc3ROb2RlWzBdLm9mZnNldFBhcmVudCk7XG5cdFx0XHR2YXIgYnV0dG9uUG9zaXRpb24gPSBob3N0Tm9kZS5wb3NpdGlvbigpO1xuXHRcdFx0dmFyIGJ1dHRvbk9mZnNldCA9IGhvc3ROb2RlLm9mZnNldCgpO1xuXHRcdFx0dmFyIHRhYmxlU2l6ZXMgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR2YXIgY29udGFpbmVyUG9zaXRpb24gPSBvZmZzZXRQYXJlbnQucG9zaXRpb24oKTtcblx0XHRcdHZhciBjb21wdXRlZCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKG9mZnNldFBhcmVudFswXSk7XG5cblx0XHRcdHRhYmxlU2l6ZXMuaGVpZ2h0ID0gb2Zmc2V0UGFyZW50Lm91dGVySGVpZ2h0KCk7XG5cdFx0XHR0YWJsZVNpemVzLndpZHRoID0gb2Zmc2V0UGFyZW50LndpZHRoKCkgKyBwYXJzZUZsb2F0KGNvbXB1dGVkLnBhZGRpbmdMZWZ0KTtcblx0XHRcdHRhYmxlU2l6ZXMucmlnaHQgPSB0YWJsZVNpemVzLmxlZnQgKyB0YWJsZVNpemVzLndpZHRoO1xuXHRcdFx0dGFibGVTaXplcy5ib3R0b20gPSB0YWJsZVNpemVzLnRvcCArIHRhYmxlU2l6ZXMuaGVpZ2h0O1xuXG5cdFx0XHQvLyBTZXQgdGhlIGluaXRpYWwgcG9zaXRpb24gc28gd2UgY2FuIHJlYWQgaGVpZ2h0IC8gd2lkdGhcblx0XHRcdHZhciB0b3AgPSBidXR0b25Qb3NpdGlvbi50b3AgKyBob3N0Tm9kZS5vdXRlckhlaWdodCgpO1xuXHRcdFx0dmFyIGxlZnQgPSBidXR0b25Qb3NpdGlvbi5sZWZ0O1xuXG5cdFx0XHRkaXNwbGF5LmNzcygge1xuXHRcdFx0XHR0b3A6IHRvcCxcblx0XHRcdFx0bGVmdDogbGVmdFxuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyBHZXQgdGhlIHBvcG92ZXIgcG9zaXRpb25cblx0XHRcdGNvbXB1dGVkID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZGlzcGxheVswXSk7XG5cdFx0XHR2YXIgcG9wb3ZlclNpemVzID0gZGlzcGxheS5vZmZzZXQoKTtcblxuXHRcdFx0cG9wb3ZlclNpemVzLmhlaWdodCA9IGRpc3BsYXkub3V0ZXJIZWlnaHQoKTtcblx0XHRcdHBvcG92ZXJTaXplcy53aWR0aCA9IGRpc3BsYXkub3V0ZXJXaWR0aCgpO1xuXHRcdFx0cG9wb3ZlclNpemVzLnJpZ2h0ID0gcG9wb3ZlclNpemVzLmxlZnQgKyBwb3BvdmVyU2l6ZXMud2lkdGg7XG5cdFx0XHRwb3BvdmVyU2l6ZXMuYm90dG9tID0gcG9wb3ZlclNpemVzLnRvcCArIHBvcG92ZXJTaXplcy5oZWlnaHQ7XG5cdFx0XHRwb3BvdmVyU2l6ZXMubWFyZ2luVG9wID0gcGFyc2VGbG9hdChjb21wdXRlZC5tYXJnaW5Ub3ApO1xuXHRcdFx0cG9wb3ZlclNpemVzLm1hcmdpbkJvdHRvbSA9IHBhcnNlRmxvYXQoY29tcHV0ZWQubWFyZ2luQm90dG9tKTtcblxuXHRcdFx0Ly8gRmlyc3QgcG9zaXRpb24gcGVyIHRoZSBjbGFzcyByZXF1aXJlbWVudHMgLSBwb3AgdXAgYW5kIHJpZ2h0IGFsaWduXG5cdFx0XHRpZiAob3B0aW9ucy5kcm9wdXApIHtcblx0XHRcdFx0dG9wID0gYnV0dG9uUG9zaXRpb24udG9wIC0gcG9wb3ZlclNpemVzLmhlaWdodCAtIHBvcG92ZXJTaXplcy5tYXJnaW5Ub3AgLSBwb3BvdmVyU2l6ZXMubWFyZ2luQm90dG9tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAob3B0aW9ucy5hbGlnbiA9PT0gJ2J1dHRvbi1yaWdodCcgfHwgZGlzcGxheS5oYXNDbGFzcyggb3B0aW9ucy5yaWdodEFsaWduQ2xhc3NOYW1lICkpIHtcblx0XHRcdFx0bGVmdCA9IGJ1dHRvblBvc2l0aW9uLmxlZnQgLSBwb3BvdmVyU2l6ZXMud2lkdGggKyBob3N0Tm9kZS5vdXRlcldpZHRoKCk7IFxuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb250YWluZXIgYWxpZ25tZW50IC0gbWFrZSBzdXJlIGl0IGRvZXNuJ3Qgb3ZlcmZsb3cgdGhlIHRhYmxlIGNvbnRhaW5lclxuXHRcdFx0aWYgKG9wdGlvbnMuYWxpZ24gPT09ICdkdC1jb250YWluZXInIHx8IG9wdGlvbnMuYWxpZ24gPT09ICdjb250YWluZXInKSB7XG5cdFx0XHRcdGlmIChsZWZ0IDwgYnV0dG9uUG9zaXRpb24ubGVmdCkge1xuXHRcdFx0XHRcdGxlZnQgPSAtYnV0dG9uUG9zaXRpb24ubGVmdDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChsZWZ0ICsgcG9wb3ZlclNpemVzLndpZHRoID4gdGFibGVTaXplcy53aWR0aCkge1xuXHRcdFx0XHRcdGxlZnQgPSB0YWJsZVNpemVzLndpZHRoIC0gcG9wb3ZlclNpemVzLndpZHRoO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdpbmRvdyBhZGp1c3RtZW50XG5cdFx0XHRpZiAoY29udGFpbmVyUG9zaXRpb24ubGVmdCArIGxlZnQgKyBwb3BvdmVyU2l6ZXMud2lkdGggPiAkKHdpbmRvdykud2lkdGgoKSkge1xuXHRcdFx0XHQvLyBPdmVyZmxvd2luZyB0aGUgZG9jdW1lbnQgdG8gdGhlIHJpZ2h0XG5cdFx0XHRcdGxlZnQgPSAkKHdpbmRvdykud2lkdGgoKSAtIHBvcG92ZXJTaXplcy53aWR0aCAtIGNvbnRhaW5lclBvc2l0aW9uLmxlZnQ7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChidXR0b25PZmZzZXQubGVmdCArIGxlZnQgPCAwKSB7XG5cdFx0XHRcdC8vIE9mZiB0byB0aGUgbGVmdCBvZiB0aGUgZG9jdW1lbnRcblx0XHRcdFx0bGVmdCA9IC1idXR0b25PZmZzZXQubGVmdDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNvbnRhaW5lclBvc2l0aW9uLnRvcCArIHRvcCArIHBvcG92ZXJTaXplcy5oZWlnaHQgPiAkKHdpbmRvdykuaGVpZ2h0KCkgKyAkKHdpbmRvdykuc2Nyb2xsVG9wKCkpIHtcblx0XHRcdFx0Ly8gUG9wIHVwIGlmIG90aGVyd2lzZSB3ZSdkIG5lZWQgdGhlIHVzZXIgdG8gc2Nyb2xsIGRvd25cblx0XHRcdFx0dG9wID0gYnV0dG9uUG9zaXRpb24udG9wIC0gcG9wb3ZlclNpemVzLmhlaWdodCAtIHBvcG92ZXJTaXplcy5tYXJnaW5Ub3AgLSBwb3BvdmVyU2l6ZXMubWFyZ2luQm90dG9tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY29udGFpbmVyUG9zaXRpb24udG9wICsgdG9wIDwgJCh3aW5kb3cpLnNjcm9sbFRvcCgpKSB7XG5cdFx0XHRcdC8vIENvcnJlY3Rpb24gZm9yIHdoZW4gdGhlIHRvcCBpcyBiZXlvbmQgdGhlIHRvcCBvZiB0aGUgcGFnZVxuXHRcdFx0XHR0b3AgPSBidXR0b25Qb3NpdGlvbi50b3AgKyBob3N0Tm9kZS5vdXRlckhlaWdodCgpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYWxjdWxhdGlvbnMgYWxsIGRvbmUgLSBub3cgc2V0IGl0XG5cdFx0XHRkaXNwbGF5LmNzcygge1xuXHRcdFx0XHR0b3A6IHRvcCxcblx0XHRcdFx0bGVmdDogbGVmdFxuXHRcdFx0fSApO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdC8vIEZpeCBwb3NpdGlvbiAtIGNlbnRyZSBvbiBzY3JlZW5cblx0XHRcdHZhciBwb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dmFyIGhhbGYgPSAkKHdpbmRvdykuaGVpZ2h0KCkgLyAyO1xuXG5cdFx0XHRcdHZhciB0b3AgPSBkaXNwbGF5LmhlaWdodCgpIC8gMjtcblx0XHRcdFx0aWYgKCB0b3AgPiBoYWxmICkge1xuXHRcdFx0XHRcdHRvcCA9IGhhbGY7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkaXNwbGF5LmNzcyggJ21hcmdpblRvcCcsIHRvcCotMSApO1xuXHRcdFx0fTtcblxuXHRcdFx0cG9zaXRpb24oKTtcblxuXHRcdFx0JCh3aW5kb3cpLm9uKCdyZXNpemUuZHRiLWNvbGxlY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHBvc2l0aW9uKCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAoIG9wdGlvbnMuYmFja2dyb3VuZCApIHtcblx0XHRcdEJ1dHRvbnMuYmFja2dyb3VuZChcblx0XHRcdFx0dHJ1ZSxcblx0XHRcdFx0b3B0aW9ucy5iYWNrZ3JvdW5kQ2xhc3NOYW1lLFxuXHRcdFx0XHRvcHRpb25zLmZhZGUsXG5cdFx0XHRcdG9wdGlvbnMuYmFja2dyb3VuZEhvc3QgfHwgaG9zdE5vZGVcblx0XHRcdCk7XG5cdFx0fVxuXG5cdFx0Ly8gVGhpcyBpcyBib25rZXJzLCBidXQgaWYgd2UgZG9uJ3QgaGF2ZSBhIGNsaWNrIGxpc3RlbmVyIG9uIHRoZVxuXHRcdC8vIGJhY2tncm91bmQgZWxlbWVudCwgaU9TIFNhZmFyaSB3aWxsIGlnbm9yZSB0aGUgYm9keSBjbGlja1xuXHRcdC8vIGxpc3RlbmVyIGJlbG93LiBBbiBlbXB0eSBmdW5jdGlvbiBoZXJlIGlzIGFsbCB0aGF0IGlzXG5cdFx0Ly8gcmVxdWlyZWQgdG8gbWFrZSBpdCB3b3JrLi4uXG5cdFx0JCgnZGl2LmR0LWJ1dHRvbi1iYWNrZ3JvdW5kJykub24oICdjbGljay5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uICgpIHt9ICk7XG5cblx0XHRpZiAoIG9wdGlvbnMuYXV0b0Nsb3NlICkge1xuXHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRkdC5vbiggJ2J1dHRvbnMtYWN0aW9uLmItaW50ZXJuYWwnLCBmdW5jdGlvbiAoZSwgYnRuLCBkdCwgbm9kZSkge1xuXHRcdFx0XHRcdGlmICggbm9kZVswXSA9PT0gaG9zdE5vZGVbMF0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH0sIDApO1xuXHRcdH1cblx0XHRcblx0XHQkKGRpc3BsYXkpLnRyaWdnZXIoJ2J1dHRvbnMtcG9wb3Zlci5kdCcpO1xuXG5cblx0XHRkdC5vbignZGVzdHJveScsIGNsb3NlKTtcblxuXHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRjbG9zZWQgPSBmYWxzZTtcblx0XHRcdCQoJ2JvZHknKVxuXHRcdFx0XHQub24oICdjbGljay5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0aWYgKGNsb3NlZCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIGFuZFNlbGYgaXMgZGVwcmVjYXRlZCBpbiBqUTEuOCwgYnV0IHdlIHdhbnQgMS43IGNvbXBhdFxuXHRcdFx0XHRcdHZhciBiYWNrID0gJC5mbi5hZGRCYWNrID8gJ2FkZEJhY2snIDogJ2FuZFNlbGYnO1xuXHRcdFx0XHRcdHZhciBwYXJlbnQgPSAkKGUudGFyZ2V0KS5wYXJlbnQoKVswXTtcblx0XG5cdFx0XHRcdFx0aWYgKCggISAkKGUudGFyZ2V0KS5wYXJlbnRzKClbYmFja10oKS5maWx0ZXIoIGNvbnRlbnQgKS5sZW5ndGggICYmICEkKHBhcmVudCkuaGFzQ2xhc3MoJ2R0LWJ1dHRvbnMnKSkgfHwgJChlLnRhcmdldCkuaGFzQ2xhc3MoJ2R0LWJ1dHRvbi1iYWNrZ3JvdW5kJykpIHtcblx0XHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IClcblx0XHRcdFx0Lm9uKCAna2V5dXAuZHRiLWNvbGxlY3Rpb24nLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHRcdGlmICggZS5rZXlDb2RlID09PSAyNyApIHtcblx0XHRcdFx0XHRcdGNsb3NlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IClcblx0XHRcdFx0Lm9uKCAna2V5ZG93bi5kdGItY29sbGVjdGlvbicsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0Ly8gRm9jdXMgdHJhcCBmb3IgdGFiIGtleVxuXHRcdFx0XHRcdHZhciBlbGVtZW50cyA9ICQoJ2EsIGJ1dHRvbicsIGNvbnRlbnQpO1xuXHRcdFx0XHRcdHZhciBhY3RpdmUgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuXG5cdFx0XHRcdFx0aWYgKGUua2V5Q29kZSAhPT0gOSkgeyAvLyB0YWJcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZWxlbWVudHMuaW5kZXgoYWN0aXZlKSA9PT0gLTEpIHtcblx0XHRcdFx0XHRcdC8vIElmIGN1cnJlbnQgZm9jdXMgaXMgbm90IGluc2lkZSB0aGUgcG9wb3ZlclxuXHRcdFx0XHRcdFx0ZWxlbWVudHMuZmlyc3QoKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmIChlLnNoaWZ0S2V5KSB7XG5cdFx0XHRcdFx0XHQvLyBSZXZlcnNlIHRhYmJpbmcgb3JkZXIgd2hlbiBzaGlmdCBrZXkgaXMgcHJlc3NlZFxuXHRcdFx0XHRcdFx0aWYgKGFjdGl2ZSA9PT0gZWxlbWVudHNbMF0pIHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHMubGFzdCgpLmZvY3VzKCk7XG5cdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAoYWN0aXZlID09PSBlbGVtZW50cy5sYXN0KClbMF0pIHtcblx0XHRcdFx0XHRcdFx0ZWxlbWVudHMuZmlyc3QoKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0fSwgMCk7XG5cdH1cbn0gKTtcblxuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICpcbiAqIFN0YXRpY3NcbiAqL1xuXG4vKipcbiAqIFNob3cgLyBoaWRlIGEgYmFja2dyb3VuZCBsYXllciBiZWhpbmQgYSBjb2xsZWN0aW9uXG4gKiBAcGFyYW0gIHtib29sZWFufSBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBiYWNrZ3JvdW5kIHNob3VsZCBiZSBzaG93biBvclxuICogICBoaWRkZW4gXG4gKiBAcGFyYW0gIHtzdHJpbmd9IENsYXNzIHRvIGFzc2lnbiB0byB0aGUgYmFja2dyb3VuZFxuICogQHN0YXRpY1xuICovXG5CdXR0b25zLmJhY2tncm91bmQgPSBmdW5jdGlvbiAoIHNob3csIGNsYXNzTmFtZSwgZmFkZSwgaW5zZXJ0UG9pbnQgKSB7XG5cdGlmICggZmFkZSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdGZhZGUgPSA0MDA7XG5cdH1cblx0aWYgKCAhIGluc2VydFBvaW50ICkge1xuXHRcdGluc2VydFBvaW50ID0gZG9jdW1lbnQuYm9keTtcblx0fVxuXG5cdGlmICggc2hvdyApIHtcblx0XHRfZmFkZUluKFxuXHRcdFx0JCgnPGRpdi8+Jylcblx0XHRcdFx0LmFkZENsYXNzKCBjbGFzc05hbWUgKVxuXHRcdFx0XHQuY3NzKCAnZGlzcGxheScsICdub25lJyApXG5cdFx0XHRcdC5pbnNlcnRBZnRlciggaW5zZXJ0UG9pbnQgKSxcblx0XHRcdGZhZGVcblx0XHQpO1xuXHR9XG5cdGVsc2Uge1xuXHRcdF9mYWRlT3V0KFxuXHRcdFx0JCgnZGl2LicrY2xhc3NOYW1lKSxcblx0XHRcdGZhZGUsXG5cdFx0XHRmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdCQodGhpcylcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoIGNsYXNzTmFtZSApXG5cdFx0XHRcdFx0LnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdCk7XG5cdH1cbn07XG5cbi8qKlxuICogSW5zdGFuY2Ugc2VsZWN0b3IgLSBzZWxlY3QgQnV0dG9ucyBpbnN0YW5jZXMgYmFzZWQgb24gYW4gaW5zdGFuY2Ugc2VsZWN0b3JcbiAqIHZhbHVlIGZyb20gdGhlIGJ1dHRvbnMgYXNzaWduZWQgdG8gYSBEYXRhVGFibGUuIFRoaXMgaXMgb25seSB1c2VmdWwgaWZcbiAqIG11bHRpcGxlIGluc3RhbmNlcyBhcmUgYXR0YWNoZWQgdG8gYSBEYXRhVGFibGUuXG4gKiBAcGFyYW0gIHtzdHJpbmd8aW50fGFycmF5fSBJbnN0YW5jZSBzZWxlY3RvciAtIHNlZSBgaW5zdGFuY2Utc2VsZWN0b3JgXG4gKiAgIGRvY3VtZW50YXRpb24gb24gdGhlIERhdGFUYWJsZXMgc2l0ZVxuICogQHBhcmFtICB7YXJyYXl9IEJ1dHRvbiBpbnN0YW5jZSBhcnJheSB0aGF0IHdhcyBhdHRhY2hlZCB0byB0aGUgRGF0YVRhYmxlc1xuICogICBzZXR0aW5ncyBvYmplY3RcbiAqIEByZXR1cm4ge2FycmF5fSBCdXR0b25zIGluc3RhbmNlc1xuICogQHN0YXRpY1xuICovXG5CdXR0b25zLmluc3RhbmNlU2VsZWN0b3IgPSBmdW5jdGlvbiAoIGdyb3VwLCBidXR0b25zIClcbntcblx0aWYgKCBncm91cCA9PT0gdW5kZWZpbmVkIHx8IGdyb3VwID09PSBudWxsICkge1xuXHRcdHJldHVybiAkLm1hcCggYnV0dG9ucywgZnVuY3Rpb24gKCB2ICkge1xuXHRcdFx0cmV0dXJuIHYuaW5zdDtcblx0XHR9ICk7XG5cdH1cblxuXHR2YXIgcmV0ID0gW107XG5cdHZhciBuYW1lcyA9ICQubWFwKCBidXR0b25zLCBmdW5jdGlvbiAoIHYgKSB7XG5cdFx0cmV0dXJuIHYubmFtZTtcblx0fSApO1xuXG5cdC8vIEZsYXR0ZW4gdGhlIGdyb3VwIHNlbGVjdG9yIGludG8gYW4gYXJyYXkgb2Ygc2luZ2xlIG9wdGlvbnNcblx0dmFyIHByb2Nlc3MgPSBmdW5jdGlvbiAoIGlucHV0ICkge1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggaW5wdXQgKSApIHtcblx0XHRcdGZvciAoIHZhciBpPTAsIGllbj1pbnB1dC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0cHJvY2VzcyggaW5wdXRbaV0gKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHRpZiAoIGlucHV0LmluZGV4T2YoICcsJyApICE9PSAtMSApIHtcblx0XHRcdFx0Ly8gU3RyaW5nIHNlbGVjdG9yLCBsaXN0IG9mIG5hbWVzXG5cdFx0XHRcdHByb2Nlc3MoIGlucHV0LnNwbGl0KCcsJykgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBTdHJpbmcgc2VsZWN0b3IgaW5kaXZpZHVhbCBuYW1lXG5cdFx0XHRcdHZhciBpZHggPSAkLmluQXJyYXkoIGlucHV0LnRyaW0oKSwgbmFtZXMgKTtcblxuXHRcdFx0XHRpZiAoIGlkeCAhPT0gLTEgKSB7XG5cdFx0XHRcdFx0cmV0LnB1c2goIGJ1dHRvbnNbIGlkeCBdLmluc3QgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJyApIHtcblx0XHRcdC8vIEluZGV4IHNlbGVjdG9yXG5cdFx0XHRyZXQucHVzaCggYnV0dG9uc1sgaW5wdXQgXS5pbnN0ICk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCB0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICkge1xuXHRcdFx0Ly8gQWN0dWFsIGluc3RhbmNlIHNlbGVjdG9yXG5cdFx0XHRyZXQucHVzaCggaW5wdXQgKTtcblx0XHR9XG5cdH07XG5cdFxuXHRwcm9jZXNzKCBncm91cCApO1xuXG5cdHJldHVybiByZXQ7XG59O1xuXG4vKipcbiAqIEJ1dHRvbiBzZWxlY3RvciAtIHNlbGVjdCBvbmUgb3IgbW9yZSBidXR0b25zIGZyb20gYSBzZWxlY3RvciBpbnB1dCBzbyBzb21lXG4gKiBvcGVyYXRpb24gY2FuIGJlIHBlcmZvcm1lZCBvbiB0aGVtLlxuICogQHBhcmFtICB7YXJyYXl9IEJ1dHRvbiBpbnN0YW5jZXMgYXJyYXkgdGhhdCB0aGUgc2VsZWN0b3Igc2hvdWxkIG9wZXJhdGUgb25cbiAqIEBwYXJhbSAge3N0cmluZ3xpbnR8bm9kZXxqUXVlcnl8YXJyYXl9IEJ1dHRvbiBzZWxlY3RvciAtIHNlZVxuICogICBgYnV0dG9uLXNlbGVjdG9yYCBkb2N1bWVudGF0aW9uIG9uIHRoZSBEYXRhVGFibGVzIHNpdGVcbiAqIEByZXR1cm4ge2FycmF5fSBBcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgYGluc3RgIGFuZCBgaWR4YCBwcm9wZXJ0aWVzIG9mXG4gKiAgIHRoZSBzZWxlY3RlZCBidXR0b25zIHNvIHlvdSBrbm93IHdoaWNoIGluc3RhbmNlIGVhY2ggYnV0dG9uIGJlbG9uZ3MgdG8uXG4gKiBAc3RhdGljXG4gKi9cbkJ1dHRvbnMuYnV0dG9uU2VsZWN0b3IgPSBmdW5jdGlvbiAoIGluc3RzLCBzZWxlY3RvciApXG57XG5cdHZhciByZXQgPSBbXTtcblx0dmFyIG5vZGVCdWlsZGVyID0gZnVuY3Rpb24gKCBhLCBidXR0b25zLCBiYXNlSWR4ICkge1xuXHRcdHZhciBidXR0b247XG5cdFx0dmFyIGlkeDtcblxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1idXR0b25zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0YnV0dG9uID0gYnV0dG9uc1tpXTtcblxuXHRcdFx0aWYgKCBidXR0b24gKSB7XG5cdFx0XHRcdGlkeCA9IGJhc2VJZHggIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdFx0YmFzZUlkeCtpIDpcblx0XHRcdFx0XHRpKycnO1xuXG5cdFx0XHRcdGEucHVzaCgge1xuXHRcdFx0XHRcdG5vZGU6IGJ1dHRvbi5ub2RlLFxuXHRcdFx0XHRcdG5hbWU6IGJ1dHRvbi5jb25mLm5hbWUsXG5cdFx0XHRcdFx0aWR4OiAgaWR4XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRpZiAoIGJ1dHRvbi5idXR0b25zICkge1xuXHRcdFx0XHRcdG5vZGVCdWlsZGVyKCBhLCBidXR0b24uYnV0dG9ucywgaWR4KyctJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdHZhciBydW4gPSBmdW5jdGlvbiAoIHNlbGVjdG9yLCBpbnN0ICkge1xuXHRcdHZhciBpLCBpZW47XG5cdFx0dmFyIGJ1dHRvbnMgPSBbXTtcblx0XHRub2RlQnVpbGRlciggYnV0dG9ucywgaW5zdC5zLmJ1dHRvbnMgKTtcblxuXHRcdHZhciBub2RlcyA9ICQubWFwKCBidXR0b25zLCBmdW5jdGlvbiAodikge1xuXHRcdFx0cmV0dXJuIHYubm9kZTtcblx0XHR9ICk7XG5cblx0XHRpZiAoIEFycmF5LmlzQXJyYXkoIHNlbGVjdG9yICkgfHwgc2VsZWN0b3IgaW5zdGFuY2VvZiAkICkge1xuXHRcdFx0Zm9yICggaT0wLCBpZW49c2VsZWN0b3IubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJ1biggc2VsZWN0b3JbaV0sIGluc3QgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yID09PSBudWxsIHx8IHNlbGVjdG9yID09PSB1bmRlZmluZWQgfHwgc2VsZWN0b3IgPT09ICcqJyApIHtcblx0XHRcdC8vIFNlbGVjdCBhbGxcblx0XHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdHJldC5wdXNoKCB7XG5cdFx0XHRcdFx0aW5zdDogaW5zdCxcblx0XHRcdFx0XHRub2RlOiBidXR0b25zW2ldLm5vZGVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIHNlbGVjdG9yID09PSAnbnVtYmVyJyApIHtcblx0XHRcdC8vIE1haW4gYnV0dG9uIGluZGV4IHNlbGVjdG9yXG5cdFx0XHRpZiAoaW5zdC5zLmJ1dHRvbnNbIHNlbGVjdG9yIF0pIHtcblx0XHRcdFx0cmV0LnB1c2goIHtcblx0XHRcdFx0XHRpbnN0OiBpbnN0LFxuXHRcdFx0XHRcdG5vZGU6IGluc3Qucy5idXR0b25zWyBzZWxlY3RvciBdLm5vZGVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIHNlbGVjdG9yID09PSAnc3RyaW5nJyApIHtcblx0XHRcdGlmICggc2VsZWN0b3IuaW5kZXhPZiggJywnICkgIT09IC0xICkge1xuXHRcdFx0XHQvLyBTcGxpdFxuXHRcdFx0XHR2YXIgYSA9IHNlbGVjdG9yLnNwbGl0KCcsJyk7XG5cblx0XHRcdFx0Zm9yICggaT0wLCBpZW49YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRydW4oIGFbaV0udHJpbSgpLCBpbnN0ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBzZWxlY3Rvci5tYXRjaCggL15cXGQrKFxcLVxcZCspKiQvICkgKSB7XG5cdFx0XHRcdC8vIFN1Yi1idXR0b24gaW5kZXggc2VsZWN0b3Jcblx0XHRcdFx0dmFyIGluZGV4ZXMgPSAkLm1hcCggYnV0dG9ucywgZnVuY3Rpb24gKHYpIHtcblx0XHRcdFx0XHRyZXR1cm4gdi5pZHg7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdGluc3Q6IGluc3QsXG5cdFx0XHRcdFx0bm9kZTogYnV0dG9uc1sgJC5pbkFycmF5KCBzZWxlY3RvciwgaW5kZXhlcyApIF0ubm9kZVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggc2VsZWN0b3IuaW5kZXhPZiggJzpuYW1lJyApICE9PSAtMSApIHtcblx0XHRcdFx0Ly8gQnV0dG9uIG5hbWUgc2VsZWN0b3Jcblx0XHRcdFx0dmFyIG5hbWUgPSBzZWxlY3Rvci5yZXBsYWNlKCAnOm5hbWUnLCAnJyApO1xuXG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBidXR0b25zW2ldLm5hbWUgPT09IG5hbWUgKSB7XG5cdFx0XHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRpbnN0OiBpbnN0LFxuXHRcdFx0XHRcdFx0XHRub2RlOiBidXR0b25zW2ldLm5vZGVcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBqUXVlcnkgc2VsZWN0b3Igb24gdGhlIG5vZGVzXG5cdFx0XHRcdCQoIG5vZGVzICkuZmlsdGVyKCBzZWxlY3RvciApLmVhY2goIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdFx0aW5zdDogaW5zdCxcblx0XHRcdFx0XHRcdG5vZGU6IHRoaXNcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHR5cGVvZiBzZWxlY3RvciA9PT0gJ29iamVjdCcgJiYgc2VsZWN0b3Iubm9kZU5hbWUgKSB7XG5cdFx0XHQvLyBOb2RlIHNlbGVjdG9yXG5cdFx0XHR2YXIgaWR4ID0gJC5pbkFycmF5KCBzZWxlY3Rvciwgbm9kZXMgKTtcblxuXHRcdFx0aWYgKCBpZHggIT09IC0xICkge1xuXHRcdFx0XHRyZXQucHVzaCgge1xuXHRcdFx0XHRcdGluc3Q6IGluc3QsXG5cdFx0XHRcdFx0bm9kZTogbm9kZXNbIGlkeCBdXG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblxuXHRmb3IgKCB2YXIgaT0wLCBpZW49aW5zdHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0dmFyIGluc3QgPSBpbnN0c1tpXTtcblxuXHRcdHJ1biggc2VsZWN0b3IsIGluc3QgKTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59O1xuXG4vKipcbiAqIERlZmF1bHQgZnVuY3Rpb24gdXNlZCBmb3IgZm9ybWF0dGluZyBvdXRwdXQgZGF0YS5cbiAqIEBwYXJhbSB7Kn0gc3RyIERhdGEgdG8gc3RyaXBcbiAqL1xuQnV0dG9ucy5zdHJpcERhdGEgPSBmdW5jdGlvbiAoIHN0ciwgY29uZmlnICkge1xuXHRpZiAoIHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnICkge1xuXHRcdHJldHVybiBzdHI7XG5cdH1cblxuXHQvLyBBbHdheXMgcmVtb3ZlIHNjcmlwdCB0YWdzXG5cdHN0ciA9IHN0ci5yZXBsYWNlKCAvPHNjcmlwdFxcYltePF0qKD86KD8hPFxcL3NjcmlwdD4pPFtePF0qKSo8XFwvc2NyaXB0Pi9naSwgJycgKTtcblxuXHQvLyBBbHdheXMgcmVtb3ZlIGNvbW1lbnRzXG5cdHN0ciA9IHN0ci5yZXBsYWNlKCAvPCFcXC1cXC0uKj9cXC1cXC0+L2csICcnICk7XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcuc3RyaXBIdG1sICkge1xuXHRcdHN0ciA9IHN0ci5yZXBsYWNlKCAvPFtePl0qPi9nLCAnJyApO1xuXHR9XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcudHJpbSApIHtcblx0XHRzdHIgPSBzdHIucmVwbGFjZSggL15cXHMrfFxccyskL2csICcnICk7XG5cdH1cblxuXHRpZiAoICEgY29uZmlnIHx8IGNvbmZpZy5zdHJpcE5ld2xpbmVzICkge1xuXHRcdHN0ciA9IHN0ci5yZXBsYWNlKCAvXFxuL2csICcgJyApO1xuXHR9XG5cblx0aWYgKCAhIGNvbmZpZyB8fCBjb25maWcuZGVjb2RlRW50aXRpZXMgKSB7XG5cdFx0X2V4cG9ydFRleHRhcmVhLmlubmVySFRNTCA9IHN0cjtcblx0XHRzdHIgPSBfZXhwb3J0VGV4dGFyZWEudmFsdWU7XG5cdH1cblxuXHRyZXR1cm4gc3RyO1xufTtcblxuXG4vKipcbiAqIEJ1dHRvbnMgZGVmYXVsdHMuIEZvciBmdWxsIGRvY3VtZW50YXRpb24sIHBsZWFzZSByZWZlciB0byB0aGUgZG9jcy9vcHRpb25cbiAqIGRpcmVjdG9yeSBvciB0aGUgRGF0YVRhYmxlcyBzaXRlLlxuICogQHR5cGUge09iamVjdH1cbiAqIEBzdGF0aWNcbiAqL1xuQnV0dG9ucy5kZWZhdWx0cyA9IHtcblx0YnV0dG9uczogWyAnY29weScsICdleGNlbCcsICdjc3YnLCAncGRmJywgJ3ByaW50JyBdLFxuXHRuYW1lOiAnbWFpbicsXG5cdHRhYkluZGV4OiAwLFxuXHRkb206IHtcblx0XHRjb250YWluZXI6IHtcblx0XHRcdHRhZzogJ2RpdicsXG5cdFx0XHRjbGFzc05hbWU6ICdkdC1idXR0b25zJ1xuXHRcdH0sXG5cdFx0Y29sbGVjdGlvbjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJydcblx0XHR9LFxuXHRcdGJ1dHRvbjoge1xuXHRcdFx0dGFnOiAnYnV0dG9uJyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ1dHRvbicsXG5cdFx0XHRhY3RpdmU6ICdhY3RpdmUnLFxuXHRcdFx0ZGlzYWJsZWQ6ICdkaXNhYmxlZCcsXG5cdFx0XHRzcGFjZXJDbGFzczogJydcblx0XHR9LFxuXHRcdGJ1dHRvbkxpbmVyOiB7XG5cdFx0XHR0YWc6ICdzcGFuJyxcblx0XHRcdGNsYXNzTmFtZTogJydcblx0XHR9LFxuXHRcdHNwbGl0OiB7XG5cdFx0XHR0YWc6ICdkaXYnLFxuXHRcdFx0Y2xhc3NOYW1lOiAnZHQtYnV0dG9uLXNwbGl0Jyxcblx0XHR9LFxuXHRcdHNwbGl0V3JhcHBlcjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ0bi1zcGxpdC13cmFwcGVyJyxcblx0XHR9LFxuXHRcdHNwbGl0RHJvcGRvd246IHtcblx0XHRcdHRhZzogJ2J1dHRvbicsXG5cdFx0XHR0ZXh0OiAnJiN4MjVCQzsnLFxuXHRcdFx0Y2xhc3NOYW1lOiAnZHQtYnRuLXNwbGl0LWRyb3AnLFxuXHRcdFx0YWxpZ246ICdzcGxpdC1yaWdodCcsXG5cdFx0XHRzcGxpdEFsaWduQ2xhc3M6ICdkdC1idXR0b24tc3BsaXQtbGVmdCdcblx0XHR9LFxuXHRcdHNwbGl0RHJvcGRvd25CdXR0b246IHtcblx0XHRcdHRhZzogJ2J1dHRvbicsXG5cdFx0XHRjbGFzc05hbWU6ICdkdC1idG4tc3BsaXQtZHJvcC1idXR0b24gZHQtYnV0dG9uJyxcblx0XHR9LFxuXHRcdHNwbGl0Q29sbGVjdGlvbjoge1xuXHRcdFx0dGFnOiAnZGl2Jyxcblx0XHRcdGNsYXNzTmFtZTogJ2R0LWJ1dHRvbi1zcGxpdC1jb2xsZWN0aW9uJyxcblx0XHR9XG5cdH1cbn07XG5cbi8qKlxuICogVmVyc2lvbiBpbmZvcm1hdGlvblxuICogQHR5cGUge3N0cmluZ31cbiAqIEBzdGF0aWNcbiAqL1xuQnV0dG9ucy52ZXJzaW9uID0gJzIuMi4zJztcblxuXG4kLmV4dGVuZCggX2R0QnV0dG9ucywge1xuXHRjb2xsZWN0aW9uOiB7XG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5jb2xsZWN0aW9uJywgJ0NvbGxlY3Rpb24nICk7XG5cdFx0fSxcblx0XHRjbGFzc05hbWU6ICdidXR0b25zLWNvbGxlY3Rpb24nLFxuXHRcdGNsb3NlQnV0dG9uOiBmYWxzZSxcblx0XHRpbml0OiBmdW5jdGlvbiAoIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdGJ1dHRvbi5hdHRyKCAnYXJpYS1leHBhbmRlZCcsIGZhbHNlICk7XG5cdFx0fSxcblx0XHRhY3Rpb246IGZ1bmN0aW9uICggZSwgZHQsIGJ1dHRvbiwgY29uZmlnICkge1xuXHRcdFx0aWYgKCBjb25maWcuX2NvbGxlY3Rpb24ucGFyZW50cygnYm9keScpLmxlbmd0aCApIHtcblx0XHRcdFx0dGhpcy5wb3BvdmVyKGZhbHNlLCBjb25maWcpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMucG9wb3Zlcihjb25maWcuX2NvbGxlY3Rpb24sIGNvbmZpZyk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFdoZW4gYWN0aXZhdGVkIHVzaW5nIGEga2V5IC0gYXV0byBmb2N1cyBvbiB0aGVcblx0XHRcdC8vIGZpcnN0IGl0ZW0gaW4gdGhlIHBvcG92ZXJcblx0XHRcdGlmIChlLnR5cGUgPT09ICdrZXlwcmVzcycpIHtcblx0XHRcdFx0JCgnYSwgYnV0dG9uJywgY29uZmlnLl9jb2xsZWN0aW9uKS5lcSgwKS5mb2N1cygpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0YXR0cjoge1xuXHRcdFx0J2FyaWEtaGFzcG9wdXAnOiAnZGlhbG9nJ1xuXHRcdH1cblx0XHQvLyBBbHNvIHRoZSBwb3BvdmVyIG9wdGlvbnMsIGRlZmluZWQgaW4gQnV0dG9ucy5wb3BvdmVyXG5cdH0sXG5cdHNwbGl0OiB7XG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5zcGxpdCcsICdTcGxpdCcgKTtcblx0XHR9LFxuXHRcdGNsYXNzTmFtZTogJ2J1dHRvbnMtc3BsaXQnLFxuXHRcdGNsb3NlQnV0dG9uOiBmYWxzZSxcblx0XHRpbml0OiBmdW5jdGlvbiAoIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdHJldHVybiBidXR0b24uYXR0ciggJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSApO1xuXHRcdH0sXG5cdFx0YWN0aW9uOiBmdW5jdGlvbiAoIGUsIGR0LCBidXR0b24sIGNvbmZpZyApIHtcblx0XHRcdHRoaXMucG9wb3Zlcihjb25maWcuX2NvbGxlY3Rpb24sIGNvbmZpZyk7XG5cdFx0fSxcblx0XHRhdHRyOiB7XG5cdFx0XHQnYXJpYS1oYXNwb3B1cCc6ICdkaWFsb2cnXG5cdFx0fVxuXHRcdC8vIEFsc28gdGhlIHBvcG92ZXIgb3B0aW9ucywgZGVmaW5lZCBpbiBCdXR0b25zLnBvcG92ZXJcblx0fSxcblx0Y29weTogZnVuY3Rpb24gKCBkdCwgY29uZiApIHtcblx0XHRpZiAoIF9kdEJ1dHRvbnMuY29weUh0bWw1ICkge1xuXHRcdFx0cmV0dXJuICdjb3B5SHRtbDUnO1xuXHRcdH1cblx0fSxcblx0Y3N2OiBmdW5jdGlvbiAoIGR0LCBjb25mICkge1xuXHRcdGlmICggX2R0QnV0dG9ucy5jc3ZIdG1sNSAmJiBfZHRCdXR0b25zLmNzdkh0bWw1LmF2YWlsYWJsZSggZHQsIGNvbmYgKSApIHtcblx0XHRcdHJldHVybiAnY3N2SHRtbDUnO1xuXHRcdH1cblx0fSxcblx0ZXhjZWw6IGZ1bmN0aW9uICggZHQsIGNvbmYgKSB7XG5cdFx0aWYgKCBfZHRCdXR0b25zLmV4Y2VsSHRtbDUgJiYgX2R0QnV0dG9ucy5leGNlbEh0bWw1LmF2YWlsYWJsZSggZHQsIGNvbmYgKSApIHtcblx0XHRcdHJldHVybiAnZXhjZWxIdG1sNSc7XG5cdFx0fVxuXHR9LFxuXHRwZGY6IGZ1bmN0aW9uICggZHQsIGNvbmYgKSB7XG5cdFx0aWYgKCBfZHRCdXR0b25zLnBkZkh0bWw1ICYmIF9kdEJ1dHRvbnMucGRmSHRtbDUuYXZhaWxhYmxlKCBkdCwgY29uZiApICkge1xuXHRcdFx0cmV0dXJuICdwZGZIdG1sNSc7XG5cdFx0fVxuXHR9LFxuXHRwYWdlTGVuZ3RoOiBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdHZhciBsZW5ndGhNZW51ID0gZHQuc2V0dGluZ3MoKVswXS5hTGVuZ3RoTWVudTtcblx0XHR2YXIgdmFscyA9IFtdO1xuXHRcdHZhciBsYW5nID0gW107XG5cdFx0dmFyIHRleHQgPSBmdW5jdGlvbiAoIGR0ICkge1xuXHRcdFx0cmV0dXJuIGR0LmkxOG4oICdidXR0b25zLnBhZ2VMZW5ndGgnLCB7XG5cdFx0XHRcdFwiLTFcIjogJ1Nob3cgYWxsIHJvd3MnLFxuXHRcdFx0XHRfOiAgICAnU2hvdyAlZCByb3dzJ1xuXHRcdFx0fSwgZHQucGFnZS5sZW4oKSApO1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0IGZvciBEYXRhVGFibGVzIDEueCAyRCBhcnJheVxuXHRcdGlmIChBcnJheS5pc0FycmF5KCBsZW5ndGhNZW51WzBdICkpIHtcblx0XHRcdHZhbHMgPSBsZW5ndGhNZW51WzBdO1xuXHRcdFx0bGFuZyA9IGxlbmd0aE1lbnVbMV07XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0Zm9yICh2YXIgaT0wIDsgaTxsZW5ndGhNZW51Lmxlbmd0aCA7IGkrKykge1xuXHRcdFx0XHR2YXIgb3B0aW9uID0gbGVuZ3RoTWVudVtpXTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0IGZvciBEYXRhVGFibGVzIDIgb2JqZWN0IGluIHRoZSBhcnJheVxuXHRcdFx0XHRpZiAoJC5pc1BsYWluT2JqZWN0KG9wdGlvbikpIHtcblx0XHRcdFx0XHR2YWxzLnB1c2gob3B0aW9uLnZhbHVlKTtcblx0XHRcdFx0XHRsYW5nLnB1c2gob3B0aW9uLmxhYmVsKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHR2YWxzLnB1c2gob3B0aW9uKTtcblx0XHRcdFx0XHRsYW5nLnB1c2gob3B0aW9uKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRleHRlbmQ6ICdjb2xsZWN0aW9uJyxcblx0XHRcdHRleHQ6IHRleHQsXG5cdFx0XHRjbGFzc05hbWU6ICdidXR0b25zLXBhZ2UtbGVuZ3RoJyxcblx0XHRcdGF1dG9DbG9zZTogdHJ1ZSxcblx0XHRcdGJ1dHRvbnM6ICQubWFwKCB2YWxzLCBmdW5jdGlvbiAoIHZhbCwgaSApIHtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHR0ZXh0OiBsYW5nW2ldLFxuXHRcdFx0XHRcdGNsYXNzTmFtZTogJ2J1dHRvbi1wYWdlLWxlbmd0aCcsXG5cdFx0XHRcdFx0YWN0aW9uOiBmdW5jdGlvbiAoIGUsIGR0ICkge1xuXHRcdFx0XHRcdFx0ZHQucGFnZS5sZW4oIHZhbCApLmRyYXcoKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGluaXQ6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdFx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFx0XHRcdFx0XHR2YXIgZm4gPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdHRoYXQuYWN0aXZlKCBkdC5wYWdlLmxlbigpID09PSB2YWwgKTtcblx0XHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRcdGR0Lm9uKCAnbGVuZ3RoLmR0Jytjb25mLm5hbWVzcGFjZSwgZm4gKTtcblx0XHRcdFx0XHRcdGZuKCk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRkZXN0cm95OiBmdW5jdGlvbiAoIGR0LCBub2RlLCBjb25mICkge1xuXHRcdFx0XHRcdFx0ZHQub2ZmKCAnbGVuZ3RoLmR0Jytjb25mLm5hbWVzcGFjZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblx0XHRcdH0gKSxcblx0XHRcdGluaXQ6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdHZhciB0aGF0ID0gdGhpcztcblx0XHRcdFx0ZHQub24oICdsZW5ndGguZHQnK2NvbmYubmFtZXNwYWNlLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dGhhdC50ZXh0KCBjb25mLnRleHQgKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fSxcblx0XHRcdGRlc3Ryb3k6IGZ1bmN0aW9uICggZHQsIG5vZGUsIGNvbmYgKSB7XG5cdFx0XHRcdGR0Lm9mZiggJ2xlbmd0aC5kdCcrY29uZi5uYW1lc3BhY2UgKTtcblx0XHRcdH1cblx0XHR9O1xuXHR9LFxuXHRzcGFjZXI6IHtcblx0XHRzdHlsZTogJ2VtcHR5Jyxcblx0XHRzcGFjZXI6IHRydWUsXG5cdFx0dGV4dDogZnVuY3Rpb24gKCBkdCApIHtcblx0XHRcdHJldHVybiBkdC5pMThuKCAnYnV0dG9ucy5zcGFjZXInLCAnJyApO1xuXHRcdH1cblx0fVxufSApO1xuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG4gKiBEYXRhVGFibGVzIEFQSVxuICpcbiAqIEZvciBjb21wbGV0ZSBkb2N1bWVudGF0aW9uLCBwbGVhc2UgcmVmZXIgdG8gdGhlIGRvY3MvYXBpIGRpcmVjdG9yeSBvciB0aGVcbiAqIERhdGFUYWJsZXMgc2l0ZVxuICovXG5cbi8vIEJ1dHRvbnMgZ3JvdXAgYW5kIGluZGl2aWR1YWwgYnV0dG9uIHNlbGVjdG9yXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpJywgZnVuY3Rpb24gKCBncm91cCwgc2VsZWN0b3IgKSB7XG5cdC8vIEFyZ3VtZW50IHNoaWZ0aW5nXG5cdGlmICggc2VsZWN0b3IgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzZWxlY3RvciA9IGdyb3VwO1xuXHRcdGdyb3VwID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0dGhpcy5zZWxlY3Rvci5idXR0b25Hcm91cCA9IGdyb3VwO1xuXG5cdHZhciByZXMgPSB0aGlzLml0ZXJhdG9yKCB0cnVlLCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRpZiAoIGN0eC5fYnV0dG9ucyApIHtcblx0XHRcdHJldHVybiBCdXR0b25zLmJ1dHRvblNlbGVjdG9yKFxuXHRcdFx0XHRCdXR0b25zLmluc3RhbmNlU2VsZWN0b3IoIGdyb3VwLCBjdHguX2J1dHRvbnMgKSxcblx0XHRcdFx0c2VsZWN0b3Jcblx0XHRcdCk7XG5cdFx0fVxuXHR9LCB0cnVlICk7XG5cblx0cmVzLl9ncm91cFNlbGVjdG9yID0gZ3JvdXA7XG5cdHJldHVybiByZXM7XG59ICk7XG5cbi8vIEluZGl2aWR1YWwgYnV0dG9uIHNlbGVjdG9yXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCknLCBmdW5jdGlvbiAoIGdyb3VwLCBzZWxlY3RvciApIHtcblx0Ly8ganVzdCBydW4gYnV0dG9ucygpIGFuZCB0cnVuY2F0ZVxuXHR2YXIgYnV0dG9ucyA9IHRoaXMuYnV0dG9ucyggZ3JvdXAsIHNlbGVjdG9yICk7XG5cblx0aWYgKCBidXR0b25zLmxlbmd0aCA+IDEgKSB7XG5cdFx0YnV0dG9ucy5zcGxpY2UoIDEsIGJ1dHRvbnMubGVuZ3RoICk7XG5cdH1cblxuXHRyZXR1cm4gYnV0dG9ucztcbn0gKTtcblxuLy8gQWN0aXZlIGJ1dHRvbnNcbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXJQbHVyYWwoICdidXR0b25zKCkuYWN0aXZlKCknLCAnYnV0dG9uKCkuYWN0aXZlKCknLCBmdW5jdGlvbiAoIGZsYWcgKSB7XG5cdGlmICggZmxhZyA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0XHRyZXR1cm4gc2V0Lmluc3QuYWN0aXZlKCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmFjdGl2ZSggc2V0Lm5vZGUsIGZsYWcgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgLyBzZXQgYnV0dG9uIGFjdGlvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5hY3Rpb24oKScsICdidXR0b24oKS5hY3Rpb24oKScsIGZ1bmN0aW9uICggYWN0aW9uICkge1xuXHRpZiAoIGFjdGlvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0XHRyZXR1cm4gc2V0Lmluc3QuYWN0aW9uKCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmFjdGlvbiggc2V0Lm5vZGUsIGFjdGlvbiApO1xuXHR9ICk7XG59ICk7XG5cbi8vIENvbGxlY3Rpb24gY29udHJvbFxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5jb2xsZWN0aW9uUmVidWlsZCgpJywgJ2J1dHRvbigpLmNvbGxlY3Rpb25SZWJ1aWxkKCknLCBmdW5jdGlvbiAoIGJ1dHRvbnMgKSB7XG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdGZvcih2YXIgaSA9IDA7IGkgPCBidXR0b25zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZih0eXBlb2YgYnV0dG9uc1tpXSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdFx0YnV0dG9uc1tpXS5wYXJlbnRDb25mID0gc2V0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRzZXQuaW5zdC5jb2xsZWN0aW9uUmVidWlsZCggc2V0Lm5vZGUsIGJ1dHRvbnMgKTtcblx0fSApO1xufSApO1xuXG4vLyBFbmFibGUgLyBkaXNhYmxlIGJ1dHRvbnNcbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXIoIFsnYnV0dG9ucygpLmVuYWJsZSgpJywgJ2J1dHRvbigpLmVuYWJsZSgpJ10sIGZ1bmN0aW9uICggZmxhZyApIHtcblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QuZW5hYmxlKCBzZXQubm9kZSwgZmxhZyApO1xuXHR9ICk7XG59ICk7XG5cbi8vIERpc2FibGUgYnV0dG9uc1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggWydidXR0b25zKCkuZGlzYWJsZSgpJywgJ2J1dHRvbigpLmRpc2FibGUoKSddLCBmdW5jdGlvbiAoKSB7XG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LmRpc2FibGUoIHNldC5ub2RlICk7XG5cdH0gKTtcbn0gKTtcblxuLy8gQnV0dG9uIGluZGV4XG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCkuaW5kZXgoKScsIGZ1bmN0aW9uICgpIHtcblx0dmFyIGlkeCA9IG51bGw7XG5cblx0dGhpcy5lYWNoKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHR2YXIgcmVzID0gc2V0Lmluc3QuaW5kZXgoIHNldC5ub2RlICk7XG5cblx0XHRpZiAocmVzICE9PSBudWxsKSB7XG5cdFx0XHRpZHggPSByZXM7XG5cdFx0fVxuXHR9ICk7XG5cblx0cmV0dXJuIGlkeDtcbn0gKTtcblxuLy8gR2V0IGJ1dHRvbiBub2Rlc1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5ub2RlcygpJywgJ2J1dHRvbigpLm5vZGUoKScsIGZ1bmN0aW9uICgpIHtcblx0dmFyIGpxID0gJCgpO1xuXG5cdC8vIGpRdWVyeSB3aWxsIGF1dG9tYXRpY2FsbHkgcmVkdWNlIGR1cGxpY2F0ZXMgdG8gYSBzaW5nbGUgZW50cnlcblx0JCggdGhpcy5lYWNoKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRqcSA9IGpxLmFkZCggc2V0Lmluc3Qubm9kZSggc2V0Lm5vZGUgKSApO1xuXHR9ICkgKTtcblxuXHRyZXR1cm4ganE7XG59ICk7XG5cbi8vIEdldCAvIHNldCBidXR0b24gcHJvY2Vzc2luZyBzdGF0ZVxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5wcm9jZXNzaW5nKCknLCAnYnV0dG9uKCkucHJvY2Vzc2luZygpJywgZnVuY3Rpb24gKCBmbGFnICkge1xuXHRpZiAoIGZsYWcgPT09IHVuZGVmaW5lZCApIHtcblx0XHRyZXR1cm4gdGhpcy5tYXAoIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdFx0cmV0dXJuIHNldC5pbnN0LnByb2Nlc3NpbmcoIHNldC5ub2RlICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QucHJvY2Vzc2luZyggc2V0Lm5vZGUsIGZsYWcgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgLyBzZXQgYnV0dG9uIHRleHQgKGkuZS4gdGhlIGJ1dHRvbiBsYWJlbHMpXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyUGx1cmFsKCAnYnV0dG9ucygpLnRleHQoKScsICdidXR0b24oKS50ZXh0KCknLCBmdW5jdGlvbiAoIGxhYmVsICkge1xuXHRpZiAoIGxhYmVsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRcdHJldHVybiBzZXQuaW5zdC50ZXh0KCBzZXQubm9kZSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uICggc2V0ICkge1xuXHRcdHNldC5pbnN0LnRleHQoIHNldC5ub2RlLCBsYWJlbCApO1xuXHR9ICk7XG59ICk7XG5cbi8vIFRyaWdnZXIgYSBidXR0b24ncyBhY3Rpb25cbkRhdGFUYWJsZS5BcGkucmVnaXN0ZXJQbHVyYWwoICdidXR0b25zKCkudHJpZ2dlcigpJywgJ2J1dHRvbigpLnRyaWdnZXIoKScsIGZ1bmN0aW9uICgpIHtcblx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3Qubm9kZSggc2V0Lm5vZGUgKS50cmlnZ2VyKCAnY2xpY2snICk7XG5cdH0gKTtcbn0gKTtcblxuLy8gQnV0dG9uIHJlc29sdmVyIHRvIHRoZSBwb3BvdmVyXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9uKCkucG9wb3ZlcigpJywgZnVuY3Rpb24gKGNvbnRlbnQsIG9wdGlvbnMpIHtcblx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbiAoIHNldCApIHtcblx0XHRyZXR1cm4gc2V0Lmluc3QuX3BvcG92ZXIoIGNvbnRlbnQsIHRoaXMuYnV0dG9uKHRoaXNbMF0ubm9kZSksIG9wdGlvbnMgKTtcblx0fSApO1xufSApO1xuXG4vLyBHZXQgdGhlIGNvbnRhaW5lciBlbGVtZW50c1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMoKS5jb250YWluZXJzKCknLCBmdW5jdGlvbiAoKSB7XG5cdHZhciBqcSA9ICQoKTtcblx0dmFyIGdyb3VwU2VsZWN0b3IgPSB0aGlzLl9ncm91cFNlbGVjdG9yO1xuXG5cdC8vIFdlIG5lZWQgdG8gdXNlIHRoZSBncm91cCBzZWxlY3RvciBkaXJlY3RseSwgc2luY2UgaWYgdGhlcmUgYXJlIG5vIGJ1dHRvbnNcblx0Ly8gdGhlIHJlc3VsdCBzZXQgd2lsbCBiZSBlbXB0eVxuXHR0aGlzLml0ZXJhdG9yKCB0cnVlLCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRpZiAoIGN0eC5fYnV0dG9ucyApIHtcblx0XHRcdHZhciBpbnN0cyA9IEJ1dHRvbnMuaW5zdGFuY2VTZWxlY3RvciggZ3JvdXBTZWxlY3RvciwgY3R4Ll9idXR0b25zICk7XG5cblx0XHRcdGZvciAoIHZhciBpPTAsIGllbj1pbnN0cy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0anEgPSBqcS5hZGQoIGluc3RzW2ldLmNvbnRhaW5lcigpICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9ICk7XG5cblx0cmV0dXJuIGpxO1xufSApO1xuXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpLmNvbnRhaW5lcigpJywgZnVuY3Rpb24gKCkge1xuXHQvLyBBUEkgbGV2ZWwgb2YgbmVzdGluZyBpcyBgYnV0dG9ucygpYCBzbyB3ZSBjYW4gemlwIGludG8gdGhlIGNvbnRhaW5lcnMgbWV0aG9kXG5cdHJldHVybiB0aGlzLmNvbnRhaW5lcnMoKS5lcSgwKTtcbn0gKTtcblxuLy8gQWRkIGEgbmV3IGJ1dHRvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbigpLmFkZCgpJywgZnVuY3Rpb24gKCBpZHgsIGNvbmYsIGRyYXcgKSB7XG5cdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cblx0Ly8gRG9uJ3QgdXNlIGB0aGlzYCBhcyBpdCBjb3VsZCBiZSBlbXB0eSAtIHNlbGVjdCB0aGUgaW5zdGFuY2VzIGRpcmVjdGx5XG5cdGlmICggY3R4Lmxlbmd0aCApIHtcblx0XHR2YXIgaW5zdCA9IEJ1dHRvbnMuaW5zdGFuY2VTZWxlY3RvciggdGhpcy5fZ3JvdXBTZWxlY3RvciwgY3R4WzBdLl9idXR0b25zICk7XG5cblx0XHRpZiAoIGluc3QubGVuZ3RoICkge1xuXHRcdFx0aW5zdFswXS5hZGQoIGNvbmYsIGlkeCAsIGRyYXcpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiB0aGlzLmJ1dHRvbiggdGhpcy5fZ3JvdXBTZWxlY3RvciwgaWR4ICk7XG59ICk7XG5cbi8vIERlc3Ryb3kgdGhlIGJ1dHRvbiBzZXRzIHNlbGVjdGVkXG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucygpLmRlc3Ryb3koKScsIGZ1bmN0aW9uICgpIHtcblx0dGhpcy5wbHVjayggJ2luc3QnICkudW5pcXVlKCkuZWFjaCggZnVuY3Rpb24gKCBpbnN0ICkge1xuXHRcdGluc3QuZGVzdHJveSgpO1xuXHR9ICk7XG5cblx0cmV0dXJuIHRoaXM7XG59ICk7XG5cbi8vIFJlbW92ZSBhIGJ1dHRvblxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbCggJ2J1dHRvbnMoKS5yZW1vdmUoKScsICdidXR0b25zKCkucmVtb3ZlKCknLCBmdW5jdGlvbiAoKSB7XG5cdHRoaXMuZWFjaCggZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0c2V0Lmluc3QucmVtb3ZlKCBzZXQubm9kZSApO1xuXHR9ICk7XG5cblx0cmV0dXJuIHRoaXM7XG59ICk7XG5cbi8vIEluZm9ybWF0aW9uIGJveCB0aGF0IGNhbiBiZSB1c2VkIGJ5IGJ1dHRvbnNcbnZhciBfaW5mb1RpbWVyO1xuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMuaW5mbygpJywgZnVuY3Rpb24gKCB0aXRsZSwgbWVzc2FnZSwgdGltZSApIHtcblx0dmFyIHRoYXQgPSB0aGlzO1xuXG5cdGlmICggdGl0bGUgPT09IGZhbHNlICkge1xuXHRcdHRoaXMub2ZmKCdkZXN0cm95LmJ0bi1pbmZvJyk7XG5cdFx0X2ZhZGVPdXQoXG5cdFx0XHQkKCcjZGF0YXRhYmxlc19idXR0b25zX2luZm8nKSxcblx0XHRcdDQwMCxcblx0XHRcdGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0JCh0aGlzKS5yZW1vdmUoKTtcblx0XHRcdH1cblx0XHQpO1xuXHRcdGNsZWFyVGltZW91dCggX2luZm9UaW1lciApO1xuXHRcdF9pbmZvVGltZXIgPSBudWxsO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRpZiAoIF9pbmZvVGltZXIgKSB7XG5cdFx0Y2xlYXJUaW1lb3V0KCBfaW5mb1RpbWVyICk7XG5cdH1cblxuXHRpZiAoICQoJyNkYXRhdGFibGVzX2J1dHRvbnNfaW5mbycpLmxlbmd0aCApIHtcblx0XHQkKCcjZGF0YXRhYmxlc19idXR0b25zX2luZm8nKS5yZW1vdmUoKTtcblx0fVxuXG5cdHRpdGxlID0gdGl0bGUgPyAnPGgyPicrdGl0bGUrJzwvaDI+JyA6ICcnO1xuXG5cdF9mYWRlSW4oXG5cdFx0JCgnPGRpdiBpZD1cImRhdGF0YWJsZXNfYnV0dG9uc19pbmZvXCIgY2xhc3M9XCJkdC1idXR0b24taW5mb1wiLz4nKVxuXHRcdFx0Lmh0bWwoIHRpdGxlIClcblx0XHRcdC5hcHBlbmQoICQoJzxkaXYvPicpWyB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyAnaHRtbCcgOiAnYXBwZW5kJyBdKCBtZXNzYWdlICkgKVxuXHRcdFx0LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKVxuXHRcdFx0LmFwcGVuZFRvKCAnYm9keScgKVxuXHQpO1xuXG5cdGlmICggdGltZSAhPT0gdW5kZWZpbmVkICYmIHRpbWUgIT09IDAgKSB7XG5cdFx0X2luZm9UaW1lciA9IHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpIHtcblx0XHRcdHRoYXQuYnV0dG9ucy5pbmZvKCBmYWxzZSApO1xuXHRcdH0sIHRpbWUgKTtcblx0fVxuXG5cdHRoaXMub24oJ2Rlc3Ryb3kuYnRuLWluZm8nLCBmdW5jdGlvbiAoKSB7XG5cdFx0dGhhdC5idXR0b25zLmluZm8oZmFsc2UpO1xuXHR9KTtcblxuXHRyZXR1cm4gdGhpcztcbn0gKTtcblxuLy8gR2V0IGRhdGEgZnJvbSB0aGUgdGFibGUgZm9yIGV4cG9ydCAtIHRoaXMgaXMgY29tbW9uIHRvIGEgbnVtYmVyIG9mIHBsdWctaW5cbi8vIGJ1dHRvbnMgc28gaXQgaXMgaW5jbHVkZWQgaW4gdGhlIEJ1dHRvbnMgY29yZSBsaWJyYXJ5XG5EYXRhVGFibGUuQXBpLnJlZ2lzdGVyKCAnYnV0dG9ucy5leHBvcnREYXRhKCknLCBmdW5jdGlvbiAoIG9wdGlvbnMgKSB7XG5cdGlmICggdGhpcy5jb250ZXh0Lmxlbmd0aCApIHtcblx0XHRyZXR1cm4gX2V4cG9ydERhdGEoIG5ldyBEYXRhVGFibGUuQXBpKCB0aGlzLmNvbnRleHRbMF0gKSwgb3B0aW9ucyApO1xuXHR9XG59ICk7XG5cbi8vIEdldCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXhwb3J0IHRoYXQgaXMgY29tbW9uIHRvIG1hbnkgb2YgdGhlIGV4cG9ydCBkYXRhXG4vLyB0eXBlcyAoRFJZKVxuRGF0YVRhYmxlLkFwaS5yZWdpc3RlciggJ2J1dHRvbnMuZXhwb3J0SW5mbygpJywgZnVuY3Rpb24gKCBjb25mICkge1xuXHRpZiAoICEgY29uZiApIHtcblx0XHRjb25mID0ge307XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdGZpbGVuYW1lOiBfZmlsZW5hbWUoIGNvbmYgKSxcblx0XHR0aXRsZTogX3RpdGxlKCBjb25mICksXG5cdFx0bWVzc2FnZVRvcDogX21lc3NhZ2UodGhpcywgY29uZi5tZXNzYWdlIHx8IGNvbmYubWVzc2FnZVRvcCwgJ3RvcCcpLFxuXHRcdG1lc3NhZ2VCb3R0b206IF9tZXNzYWdlKHRoaXMsIGNvbmYubWVzc2FnZUJvdHRvbSwgJ2JvdHRvbScpXG5cdH07XG59ICk7XG5cblxuXG4vKipcbiAqIEdldCB0aGUgZmlsZSBuYW1lIGZvciBhbiBleHBvcnRlZCBmaWxlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fVx0Y29uZmlnIEJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGluY0V4dGVuc2lvbiBJbmNsdWRlIHRoZSBmaWxlIG5hbWUgZXh0ZW5zaW9uXG4gKi9cbnZhciBfZmlsZW5hbWUgPSBmdW5jdGlvbiAoIGNvbmZpZyApXG57XG5cdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG5cdHZhciBmaWxlbmFtZSA9IGNvbmZpZy5maWxlbmFtZSA9PT0gJyonICYmIGNvbmZpZy50aXRsZSAhPT0gJyonICYmIGNvbmZpZy50aXRsZSAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy50aXRsZSAhPT0gbnVsbCAmJiBjb25maWcudGl0bGUgIT09ICcnID9cblx0XHRjb25maWcudGl0bGUgOlxuXHRcdGNvbmZpZy5maWxlbmFtZTtcblxuXHRpZiAoIHR5cGVvZiBmaWxlbmFtZSA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRmaWxlbmFtZSA9IGZpbGVuYW1lKCk7XG5cdH1cblxuXHRpZiAoIGZpbGVuYW1lID09PSB1bmRlZmluZWQgfHwgZmlsZW5hbWUgPT09IG51bGwgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHRpZiAoIGZpbGVuYW1lLmluZGV4T2YoICcqJyApICE9PSAtMSApIHtcblx0XHRmaWxlbmFtZSA9IGZpbGVuYW1lLnJlcGxhY2UoICcqJywgJCgnaGVhZCA+IHRpdGxlJykudGV4dCgpICkudHJpbSgpO1xuXHR9XG5cblx0Ly8gU3RyaXAgY2hhcmFjdGVycyB3aGljaCB0aGUgT1Mgd2lsbCBvYmplY3QgdG9cblx0ZmlsZW5hbWUgPSBmaWxlbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOV9cXHUwMEExLVxcdUZGRkZcXC4sXFwtXyAhXFwoXFwpXS9nLCBcIlwiKTtcblxuXHR2YXIgZXh0ZW5zaW9uID0gX3N0cmluZ09yRnVuY3Rpb24oIGNvbmZpZy5leHRlbnNpb24gKTtcblx0aWYgKCAhIGV4dGVuc2lvbiApIHtcblx0XHRleHRlbnNpb24gPSAnJztcblx0fVxuXG5cdHJldHVybiBmaWxlbmFtZSArIGV4dGVuc2lvbjtcbn07XG5cbi8qKlxuICogU2ltcGx5IHV0aWxpdHkgbWV0aG9kIHRvIGFsbG93IHBhcmFtZXRlcnMgdG8gYmUgZ2l2ZW4gYXMgYSBmdW5jdGlvblxuICpcbiAqIEBwYXJhbSB7dW5kZWZpbmVkfHN0cmluZ3xmdW5jdGlvbn0gb3B0aW9uIE9wdGlvblxuICogQHJldHVybiB7bnVsbHxzdHJpbmd9IFJlc29sdmVkIHZhbHVlXG4gKi9cbnZhciBfc3RyaW5nT3JGdW5jdGlvbiA9IGZ1bmN0aW9uICggb3B0aW9uIClcbntcblx0aWYgKCBvcHRpb24gPT09IG51bGwgfHwgb3B0aW9uID09PSB1bmRlZmluZWQgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0ZWxzZSBpZiAoIHR5cGVvZiBvcHRpb24gPT09ICdmdW5jdGlvbicgKSB7XG5cdFx0cmV0dXJuIG9wdGlvbigpO1xuXHR9XG5cdHJldHVybiBvcHRpb247XG59O1xuXG4vKipcbiAqIEdldCB0aGUgdGl0bGUgZm9yIGFuIGV4cG9ydGVkIGZpbGUuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1x0QnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqL1xudmFyIF90aXRsZSA9IGZ1bmN0aW9uICggY29uZmlnIClcbntcblx0dmFyIHRpdGxlID0gX3N0cmluZ09yRnVuY3Rpb24oIGNvbmZpZy50aXRsZSApO1xuXG5cdHJldHVybiB0aXRsZSA9PT0gbnVsbCA/XG5cdFx0bnVsbCA6IHRpdGxlLmluZGV4T2YoICcqJyApICE9PSAtMSA/XG5cdFx0XHR0aXRsZS5yZXBsYWNlKCAnKicsICQoJ2hlYWQgPiB0aXRsZScpLnRleHQoKSB8fCAnRXhwb3J0ZWQgZGF0YScgKSA6XG5cdFx0XHR0aXRsZTtcbn07XG5cbnZhciBfbWVzc2FnZSA9IGZ1bmN0aW9uICggZHQsIG9wdGlvbiwgcG9zaXRpb24gKVxue1xuXHR2YXIgbWVzc2FnZSA9IF9zdHJpbmdPckZ1bmN0aW9uKCBvcHRpb24gKTtcblx0aWYgKCBtZXNzYWdlID09PSBudWxsICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0dmFyIGNhcHRpb24gPSAkKCdjYXB0aW9uJywgZHQudGFibGUoKS5jb250YWluZXIoKSkuZXEoMCk7XG5cdGlmICggbWVzc2FnZSA9PT0gJyonICkge1xuXHRcdHZhciBzaWRlID0gY2FwdGlvbi5jc3MoICdjYXB0aW9uLXNpZGUnICk7XG5cdFx0aWYgKCBzaWRlICE9PSBwb3NpdGlvbiApIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdHJldHVybiBjYXB0aW9uLmxlbmd0aCA/XG5cdFx0XHRjYXB0aW9uLnRleHQoKSA6XG5cdFx0XHQnJztcblx0fVxuXG5cdHJldHVybiBtZXNzYWdlO1xufTtcblxuXG5cblxudmFyIF9leHBvcnRUZXh0YXJlYSA9ICQoJzx0ZXh0YXJlYS8+JylbMF07XG52YXIgX2V4cG9ydERhdGEgPSBmdW5jdGlvbiAoIGR0LCBpbk9wdHMgKVxue1xuXHR2YXIgY29uZmlnID0gJC5leHRlbmQoIHRydWUsIHt9LCB7XG5cdFx0cm93czogICAgICAgICAgIG51bGwsXG5cdFx0Y29sdW1uczogICAgICAgICcnLFxuXHRcdG1vZGlmaWVyOiAgICAgICB7XG5cdFx0XHRzZWFyY2g6ICdhcHBsaWVkJyxcblx0XHRcdG9yZGVyOiAgJ2FwcGxpZWQnXG5cdFx0fSxcblx0XHRvcnRob2dvbmFsOiAgICAgJ2Rpc3BsYXknLFxuXHRcdHN0cmlwSHRtbDogICAgICB0cnVlLFxuXHRcdHN0cmlwTmV3bGluZXM6ICB0cnVlLFxuXHRcdGRlY29kZUVudGl0aWVzOiB0cnVlLFxuXHRcdHRyaW06ICAgICAgICAgICB0cnVlLFxuXHRcdGZvcm1hdDogICAgICAgICB7XG5cdFx0XHRoZWFkZXI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0cmV0dXJuIEJ1dHRvbnMuc3RyaXBEYXRhKCBkLCBjb25maWcgKTtcblx0XHRcdH0sXG5cdFx0XHRmb290ZXI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0cmV0dXJuIEJ1dHRvbnMuc3RyaXBEYXRhKCBkLCBjb25maWcgKTtcblx0XHRcdH0sXG5cdFx0XHRib2R5OiBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0XHRcdHJldHVybiBCdXR0b25zLnN0cmlwRGF0YSggZCwgY29uZmlnICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRjdXN0b21pemVEYXRhOiBudWxsXG5cdH0sIGluT3B0cyApO1xuXG5cdHZhciBoZWFkZXIgPSBkdC5jb2x1bW5zKCBjb25maWcuY29sdW1ucyApLmluZGV4ZXMoKS5tYXAoIGZ1bmN0aW9uIChpZHgpIHtcblx0XHR2YXIgZWwgPSBkdC5jb2x1bW4oIGlkeCApLmhlYWRlcigpO1xuXHRcdHJldHVybiBjb25maWcuZm9ybWF0LmhlYWRlciggZWwuaW5uZXJIVE1MLCBpZHgsIGVsICk7XG5cdH0gKS50b0FycmF5KCk7XG5cblx0dmFyIGZvb3RlciA9IGR0LnRhYmxlKCkuZm9vdGVyKCkgP1xuXHRcdGR0LmNvbHVtbnMoIGNvbmZpZy5jb2x1bW5zICkuaW5kZXhlcygpLm1hcCggZnVuY3Rpb24gKGlkeCkge1xuXHRcdFx0dmFyIGVsID0gZHQuY29sdW1uKCBpZHggKS5mb290ZXIoKTtcblx0XHRcdHJldHVybiBjb25maWcuZm9ybWF0LmZvb3RlciggZWwgPyBlbC5pbm5lckhUTUwgOiAnJywgaWR4LCBlbCApO1xuXHRcdH0gKS50b0FycmF5KCkgOlxuXHRcdG51bGw7XG5cdFxuXHQvLyBJZiBTZWxlY3QgaXMgYXZhaWxhYmxlIG9uIHRoaXMgdGFibGUsIGFuZCBhbnkgcm93cyBhcmUgc2VsZWN0ZWQsIGxpbWl0IHRoZSBleHBvcnRcblx0Ly8gdG8gdGhlIHNlbGVjdGVkIHJvd3MuIElmIG5vIHJvd3MgYXJlIHNlbGVjdGVkLCBhbGwgcm93cyB3aWxsIGJlIGV4cG9ydGVkLiBTcGVjaWZ5XG5cdC8vIGEgYHNlbGVjdGVkYCBtb2RpZmllciB0byBjb250cm9sIGRpcmVjdGx5LlxuXHR2YXIgbW9kaWZpZXIgPSAkLmV4dGVuZCgge30sIGNvbmZpZy5tb2RpZmllciApO1xuXHRpZiAoIGR0LnNlbGVjdCAmJiB0eXBlb2YgZHQuc2VsZWN0LmluZm8gPT09ICdmdW5jdGlvbicgJiYgbW9kaWZpZXIuc2VsZWN0ZWQgPT09IHVuZGVmaW5lZCApIHtcblx0XHRpZiAoIGR0LnJvd3MoIGNvbmZpZy5yb3dzLCAkLmV4dGVuZCggeyBzZWxlY3RlZDogdHJ1ZSB9LCBtb2RpZmllciApICkuYW55KCkgKSB7XG5cdFx0XHQkLmV4dGVuZCggbW9kaWZpZXIsIHsgc2VsZWN0ZWQ6IHRydWUgfSApXG5cdFx0fVxuXHR9XG5cblx0dmFyIHJvd0luZGV4ZXMgPSBkdC5yb3dzKCBjb25maWcucm93cywgbW9kaWZpZXIgKS5pbmRleGVzKCkudG9BcnJheSgpO1xuXHR2YXIgc2VsZWN0ZWRDZWxscyA9IGR0LmNlbGxzKCByb3dJbmRleGVzLCBjb25maWcuY29sdW1ucyApO1xuXHR2YXIgY2VsbHMgPSBzZWxlY3RlZENlbGxzXG5cdFx0LnJlbmRlciggY29uZmlnLm9ydGhvZ29uYWwgKVxuXHRcdC50b0FycmF5KCk7XG5cdHZhciBjZWxsTm9kZXMgPSBzZWxlY3RlZENlbGxzXG5cdFx0Lm5vZGVzKClcblx0XHQudG9BcnJheSgpO1xuXG5cdHZhciBjb2x1bW5zID0gaGVhZGVyLmxlbmd0aDtcblx0dmFyIHJvd3MgPSBjb2x1bW5zID4gMCA/IGNlbGxzLmxlbmd0aCAvIGNvbHVtbnMgOiAwO1xuXHR2YXIgYm9keSA9IFtdO1xuXHR2YXIgY2VsbENvdW50ZXIgPSAwO1xuXG5cdGZvciAoIHZhciBpPTAsIGllbj1yb3dzIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0dmFyIHJvdyA9IFsgY29sdW1ucyBdO1xuXG5cdFx0Zm9yICggdmFyIGo9MCA7IGo8Y29sdW1ucyA7IGorKyApIHtcblx0XHRcdHJvd1tqXSA9IGNvbmZpZy5mb3JtYXQuYm9keSggY2VsbHNbIGNlbGxDb3VudGVyIF0sIGksIGosIGNlbGxOb2Rlc1sgY2VsbENvdW50ZXIgXSApO1xuXHRcdFx0Y2VsbENvdW50ZXIrKztcblx0XHR9XG5cblx0XHRib2R5W2ldID0gcm93O1xuXHR9XG5cblx0dmFyIGRhdGEgPSB7XG5cdFx0aGVhZGVyOiBoZWFkZXIsXG5cdFx0Zm9vdGVyOiBmb290ZXIsXG5cdFx0Ym9keTogICBib2R5XG5cdH07XG5cblx0aWYgKCBjb25maWcuY3VzdG9taXplRGF0YSApIHtcblx0XHRjb25maWcuY3VzdG9taXplRGF0YSggZGF0YSApO1xuXHR9XG5cblx0cmV0dXJuIGRhdGE7XG59O1xuXG5cbi8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG4gKiBEYXRhVGFibGVzIGludGVyZmFjZVxuICovXG5cbi8vIEF0dGFjaCB0byBEYXRhVGFibGVzIG9iamVjdHMgZm9yIGdsb2JhbCBhY2Nlc3NcbiQuZm4uZGF0YVRhYmxlLkJ1dHRvbnMgPSBCdXR0b25zO1xuJC5mbi5EYXRhVGFibGUuQnV0dG9ucyA9IEJ1dHRvbnM7XG5cblxuXG4vLyBEYXRhVGFibGVzIGNyZWF0aW9uIC0gY2hlY2sgaWYgdGhlIGJ1dHRvbnMgaGF2ZSBiZWVuIGRlZmluZWQgZm9yIHRoaXMgdGFibGUsXG4vLyB0aGV5IHdpbGwgaGF2ZSBiZWVuIGlmIHRoZSBgQmAgb3B0aW9uIHdhcyB1c2VkIGluIGBkb21gLCBvdGhlcndpc2Ugd2Ugc2hvdWxkXG4vLyBjcmVhdGUgdGhlIGJ1dHRvbnMgaW5zdGFuY2UgaGVyZSBzbyB0aGV5IGNhbiBiZSBpbnNlcnRlZCBpbnRvIHRoZSBkb2N1bWVudFxuLy8gdXNpbmcgdGhlIEFQSS4gTGlzdGVuIGZvciBgaW5pdGAgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBwcmUgMS4xMC4xMCwgYnV0IHRvXG4vLyBiZSByZW1vdmVkIGluIGZ1dHVyZS5cbiQoZG9jdW1lbnQpLm9uKCAnaW5pdC5kdCBwbHVnaW4taW5pdC5kdCcsIGZ1bmN0aW9uIChlLCBzZXR0aW5ncykge1xuXHRpZiAoIGUubmFtZXNwYWNlICE9PSAnZHQnICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdHZhciBvcHRzID0gc2V0dGluZ3Mub0luaXQuYnV0dG9ucyB8fCBEYXRhVGFibGUuZGVmYXVsdHMuYnV0dG9ucztcblxuXHRpZiAoIG9wdHMgJiYgISBzZXR0aW5ncy5fYnV0dG9ucyApIHtcblx0XHRuZXcgQnV0dG9ucyggc2V0dGluZ3MsIG9wdHMgKS5jb250YWluZXIoKTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBfaW5pdCAoIHNldHRpbmdzLCBvcHRpb25zICkge1xuXHR2YXIgYXBpID0gbmV3IERhdGFUYWJsZS5BcGkoIHNldHRpbmdzICk7XG5cdHZhciBvcHRzID0gb3B0aW9uc1xuXHRcdD8gb3B0aW9uc1xuXHRcdDogYXBpLmluaXQoKS5idXR0b25zIHx8IERhdGFUYWJsZS5kZWZhdWx0cy5idXR0b25zO1xuXG5cdHJldHVybiBuZXcgQnV0dG9ucyggYXBpLCBvcHRzICkuY29udGFpbmVyKCk7XG59XG5cbi8vIERhdGFUYWJsZXMgYGRvbWAgZmVhdHVyZSBvcHRpb25cbkRhdGFUYWJsZS5leHQuZmVhdHVyZS5wdXNoKCB7XG5cdGZuSW5pdDogX2luaXQsXG5cdGNGZWF0dXJlOiBcIkJcIlxufSApO1xuXG4vLyBEYXRhVGFibGVzIDIgbGF5b3V0IGZlYXR1cmVcbmlmICggRGF0YVRhYmxlLmV4dC5mZWF0dXJlcyApIHtcblx0RGF0YVRhYmxlLmV4dC5mZWF0dXJlcy5yZWdpc3RlciggJ2J1dHRvbnMnLCBfaW5pdCApO1xufVxuXG5cbnJldHVybiBCdXR0b25zO1xufSkpO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/dataTables.buttons.js\n"); /***/ }), /***/ "datatables.net": /*!*********************************!*\ !*** external "$.fn.dataTable" ***! \*********************************/ /***/ (function(module) { "use strict"; module.exports = window["$.fn.dataTable"]; /***/ }), /***/ "jquery": /*!*************************!*\ !*** external "jQuery" ***! \*************************/ /***/ (function(module) { "use strict"; module.exports = window["jQuery"]; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ !function() { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function() { return module['default']; } : /******/ function() { return module; }; /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ !function() { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = function(exports, definition) { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !function() { /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /******/ }(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ !function() { /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ }(); /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module can't be inlined because the eval-source-map devtool is used. /******/ var __webpack_exports__ = __webpack_require__("./libs/datatables-buttons/buttons.html5.js"); /******/ var __webpack_export_target__ = window; /******/ for(var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i]; /******/ if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true }); /******/ /******/ })() ;
SIMPAN PERUBAHAN